Dynamically Updating TabControl Content at Runtime

Ok… lets see:

First of all, you must learn to think your UI in an abstract way:

What is a TabControl?

It’s a graphical representation of a List of widgets, where the user can have 1 active widget at a time. These widgets have a Title (the tab item text), a Visibility state, and an Enabled/Disabled state.

What is a bunch of stacked buttons? (toolbar, if you want to call it that)

It’s a graphical representation of a List of actions that the user can perform at any given time. These actions have a Description (the button’s content), possibly an associated icon or graphical image, and an Enabled / Disabled State.

What is a ContextMenu, or a Menu?

The same as above, it’s a graphical representation of a list of Actions that the user can perform.

How would I go about creating a dynamic TabControl in WPF?

This is the XAML for a WPF TabControl that supports dynamic Children:

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

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

With this example, each item (TabItem) in the TabControl will be bound to one of the ViewModels, then it’s just a matter of inheriting the base TabViewModel for each of your tabs and creating a proper DataTemplate for each.

As you can see in this example, I’m in no way creating or manipulating ANY UI elements in code. This simplifies all code A LOT, and helps maintain a clear separation between logic and UI.
You can apply this same concept to everything in WPF.

Leave a Comment