Reputation: 2113
I have a TabControl
with multiple DataTemplate
. the first DataTemplate
will be used for search reasons and the second will be for displaying items obtained from that search. My XAML
code will be as follows:
<UserControl.Resources>
<!--First template-->
<DataTemplate>
<!-- I will have a DataGrid here-->
</DataTemplate>
<!--Second template-->
<DataTemplate >
<!-- I will have details of one item of the DataGrid-->
</DataTemplate>
</UserControl.Resources>
<TabControl ItemsSource="{Binding }"/>
What I want to accomplish is that in the TabControl
the first tab will contain the first DataTemplate
(the search template) and when I double click on one row of my DataGrid
, a tab will be added with the details of that row (in other words a tab with the second template).
Since I am using MVVM
, I thought of creating two UserControl
s, one for each template and then catch the double click event, but after this I don't know how to add a tab since now my search template is a UserControl
seperated from the one that contains the TabControl
.
So how do I do this?
UPDATE:
As I read the answers I think I wasn't very clear in stating the problem. My problem is how to add tabs with the second template, by catching double click events from the first template. I don't have any problem in adding the two templates independently.
Upvotes: 1
Views: 4282
Reputation: 27360
There are two options: Use datatemplate selector, or use implicit datatemplates and different types for each tabitem.
1. DataTemplateSelector:
public ObservableCollection<TabItemVM> Tabs { get; private set; }
public MainVM()
{
Tabs = ObservableCollection<TabItemVM>
{
new TabItemVM { Name="Tab 1" },
};
}
void AddTab(){
var newTab = new TabItemVM { Name="Tab 2" };
Tabs.Add(newTab);
//SelectedTab = newTab; //you may bind TabControl.SelectedItemProperty to viewmodel in order to be able to activate the tab from viewmodel
}
public class TabItemTemplateSelector : DataTemplateSelector
{
public DataTemplate Tab1Template { get; set; }
public DataTemplate Tab2Template { get; set; }
public override DataTemplate SelectTemplate(object item, DependencyObject container)
{
var tabItem = item as TabItemVM;
if (tabItem.Name == "Tab 1") return Tab1Template;
if (tabItem.Name == "Tab 2") return Tab2Template;
return base.SelectTemplate(item, container);
}
}
<local:TabItemTemplateSelector
x:Key="TabItemTemplateSelector"
Tab1Template="{StaticResource Tab1Template}"
Tab2Template="{StaticResource Tab2Template}" />
2. Implicit Data Templates:
public class MainVM : ViewModelBase
{
public ObservableCollection<TabItemVM> Tabs { get; private set; }
public MainVM()
{
Tabs = new ObservableCollection<TabItemVM>
{
new Tab1VM(),
};
}
void AddTab()
{
var newTab = new Tab2VM()
Tabs.Add(newTab);
//SelectedTab = newTab;
}
}
public class TabItemBase
{
public string Name { get; protected set; }
}
public class Tab1VM : TabItemBase
{
public Tab1VM()
{
Name = "Tab 1";
}
}
public class Tab2VM : TabItemBase
{
public Tab2VM()
{
Name = "Tab 2";
}
}
<UserControl.Resources>
<!--First template-->
<DataTemplate DataType="local:Tab1VM">
<!-- I will have a DataGrid here-->
</DataTemplate>
<!--Second template-->
<DataTemplate DataType="local:Tab2VM">
<!-- I will have details of one item of the DataGrid-->
</DataTemplate>
</UserControl.Resources>
Upvotes: 1
Reputation: 21261
If you're going to do this with MVVM, your tab control should be bound to some ObservableCollection
in your VM, and you just add and remove VM's to the collection as needed.
The VMs can be any type you like and your DataTemplates will show the correct view in the tab just like any other view, so yes, create two UserControls for the two views.
public class MainVM
{
public ObservableCollection<object> Views { get; private set; }
public MainVM()
{
this.Views = new ObservableCollection<object>();
this.Views.Add(new SearchVM(GotResults));
}
private void GotResults(Results results)
{
this.Views.Add(new ResultVM(results));
}
}
Upvotes: 1
Reputation: 758
Rather can creating two UserControl
s, you can create and use a DataTemplateSelector
in order to switch different DataTemplate
s in.
Basically, create a new class that inhereits from DataTemplateSelector
and override the SelecteTemplate
method. Then declare an instance of it in the XAML (much like a value converter), and then apply it to ContentTemplateSelector
property of the TabControl
.
Upvotes: 2