我正在尝试创建一个基本的窗口,该窗口使用WPF TabControl允许用户添加新的选项卡。我希望最终产品看起来像选项卡在Web浏览器中的工作方式,其中最后一个选项卡只是一个“ +”,单击该选项将添加一个新的选项卡。
我正在尝试编写XAML代码来进行设置,发现我可以在“ TabControl.Resources”中指定多个DataTemplate,并且根据“ DataType”,正确的DataTemplate将用于显示每个选项卡的正确视图...但是在处理选项卡标题时,我只能为“ TabControl.ItemTemplate”
指定一个DataTemplate这是我到目前为止所拥有的:
<TabControl ItemsSource="{Binding Tabs}">
<TabControl.Resources>
<!-- If the tab is of type "TabViewModel" I want this content -->
<DataTemplate DataType="x:Type vm:TabViewModel">
<!-- TabView is defined as a separate user control -->
<v:TabView/>
</DataTemplate>
<!-- If the tab is of type "NewTabViewModel" I want this content -->
<DataTemplate DataType="x:Type vm:NewTabViewModel">
<!-- NewTabView is defined as a separate user control -->
<v:NewTabView/>
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<!-- if the tab is of type "TabViewModel" I want this header -->
<DataTemplate DataType="x:Type vm:TabViewModel">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<!-- If the tab is of type "NewTabViewModel" I want this header -->
<!-- ERROR: Adding a second "DataTemplate" here results in an error -->
<DataTemplate DataType="x:Type vm:NewTabViewModel">
<TextBlock Text="+"/>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>
[Google周围的地方,我发现了一些有关设置TemplateSelector并编写大量背景C#代码的文章,但是对于这种简单的操作来说,这似乎太过分了。我只希望它显示选项卡名称,如果它是常规的TabViewModel对象,则显示“ +”,如果它是NewTabViewModel对象。
这里有DataTemplate的两种完全不同的用法。
ItemTemplate属性的类型为DataTemplate。具体来说,是一个DataTemplate,而不是一个集合。期望您将其设置为所需的任何模板,这就是它将用于填充选项卡标题的模板。此外,在TabControl的情况下,该模板将应用于all标头;您不必在每个标签上进行更改。
选项卡面板本身的类型为ContentControl,每个面板都绑定到一个视图模型。 ContentControl包含一个ContentPresenter,它遍历逻辑树,为它绑定到的数据类型寻找一个DataTemplate(在内部,DataTemplate的DataType属性只是将类型本身设置为x:Key的语法糖)。
[您的问题是,您希望像提供ResourceDictionary一样使用ItemTemplate,指定多个DataTemplate,但希望您提供模板本身,而只能提供一个。因此,要实现您要执行的操作,只需给它提供一个DataTemplate并用ContentPresenter(由Dreamer建议)填充它,就如同选项卡面板本身一样。这个ContentPresenter有自己的ResourceDictionary,您可以在其中放置标题模板:
<TabControl ItemsSource="{Binding Tabs}">
<TabControl.Resources>
<!-- Panel templates -->
<DataTemplate DataType="{x:Type vm:TabViewModel}">
<v:TabView />
</DataTemplate>
<DataTemplate DataType="{x:Type vm:NewTabViewModel}">
<v:NewTabView />
</DataTemplate>
</TabControl.Resources>
<TabControl.ItemTemplate>
<DataTemplate>
<ContentPresenter Content="{Binding}">
<ContentPresenter.Resources>
<!-- Header templates -->
<DataTemplate DataType="{x:Type vm:TabViewModel}">
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
<DataTemplate DataType="{x:Type vm:NewTabViewModel}">
<TextBlock Text="+"/>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
</DataTemplate>
</TabControl.ItemTemplate>
</TabControl>