I've a strange problem, and hope someone can help me with my struggle.
Here is the problem.
I have an application that needs to create dynamically TabItem's in one main TabControl.
The main window has two buttons in a StackPanel, and one TabControl (that will host the different TabItem instances:
<DockPanel>
<StackPanel Orientation="Horizontal" DockPanel.Dock="Top">
<Button Content="Tab1" Command="{Binding AddTab}" CommandParameter="Tab1"/>
<Button Content="Tab2" Command="{Binding AddTab}" CommandParameter="Tab2"/>
</StackPanel>
<TabControl DockPanel.Dock="Bottom"
ItemsSource="{Binding TabItems}"
SelectedItem="{Binding CurrentTabItem}"
ItemTemplate="{StaticResource TabItemItemTemplate}"/>
</DockPanel>
In the CodeBehind of the main window, a set the DataContext to a new class that has public property for all opened TabItem instances, for the selected Tab, and a command for adding a new tab:
public ICommand AddTab { get; set; }
public ObservableCollection<TabItem> TabItems { get; set; }
private TabItem _currentTabItem;
public TabItem CurrentTabItem
{
get {return _currentTabItem;}
set
{
if(_currentTabItem == value) return;
_currentTabItem = value;
OnPropertyChanged(nameOf(CurrentTabItem);
}
}
And a function that handles adding the new tab:
private void OnAddTabExecute(object obj)
{
var type = obj as string;
if (type != null)
{
TabItem ti;
if (type == "Tab1")
{
ti = new Tab1ViewModel();
}
else
{
ti = new Tab2ViewModel();
}
TabItems.Add(ti);
CurrentTabItem = ti;
}
In the Main Window I'm declaring two DataTemplates that are responsible to "wire" the selected "Tab1ViewModel" or "Tab2ViewModel" a corresponding View:
<DataTemplate DataType="{x:Type local:Tab1ViewModel}">
<local:Tab1View/>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Tab2ViewModel}">
<local:Tab2View/>
</DataTemplate>
So far so good!! Everything works perfect!!! Then in the local:Tab1View.xaml I add another TabControl with manually added TabItems:
<TabControl SelectedIndex="{Binding SelectedIndex}">
<TabItem Header="New Tab">
<DataGrid AutoGenerateColumns="False" ItemsSource="{Binding ThisThings}" CanUserAddRows="False">
<DataGrid.Columns>
<DataGridTemplateColumn Header="Country">
<DataGridTemplateColumn.CellTemplate>
<DataTemplate>
<ComboBox ItemsSource="{Binding DataContext.Countries,
RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"
DisplayMemberPath="Description"
SelectedValuePath="ID"
SelectedValue="{Binding CountryID}"/>
</DataTemplate>
</DataGridTemplateColumn.CellTemplate>
</DataGridTemplateColumn>
</DataGrid.Columns>
</DataGrid>
</TabItem>
<TabItem Header="Newer Tab">
<TextBlock Text="This is test tab"/>
</TabItem>
</TabControl>
The presented properties are in the ViewModel, and Everything loads up as I wanted, BUT here is the problem:
- I push the Tab2 button and Tab2 shows up (no problems) 2.I push the Tab1 button and Tab1 loads up, with all selected data in the comboboxes:
Notice the selected countries: "Bulgaria" (row1), "UK" (row2), "Russia" (row3). 3. Change the "UK" selection from row 2, to "Germany".
- Select from the inner TabControl the "Newer Tab", and get back to the "New Tab". The row 2 selection is still "Germany"
5.Select "Tab 2" tab from the outer TabControl, and get back to "Tab 1", The selection is back from "Germany" to "UK", as it was at the load up of tab.
I red somewhere that when you select a current tab, the one that is unselected is taken out from the Visual tree. But why then it is not happening when I change the inner TabControl's tabs? This drive's me crazy.
I have a solution with the project, if anyone needs it, I can present it. Here is a link I hope it works! (When you start the project, the window in the screenshots shows, by clicking on the "Show" button)
I'll appritiate any ideas what is wrong with this, and how it can be fixed
EDIT on 01/03/2017
I'm providing the code for the Tab1ViewModel:
public class Tab1ViewModel : TabItem
{
public ObservableCollection<Country> Countries { get; set; }
public ObservableCollection<Thing> ThisThings { get; set; }
public Thing ThisThing { get; set; }
//public NewerTabViewModel NewerTabViewModel { get; set; }
//public NewTabViewModel NewTabViewModel { get; set; }
public int SelectedIndex { get; set; }
public override string Header
{
get
{
return "Tab 1";
}
}
public Tab1ViewModel()
{
ThisThings = new ObservableCollection<Thing>();
ThisThings.Add(new Thing() { CountryID = 1, Name = "Greg" });
ThisThings.Add(new Thing() { CountryID = 2, Name = "John" });
ThisThings.Add(new Thing() { CountryID = 4, Name = "Sam" });
ThisThing = new Thing()
{
CountryID = 3,
Name = "Thingy",
//HisThings = ThisThings
};
//NewTabViewModel = new NewTabViewModel(ThisThing);
//NewerTabViewModel = new NewerTabViewModel(ThisThing);
Countries = new ObservableCollection<Country>();
Countries.Add(new Country() { ID = 1, Description = "Bulgaria" });
Countries.Add(new Country() { ID = 2, Description = "UK" });
Countries.Add(new Country() { ID = 3, Description = "USA" });
Countries.Add(new Country() { ID = 4, Description = "Russia" });
Countries.Add(new Country() { ID = 5, Description = "Germany" });
}
}




ThisThingscollection, and the ThisThing object and the Countries collection - Julian