如何在单击按钮时切换到第二个选项卡而不违反MVVM模式?
我尝试将TabItem.IsSelected属性绑定到ViewModel中的某些内容,但我也想使用其他选项卡(Tab1)。
你有什么建议吗?
DisplayXamlTab
设置为 true。 IsSelected
属性与此变量绑定。如果单击另一个选项卡,则绑定将将 DisplayXamlTab 属性设置为 false。UpdateSourceTrigger=PropertyChanged
也非常重要。 <TabItem Header="XAML" IsSelected="{Binding DisplayXamlTab, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
<Grid Background="#FFE5E5E5">
<TextBox x:Name="TxtXamlOutput" IsReadOnly="True" Text="{Binding XamlText, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, UpdateSourceTrigger=PropertyChanged}" AcceptsReturn="True" TextWrapping="Wrap" VerticalScrollBarVisibility="Visible"/>
</Grid>
</TabItem>
C# 属性:
private bool displayXamlTab;
public bool DisplayXamlTab
{
get { return this.displayXamlTab; }
set
{
this.displayXamlTab = value;
this.RaisePropertyChanged("DisplayXamlTab");
}
}
如果你采用MVVM方式,那么你需要在代码后台创建两个依赖属性:
ObservableCollection<ItemType> Items;
ItemType MySelectedItem;
然后将TabControl的ItemsSource属性绑定到Items,并将SelectedItem属性绑定到MySelectedItem。
<TabControl ItemsSource="{Binding Items}"
SelectedItem="{Binding MySelectedItem, Mode=TwoWay}">
<TabControl.ItemTemplate>
<DataTemplate>
<... here goes the UI to display ItemType ... >
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
如果想要更改所选选项卡,只需更新MySelectedItem依赖属性即可。
虽然这个问题已经相当老,而且已经有了很好的回答,但我想添加这个额外的答案来演示一种在TabControl
中更改所选TabItem
的替代方法。如果你为每个TabItem
都有一个视图模型,那么在其中具有一个IsSelected
属性可以帮助确定它是否被选中。可以使用ItemContainerStyle
属性将此IsSelected
属性与TabItem.IsSelected
属性进行数据绑定:
<TabControl ItemsSource="{Binding MenuItems}" TabStripPlacement="Top">
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type ControlViewModels:MenuItemViewModel}">
<StackPanel Orientation="Horizontal">
<Image Source="{Binding ImageSource}" Margin="0,0,10,0" />
<TextBlock Text="{Binding HeaderText}" FontSize="16" />
</StackPanel>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.ContentTemplate>
<DataTemplate DataType="{x:Type ControlViewModels:MenuItemViewModel}">
<ContentControl Content="{Binding ViewModel}" />
</DataTemplate>
</TabControl.ContentTemplate>
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</TabControl.ItemContainerStyle>
</TabControl>
现在您可以像这样从父视图模型更改所选的TabItem
:
MenuItems[0].IsSelected = true;
TabItem.IsSelected
属性绑定,因此调用此属性的get
访问器将返回该TabItem
是否被选中。MenuItems[1].IsSelected = true;
实际上,这也会自动将MenuItems [0] .IsSelected
属性设置为false
。因此,如果您正在使用的视图模型其IsSelected
属性设置为true,则可以确保其相关视图在TabControl
中被选中。
TabControl.SelectedIndex
属性之间创建绑定 - 例如,0 选择第一个 TabItem
,1 选择第二个,以此类推。<TabControl DataContext="..." SelectedIndex="{Binding SomeVmProperty}" ...
另外,根据您的设置方式,您还可以绑定到 SelectedItem
...
你可能想要使用某种 "事件聚合器" 模式(例如 MVVM Light 中的 Messenger 类),来广播某种 "导航" 消息。你的视图 - TabControl - 可以监听特定的消息,并在接收到消息时导航到 Tab2。
另外一种方法是将TabControl的"SelectedItem"属性绑定到您的ViewModel,并在ViewModel中调用CurrentTab = MySecondTabViewModel
。这是@HighPoint在评论中推荐的做法,但我个人不太喜欢;请参考下面的内容。此方法的另一个注意事项是您需要熟悉DataTemplates,因为您需要将每个要显示的ViewModel映射到一个视图。
个人而言,我更喜欢第一种方法,因为我认为处理选项卡导航并不属于ViewModel的"责任"。如果您只需在ViewModel中的数据发生更改时通知View,您就允许View决定是否要更改选项卡。