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

Как я могу переключиться на вторую вкладку при нажатии кнопки, не нарушая шаблон MVVM?
Я попытался связать Табитем.IsSelected свойство к чему-то в моем ViewModel, но я хотел использовать другие вкладки (tab1) также.
Есть мысли?
5 ответов:
Я выяснил это сам.
Ключ - это двусторонняя привязка. При нажатии на кнопку устанавливается свойство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"); } }
Если вы идете по пути 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