1
votes

I have a problem with the selected item in WPF-TabControl that could be reproduced with the following simplified code:

If a new TabItem is created and selected through the Click-event of the button in the second window, the tab is created, added and selected. When the second window will be closed, the selected item of the tab-control is reset to the last selected item. The problem occurs in my MVVM-app and it is independent of the Items-collection. I can use the ItemsSource or the Items-Collection, it happens always.

Has someone an idea what happens here or has a nice workaround?

TabControl tabControl = new TabControl() ;
tabControl.Items.Add(new TabItem { Header="InitialTabItem"});
((TabItem)tabControl.Items[0]).Focus();
Window mainWindow = new Window() { Content=tabControl,Title="TabControl-Window"};
mainWindow.Show();            
Button addButton = new Button() { Content="AddTabItem"};
addButton.Click += (o, e) => {
        TabItem newTabItem=new TabItem(){Header=DateTime.Now.ToLongTimeString()};
        tabControl.Items.Add(newTabItem);                
        tabControl.SelectedItem = newTabItem;                
};
Window directorWindow = new Window() { Owner = mainWindow ,Content=addButton,Height=80,Width=200,Title="DirectorWindow"};
directorWindow.Show();

Update

It seems to be as always when I have bigger problems with WPF, to be an issue with focus-management. If I change the creation-code as follows, it works:

TabItem newTabItem=new TabItem(){Header=DateTime.Now.ToLongTimeString()};
tabControl.Items.Add(newTabItem);                    
Dispatcher.BeginInvoke(new Action(delegate{
    newTabItem.Focus();
    tabControl.SelectedItem = newTabItem;
}), System.Windows.Threading.DispatcherPriority.Input, null);

However it looks not very confidently to me. Some ideas?

2
r u really using MVVM pattern ? Becuase you are creating all these tabs uisng code. Why don't you consider using observrable collection which is binded to the TabControl's ItemSource Property,TalentTuner
@saurabh: Its demo code to reproduce the error. The real application works with a ViewModel that provides an ItemsSource for the tab-items and also a SelectedTabItem-property. But I don't like to post huge code examples. No one likes to study huge code-blocks to see a simple problem. As I wrote, it makes no difference if I use the Items-or the ItemsSource-property. It's a general problem that can be reproduced with the above code.HCL

2 Answers

1
votes

Yeah, TabControl behaves strange sometimes. In our project we had to create a subclass and override some methods to workaround another bug in it.

In your case, everything seems to work if you focus the TabControl itself before focusing the TabItem:

        var tabControl = new TabControl();
        var tabItem = new TabItem { Header = "InitialTabItem" };
        tabControl.Items.Add(tabItem);
        tabControl.Focus();
        tabItem.Focus();
        Window mainWindow = new Window() { Content = tabControl, Title = "TabControl-Window" };
        mainWindow.Show();
        Button addButton = new Button() { Content = "AddTabItem" };
        addButton.Click += (o, args) =>
        {
            TabItem newTabItem = new TabItem() { Header = DateTime.Now.ToLongTimeString() };
            tabControl.Items.Add(newTabItem);
            tabControl.SelectedItem = newTabItem;
        };
        Window directorWindow = new Window() { Owner = mainWindow, Content = addButton, Height = 80, Width = 200, Title = "DirectorWindow" };
        directorWindow.Show();

Update 1. See comments -- the original code causes bad side effects.

        var tabControl = new TabControl();
        var tabItem = new TabItem { Header = "InitialTabItem" };
        tabControl.Items.Add(tabItem);
        Window mainWindow = new Window() { Content = tabControl, Title = "TabControl-Window" };
        mainWindow.Show();
        tabControl.Focus();
        tabItem.Focus();
        Button addButton = new Button() { Content = "AddTabItem" };
        addButton.Click += (o, args) =>
        {
            TabItem newTabItem = new TabItem() { Header = DateTime.Now.ToLongTimeString() };
            tabControl.Items.Add(newTabItem);
            tabControl.SelectedItem = newTabItem;
        };
        Window directorWindow = new Window() { Owner = mainWindow, Content = addButton, Height = 80, Width = 200, Title = "DirectorWindow" };
        directorWindow.Show();
1
votes

See Yacoders solution that solves the issue with the demo-code. However led this solution to focus-issues in my real project.

A way that seems to work for me is the way I showed in my update. If someone has the same problem, try the following code. Up to now, I have not seen any side-effects.

TabControl tabControl = new TabControl() ;  
tabControl.Items.Add(new TabItem { Header="InitialTabItem"});  
((TabItem)tabControl.Items[0]).Focus();  
Window mainWindow = new Window() { Content=tabControl,Title="TabControl-Window"};  
mainWindow.Show();              
Button addButton = new Button() { Content="AddTabItem"};  
addButton.Click += (o, e) => {  
    TabItem newTabItem=new TabItem(){Header=DateTime.Now.ToLongTimeString()};   
    tabControl.Items.Add(newTabItem);                       
    Dispatcher.BeginInvoke(new Action(delegate{   
       newTabItem.Focus();   
       tabControl.SelectedItem = newTabItem;   
    }), System.Windows.Threading.DispatcherPriority.Input, null); 
};  
Window directorWindow = new Window() { Owner = mainWindow ,Content=addButton,Height=80,Width=200,Title="DirectorWindow"};  
directorWindow.Show();