获取视图模型中的选定选项卡 (wpf)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27263318/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get the selected tab in the view model (wpf)
提问by nan
I have one main view which has a tab control. When a tab is selected, it calls the appropriate view to display. I have a function in view model which has to know which tab was selected to preform an operation. How do I achieve this? How will the view model know which tab is selected?
我有一个带有选项卡控件的主视图。当一个选项卡被选中时,它会调用适当的视图来显示。我在视图模型中有一个函数,它必须知道选择了哪个选项卡来执行操作。我如何实现这一目标?视图模型如何知道选择了哪个选项卡?
回答by Sinaesthetic
Quite simply:
很简单:
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication2"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<local:TestViewModel x:Key="MainViewModel"/>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<TabControl DataContext="{StaticResource MainViewModel}"
SelectedIndex="{Binding Selected}"
Grid.Row="0"
x:Name="TestTabs">
<TabItem Header="Section 1"/>
<TabItem Header="Section 2"/>
<TabItem Header="Section 3"/>
</TabControl>
<Button Content="Check
Selected Index"
Grid.Row="1"
x:Name="TestButton"
Click="TestButton_OnClick"/>
</Grid>
</Window>
The model is defined here, declaratively, as a data context. The selectedindex property is bound to the model so any time it changes, the propery it is mapped to on the view model will also change
该模型在此处以声明方式定义为数据上下文。selectedindex 属性绑定到模型,因此任何时候它更改,它映射到视图模型上的属性也将更改
class TestViewModel : INotifyPropertyChanged
{
private int _selected;
public int Selected
{
get { return _selected; }
set
{
_selected = value;
OnPropertyChanged("Selected");
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string property)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
}
This implements INotifyPropertyChanged so the view will register with it. In the handler here, I output the value of Selected to show the as you change them.
这实现了 INotifyPropertyChanged,因此视图将向其注册。在此处的处理程序中,我输出 Selected 的值以在您更改它们时显示 。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TestButton_OnClick(object sender, RoutedEventArgs e)
{
var vm = TestTabs.DataContext as TestViewModel;
MessageBox.Show(string.Format("You selected tab {0}", vm.Selected));
}
}
This gets the viewmodel and then shows us that the properties were in fact updated.
这将获取视图模型,然后向我们显示属性实际上已更新。
回答by apo
In View, you put SelectedIndex property on TabControl:
在 View 中,您将 SelectedIndex 属性放在 TabControl 上:
xmlns:cal="http://www.caliburnproject.org"
<TabControl cal:Message.Attach="[SelectionChanged] = [OnTabSelectionChanged()]"
SelectedIndex="{Binding SelectedIndexTab}">
<TabItem Header="Tab 1"/>
<TabItem Header="Tab 2"/>
</TabControl>
In ViewModel, you declare a public property name SelectedIndexTaband OnTabSelectionChanged()method to operate.
在 ViewModel 中,您声明了一个公共属性名称SelectedIndexTab和OnTabSelectionChanged()方法来进行操作。
public int SelectedIndexTab { get; set; }
In this example, I use Caliburn to catch SelectionChange event of TabControl.
在这个例子中,我使用 Caliburn 来捕捉 TabControl 的 SelectionChange 事件。
回答by Andrew
You can use the SelectionChanged event provided by the Selector base class. The SelectionChangedEventArgs will contain the newly selected (and deselected) items. Alternatively, you can bind the SelectedItem of the Selector Base class to a property in your ViewModel, and then perform some logic in the setter.
您可以使用 Selector 基类提供的 SelectionChanged 事件。SelectionChangedEventArgs 将包含新选择(和取消选择)的项目。或者,您可以将 Selector Base 类的 SelectedItem 绑定到 ViewModel 中的一个属性,然后在 setter 中执行一些逻辑。
Generally though, it's considered a violation of MVVM to pass view-specific objects to your ViewModels - it tightly couples the UI framework (WPF in this case) to the more generic ViewModel logic. A better route is to put event handlers in your UI code-behind which in turn act on the view-model appropriately, but without passing View objects as parameters.
不过,一般而言,将特定于视图的对象传递给您的 ViewModel 被认为是违反 MVVM 的——它将 UI 框架(在本例中为 WPF)与更通用的 ViewModel 逻辑紧密耦合。更好的方法是将事件处理程序放在你的 UI 代码隐藏中,它反过来适当地作用于视图模型,但不将 View 对象作为参数传递。
回答by Abhinav Sharma
Here is a simple example.
这是一个简单的例子。
You should be binding the ItemsSource of the Tab to your ObservableCollection, and that should hold models with information about the tabs that should be created.
您应该将选项卡的 ItemsSource 绑定到您的 ObservableCollection,并且该模型应该包含有关应该创建的选项卡的信息的模型。
Here are the VM and the model which represents a tab page:
以下是代表标签页的 VM 和模型:
public class ViewModel
{
public ObservableCollection<TabItem> Tabs { get; set; }
public ViewModel()
{
Tabs = new ObservableCollection<TabItem>();
Tabs.Add(new TabItem { Header = "One", Content = "One's content" });
Tabs.Add(new TabItem { Header = "Two", Content = "Two's content" });
}
}
public class TabItem
{
public string Header { get; set; }
public string Content { get; set; }
}
Here`s the View and VM binding
这是 View 和 VM 绑定
<Window x:Class="WpfApplication12.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<ViewModel
xmlns="clr-namespace:WpfApplication12" />
</Window.DataContext>
<TabControl
ItemsSource="{Binding Tabs}">
<TabControl.ItemTemplate>
<!-- this is the header template-->
<DataTemplate>
<TextBlock
Text="{Binding Header}" />
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<!-- this is the body of the TabItem template-->
<DataTemplate>
<----- usercontrol namespace goes here--->
</DataTemplate>
</TabControl.ContentTemplate>
Source:link
来源:链接

