简体   繁体   English

WPF:具有多个DataTemplates的TabControl

[英]WPF: TabControl with multiple DataTemplates

I have a TabControl with multiple DataTemplate . 我有一个带有多个DataTemplateTabControl the first DataTemplate will be used for search reasons and the second will be for displaying items obtained from that search. 第一个DataTemplate将用于搜索原因,第二个将用于显示从该搜索中获得的项目。 My XAML code will be as follows: 我的XAML代码如下:

 <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). 我要完成的工作是,在TabControl ,第一个选项卡将包含第一个DataTemplate (搜索模板),当我双击DataGrid一行时,将添加一个带有该行详细信息的选项卡(换句话说,一个带有第二个模板的标签)。

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 . 由于我使用的MVVM ,我想创建两个UserControl S,为每个模板,然后捕捉双击事件,但在此之后,我不知道如何,因为现在我的搜索模板是添加标签UserControl从分隔一个包含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. 我独立添加两个模板没有任何问题。

Rather can creating two UserControl s, you can create and use a DataTemplateSelector in order to switch different DataTemplate s in. 可以创建两个UserControl ,而可以创建和使用DataTemplateSelector来切换不同的DataTemplate

Basically, create a new class that inhereits from DataTemplateSelector and override the SelecteTemplate method. 基本上,从DataTemplateSelector创建一个新类,并重写SelecteTemplate方法。 Then declare an instance of it in the XAML (much like a value converter), and then apply it to ContentTemplateSelector property of the TabControl . 然后在XAML中声明它的一个实例(非常类似于值转换器),然后将其应用于TabControl ContentTemplateSelector属性。

More info can be found here . 更多信息可以在这里找到

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. 如果要使用MVVM进行此操作,则应将选项卡控件绑定到VM中的某些ObservableCollection ,然后根据需要将VM添加和删除到集合中。

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. VM可以是您喜欢的任何类型,并且DataTemplates会像其他任何视图一样在选项卡中显示正确的视图,因此可以,为这两个视图创建两个UserControl。

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));
    }
}

There are two options: Use datatemplate selector, or use implicit datatemplates and different types for each tabitem. 有两个选项:使用datatemplate选择器,或对每个tabitem使用隐式datatemplates和不同的类型。

1. DataTemplateSelector: 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: 2.隐式数据模板:

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>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM