You do not need anything. It is clear that TabControl is just a graphical representation of the ObservableCollection<ViewModel> , where each view model is represented by a tab element, and there is only 1 SelectedItem at a given time:
<Window x:Class="WpfApplication4.Window12" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Window12" Height="300" Width="300"> <Window.Resources> <BooleanToVisibilityConverter x:Key="BoolToVisibilityConverter"/> </Window.Resources> <TabControl ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}"> <TabControl.ItemContainerStyle> <Style TargetType="TabItem"> <Setter Property="IsEnabled" Value="{Binding IsEnabled}"/> <Setter Property="Visibility" Value="{Binding IsVisible, Converter={StaticResource BoolToVisibilityConverter}}"/> <Setter Property="Header" Value="{Binding Title}"/> </Style> </TabControl.ItemContainerStyle> </TabControl> </Window>
Code for:
using System.Windows; using BaseFramework.MVVM; using System.Collections.ObjectModel; namespace WpfApplication4 { public partial class Window12 : Window { public Window12() { InitializeComponent(); DataContext = new TabbedViewModel() { Items = { new TabViewModel() {Title = "Tab #1", IsEnabled = true, IsVisible = true}, new TabViewModel() {Title = "Tab #2", IsEnabled = false, IsVisible = true}, new TabViewModel() {Title = "Tab #3", IsEnabled = true, IsVisible = false}, } }; } }
ViewModel:
public class TabbedViewModel: ViewModelBase { private ObservableCollection<TabViewModel> _items; public ObservableCollection<TabViewModel> Items { get { return _items ?? (_items = new ObservableCollection<TabViewModel>()); } } private ViewModelBase _selectedItem; public ViewModelBase SelectedItem { get { return _selectedItem; } set { _selectedItem = value; NotifyPropertyChange(() => SelectedItem); } } } public class TabViewModel: ViewModelBase { private string _title; public string Title { get { return _title; } set { _title = value; NotifyPropertyChange(() => Title); } } private bool _isEnabled; public bool IsEnabled { get { return _isEnabled; } set { _isEnabled = value; NotifyPropertyChange(() => IsEnabled); } } private bool _isVisible; public bool IsVisible { get { return _isVisible; } set { _isVisible = value; NotifyPropertyChange(() => IsVisible); } } } }
Then it's just a matter of inheriting TabViewModel for each of your tabs (creating the appropriate logic inside each) and the correct DataTemplate for each of these derived classes in app.xaml or something.
Whenever you want to remove a tab element from the view, instead of manipulating the view that you are controlling the ViewModel. this is a WPF approach for everything. This simplifies everything by eliminating the need to manage complex objects (user interface elements) in the code. Whenever you install
TabbedViewModel.SelectedItem.IsVisible = false; make sure you also do:
TabbedViewModel.SelectedItem = TabbedViewModel.Items.First(x => x.IsVisible && x.IsEnabled);
This will prevent you from ever getting into the case if the selected item has an invisible tab.