Как изменить вкладку из TabControl в WPF без нарушения шаблона MVVM

мои окна WPF содержат TabControl, который отображает содержимое на разных вкладках. Щелчок по кнопке ниже выполняет метод через интерфейс / привязку ICommand. Вызываемый метод генерирует текст, который предназначен для отображения во второй вкладке.

Application Mockup

Как я могу переключиться на вторую вкладку при нажатии кнопки, не нарушая шаблон MVVM?

Я попытался связать TabItem.IsSelected свойство к чему-то в моей ViewModel, но я хотел используйте также другие вкладки (tab1).

какие мысли?

5 ответов


я выяснил это сам.

ключ является двусторонней привязкой. При нажатии на кнопку устанавливается свойство DisplayXamlTab true. The 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");
    }
}

Если вы идете в MVVM, как вы собираетесь создать два свойства зависимостей в коде:

  • ObservableCollection<ItemType> Items;
  • ItemType MySelectedItem;

затем привяжите свойство TabControl ItemsSource к предметы и привязать свойство 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 dependecy


хотя этот вопрос довольно старый и уже хорошо ответил, я подумал, что добавлю этот дополнительный ответ, чтобы продемонстрировать альтернативный способ изменения выбранного TabItem на TabControl. Если у вас есть модель представления для каждого TabItem, тогда может быть полезно иметь IsSelected свойство в нем, чтобы определить, выбран ли он или нет. Можно данные привязать это IsSelected собственность с TabItem.IsSelected свойство с помощью ItemContainerStyle свойства:

<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;

... будет infact также автоматически установить MenuItems[0].IsSelected свойство false. поэтому, если модель представления, с которой вы работаете, имеет свой IsSelected свойство имеет значение true, то вы можете быть уверены, что его связанный вид выбран в TabControl.


вы можете создать привязку между моделью представления и TabControl.SelectedIndex собственность - т. е. 0 выбирает "первый"!--2--> , 1 выбираем второй, и т. д.

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

(в качестве альтернативы, в зависимости от того, как у вас все настроено, вы можете привязаться к SelectedItem...)


вы, вероятно, захотите использовать какой-то "Событие Агрегатор" шаблон (т. е. the Посланник класс в MVVM Light) для трансляции какого-то" навигационного " сообщения. Ваше представление-TabControl - может прослушивать конкретное сообщение и переходить к Tab2 при получении сообщения.

кроме того, вы можете привязать "SelectedItem" свойство TabControl для вашей ViewModel и просто вызовите CurrentTab = MySecondTabViewModel из вашей виртуальной машины. Это the подход рекомендуется @HighPoint в комментариях к OP, но я не поклонник; см. ниже. Еще одно предостережение к этому подходу заключается в том, что вы должны быть знакомы с DataTemplates, так как вам нужно будет отобразить вид на каждый ViewModel, который вы отображаете.

Мне лично нравится первый подход, потому что я не считаю его "ответственностью" ViewModel для обработки навигации по вкладкам. Если вы просто предупредите свое представление, когда данные изменятся в вашем ViewModel, вы позволяете представлению решать, хочет ли он изменять вкладки.