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



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



Макет Приложения



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



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



Есть мысли?

927   5  

5 ответов:

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

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

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

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

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

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

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

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

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

Comments

    Ничего не найдено.