8

我的 WPF Windows 包含一个 TabControl,它在不同的选项卡上显示内容。单击下面的按钮通过 ICommand 接口/绑定执行方法。被调用的方法生成文本,该文本旨在显示在第二个选项卡中。

应用模型

如何在不违反 MVVM 模式的情况下切换到按钮单击的第二个选项卡?

我试图将 TabItem.IsSelected 属性绑定到我的 ViewModel 中的某个东西,但我也想使用其他选项卡 (tab1)。

有什么想法吗?

4

5 回答 5

15

我自己发现的。

关键是双向绑定。单击按钮时,它将属性设置为DisplayXamlTabtrue。该IsSelected属性绑定到此变量。如果单击另一个选项卡,则绑定会将 DisplayXamlTab 属性设置为 false。

注意:UpdateSourceTrigger=PropertyChanged也很重要

代码如下:

XAML:

        <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");
    }
}
于 2013-03-06T17:05:48.623 回答
12

如果您采用 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 依赖属性

于 2013-03-06T17:00:23.467 回答
2

尽管这个问题已经相当老了并且已经得到了很好的回答,但我想我会添加这个额外的答案来演示另一种TabItem更改TabControl. 如果每个 都有一个视图模型TabItem,那么在其中有一个IsSelected属性来确定它是否被选中会很有帮助。可以使用以下属性将此IsSelected属性与属性数据绑定:TabItem.IsSelectedItemContainerStyle

<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属性的数据,因此调用此...:

MenuItems[1].IsSelected = true;

...实际上还会自动将MenuItems[0].IsSelected属性设置为false. 因此,如果您正在使用的视图模型的IsSelected属性设置为 true,那么您可以确保在TabControl.

于 2014-11-06T21:11:45.207 回答
1

您可以在视图模型和属性之间创建绑定TabControl.SelectedIndex- 即,0 选择第一个TabItem,1 选择第二个,等等。

<TabControl DataContext="..." SelectedIndex="{Binding SomeVmProperty}" ...

(或者,根据您的设置方式,您可以绑定SelectedItem...)

于 2013-03-06T16:55:03.427 回答
0

您可能希望使用某种“事件聚合器”模式(即 MVVM Light 中的Messenger类)来广播某种“导航”消息。您的视图 - TabControl - 可以侦听特定消息,并在收到消息时导航到 Tab2。

或者,您可以将 TabControl 的“ SelectedItem ”属性绑定到您的 ViewModel,然后简单地CurrentTab = MySecondTabViewModel从您的 VM 中调用。这是@HighPoint 在对 OP 的评论中推荐的方法,但我不是粉丝;见下文。这种方法的另一个警告是您需要熟悉DataTemplates,因为您需要将视图映射到您显示的每个 ViewModel。

我个人喜欢第一种方法,因为我不认为它是 ViewModel 处理选项卡导航的“职责”。如果您只是在 ViewModel 中的数据更改时提醒您的 View,您可以让 View 决定是否要更改选项卡。

于 2013-03-06T16:53:09.507 回答