'WPF Tabcontrol (TabItem Content is not appearing)

I implemented a TabControl with Closable TabItems in my App. For this, I am using a Collection which I fill with the SubMenuItems of MenuItem "Öffne", which are bound to ICommands in the MainViewModel.

So if I click on MenuItem "Open Tab1", then the header of Tab 1 is created, but I can not see any content. The content of the TabItem is shown AFTER I click on the Header of the TabItem. But I want it to be shown directly when the TabItem is "created" without any need of clicking on the header. Closing the TabItems from the "X" button works fine.

I looked at a couple of examples and tried a ContentTemplate, but it didn't work (Maybe I made something wrong?).

I Hope you can tell me what i have done wrong or show me a good example. Thanks in advance!

Here are my code snippets:

MainWindow.XAML:

<Window.Resources>
<vm:MainViewModel x:Key="viewModel"/>
</Window.Resources>
<TabControl Background="#FFE5E5E5" ItemsSource="{Binding TabControlViews}" SelectedItem="{Binding CurrentTabItem}" Margin="0,21,0,0">
        <TabControl.ItemTemplate>
            <DataTemplate>       
                <DockPanel Width="120">
                    <TextBlock Text="{Binding Header}"/>
                    <Button
                Command="{Binding ParameterizedCommand, Source={StaticResource viewModel}}"
                CommandParameter="{Binding Header, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"
                Content="X"
                Cursor="Hand"
                DockPanel.Dock="Right"
                Focusable="False"
                FontFamily="Courier"
                FontSize="9"
                FontWeight="Bold"
                Margin="0,1,0,0"
                Padding="0"
                VerticalContentAlignment="Bottom"
                Width="16" Height="16" />
                    <ContentPresenter
                Content="{Binding Path=DisplayName}"
                VerticalAlignment="Center" />
                </DockPanel>
            </DataTemplate>
        </TabControl.ItemTemplate>
        <!--<TabControl.ContentTemplate>
            <DataTemplate>                   
            </DataTemplate>
        </TabControl.ContentTemplate>-->
        <TabControl.Resources>
            <DataTemplate x:Name="test" DataType="{x:Type vm:MenueVM}">
                <cu:MenueSearch/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type vm:FieldPointsVM}">
                <cu:FieldPointsSearch/>
            </DataTemplate>
            <DataTemplate DataType="{x:Type vm:DataTransferVM}">
                <cu:DataTransfer/>
            </DataTemplate>
        </TabControl.Resources>
</TabControl>

MainWindow.cs:

public partial class MainWindow : Window
{

    public MainWindow()
    {
        InitializeComponent();
        var vm = (MainViewModel)Resources["viewModel"];
        this.DataContext = vm;
    }
}

MainViewModel.cs:

    public MainViewModel()
    {

        TabControlViews = new ObservableCollection<BaseViewModel>();
        _menueVM = new MenueVM("Menüpunkte", "Menue");
        _fieldVM = new FieldPointsVM("Feldpunkte", "FieldPoint");
        _dataVM = new DataTransferVM("DatenTransfer", "DataTransfer");
        ParameterizedCommand = new RelayCommand(DoParameterizedCommand);
    }

    private void DoParameterizedCommand(object parameter)
    {
        if (parameter.ToString() == "App.ViewModel.MenueVM")
        {
            TabControlViews.Remove(_menueVM);
        }
        else if (parameter.ToString() == "App.ViewModel.FieldPointsVM")
        {
            TabControlViews.Remove(_fieldVM);
        }
        else if (parameter.ToString() == "App.ViewModel.DataTransfer")
        {
            TabControlViews.Remove(_dataVM);
        }
    }

    private ICommand _parameterizedCommand;
    public ICommand ParameterizedCommand
    {
        get 
        { 
            return _parameterizedCommand; 
        }
        set
        {
            _parameterizedCommand = value;
        }
    }

    private TabItem _propCurrentTabItem;
    public TabItem CurrentTabItem
    {
        get
        {
            return _propCurrentTabItem;
        }
        set
        {
            _propCurrentTabItem = value;
        }
    }

    private ObservableCollection<BaseViewModel> _TabControlViews = new ObservableCollection<BaseViewModel>();
    public ObservableCollection<BaseViewModel> TabControlViews
    {
        get
        {
            return _TabControlViews;
        }
        set
        {
            _TabControlViews = value;
            OnPropertyChanged();
        }
    }

    public ICommand OpenMenupunkteCommand
    {
        get
        {
            return new BaseCommand(OpenMenuPunkte);
        }
    }

    public ICommand OpenFeldpunkteCommand
    {
        get
        {
            return new BaseCommand(OpenFeldpunkte);
        }
    }

    public ICommand OpenDataTransferCommand
    {
        get
        {
            return new BaseCommand(OpenDataTransfer);
        }
    }
   private void OpenMenuPunkte()
    {
        if (!TabControlViews.Contains(_menueVM))
        {
            TabControlViews.Add(_menueVM);
        }

    }

    private void OpenFeldpunkte()
    {
        if (!TabControlViews.Contains(_fieldVM))
        {
            TabControlViews.Add(_fieldVM);
        }
    }

    private void OpenDataTransfer()
    {
        if (!TabControlViews.Contains(_dataVM))
        {
            TabControlViews.Add(_dataVM);
        }
    }

MenueVM.cs

public class MenueVM : BaseViewModel
{

    public MenueVM()
    {
       //Here are some actions done for Data, but I think they are unimportant for this question
    }

    public MenueVM(string header, string content)
    {
        Header = header;
        Content = content;
    }

    private string _header;
    public string Header
    {
        get
        {
            return _header;
        }
        set
        {
            _header = value;
        }
    }


Solution 1:[1]

Still time to post an answer? Try this :

XAML:

<TabControl ItemsSource="{Binding....}" IsSynchronizedWithCurrentItem="True">
    <!-- style, template, ... -->
</TabControl>

CS:

//Adding your viewModel to your ObservableCollection<> TabControlViews
TabControlViews.Add(_viewModelToAdd);
ICollectionView collectionView = CollectionViewSource.GetDefaultView(TabControlViews);
if (collectionView != null)
{
    collectionView.MoveCurrentTo(_viewModelToAdd);
    //And this is because you don't want your tabItem to be selected :
    collectionView.MoveCurrentToPrevious();
}

Found in the downloadable DemoMVVMApp here : https://msdn.microsoft.com/en-us/magazine/dd419663.aspx#id0090030

I've also spent a huge amount of time to solve this problem... ;-)

Solution 2:[2]

The problem is that your tab is been created, but it´s not been selected. So, in addition to calling

TabControlViews.Add(_dataVM)

, you should also update your CurrentTabItem

CurrentTabItem = _dataVM;

and bind your TabControl SelectedItem property to your CurrentTabItem, like this:

<TabControl ItemsSource="{Binding TabControlViews}" SelectedItem="{Binding CurrentTabItem}">

Also, if you remove a TabItem and want to get back to the last one, you have to call

CurrentTabItem = TabControlViews.LastOrDefault();

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 rod0302