Handling WPF TabItems Visibility property

12,942

Solution 1

You don't need any of that. Conceptually, a TabControl is just a graphical representation of an ObservableCollection<ViewModel>, where each viewmodel is represented by a tab item, and there's 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 Behind:

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, its just a matter of inheriting TabViewModel for each one of your tabs (creating the appropiate logic inside of each), and a proper DataTemplate for each one of these derived classes in the app.xaml or something.

Whenever you want to remove a tab item from the view, instead of manipulating the view you manipulate the ViewModel. this is the WPF approach for everything. It simplifies everything by removing the need to manipulate complex objects (UI elements) in code. Whenever you set

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 falling into the case of having an invisible tab item as the selected item.

Solution 2

Hi just Add and Remove the TabItems from TabControl instead of setting Visibility. There is one more issue with Turning on and off the Visibility and it is exception like Out of index when you scroll or minimize or resize the TabControl.

Share:
12,942

Related videos on Youtube

aioracle
Author by

aioracle

Updated on September 15, 2022

Comments

  • aioracle
    aioracle over 1 year

    I have been reading about Visibility.Collapsed for TabItems. When the Visibility is set to Collapsed, the TabItem header is hidden but the contents are still visible.

    I have also tried the following approch mentioned in here, but no luck.

    Is there any way to get the contents inside the TabItems to hide and also select the tab that is visible.

    • Federico Berasategui
      Federico Berasategui about 11 years
      You don't need any of that. Conceptually, a TabControl is just a graphical representation of an ObservableCollection<ViewModel>, where each viewmodel is represented by a tab item, and there's only 1 SelectedItem at a given time.