WPF:TabControl.ItemTemplate和TabItem.ContentTemplate的区别

16
我对此有很长一段时间的困惑,这两者似乎都会影响tabcontrol中tabitems的呈现方式。它是为了最佳地控制tabcontrol的呈现而设计的吗?还是我有什么不理解的地方。

我相信它做了同样的事情。 - eran otzap
3个回答

41

这里有一些对于一个非常简单的问题非常冗长的答案。为了避免混淆:

ItemTemplate 是用于格式化 ItemsSource 中每个项目的模板,以创建标签栏中出现的标题(控件),而 ContentTemplate 是用于格式化 ItemsSource 中每个项目的模板,以创建选项卡内容(在您单击标题时出现的控件)。


5
通过设置TabControl.ItemTemplate,您可以为TabControl中的所有TabItems指定一个模板,除非您针对特定的TabItem覆盖TabItem.ContentTemplate
因此,虽然它们做相同的事情,TabControl.ItemTemplateTabControl中所有TabItems的更通用的模板,而TabItem.ContentTemplate则是特定于其使用的TabItem的模板。
但事实并不完全如此,因为TabControl具有ItemTemplate属性和ContentTemplate属性,使其更加混乱。 ItemTemplate用作所有通过数据绑定添加到ItemsSource或通过Xaml添加项目时(而不使添加的项目成为TabItem)的所有TabItems标头(选项卡)的模板:
<TabControl ItemsSource="{Binding ListOfItems}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Foreground="Red"/>
        </DataTemplate>
     </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
             <TextBlock Text="{Binding}" Foreground="Blue"/>
        </DataTemplate>
    </TabControl.ContentTemplate>
</TabControl>

这将创建一个带有红色标签/标签页文本和蓝色内容文本的TabControl

如果我们执行以下操作:

<TabControl>
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" Foreground="Red"/>
        </DataTemplate>
     </TabControl.ItemTemplate>
    <TabControl.ContentTemplate>
        <DataTemplate>
             <TextBlock Text="{Binding}" Foreground="Blue"/>
        </DataTemplate>
    </TabControl.ContentTemplate>

    <TabItem Header="One" Content="One"/>
    <TabItem Header="Two" Content="Two"/>
    <TabItem Header="Three" Content="Three"/>
</TabControl>

我们将有一个包含三个选项卡的TabControl,选项卡标题文本为黑色,内容仍为蓝色。同时还会出现一个数据错误(DataError),提示我们对于已经属于ItemsControl容器类型(在此情况下是TabItem)的项目,ItemTemplate和ItemTemplateSelector属性被忽略了。在这种情况下,我们需要指定TabItem.HeaderTemplate来改变选项卡标题的外观。
因此,TabControl.ItemTemplate和TabItem.ContentTemplate并不相同,但我的前面的解释仍然适用于TabControl.ContentTemplate和TabItem.ContentTemplate。

谢谢,你的解释很有用。 - Andrew Carl
其实,我说得不太对。刚刚检查了一下发现 TabControl 有一个 ItemTemplate 属性和一个 ContentTemplate 属性。稍后会更新我的答案以反映这一点。 - Roel van Westerop
所以结论是:tabControl(或ListBox)是itemsControl,这意味着它的属性,如itemTemplate,仅负责其自身从itemssource中获取的项目的形式。它不会对以其他方式添加的对象起作用。我说得对吗? - Andrew Carl

5
ItemsControl.ItemTemplate属性用于定义绑定数据集合中每个项目的外观...来自MSDN上的ItemsControl.ItemTemplate Property页面:

获取或设置用于显示每个项的DataTemplate。

正如您所看到的,它是DataTemplate类型的,这对于显示数据的模板是惯例...它的DataContext将自动设置为集合中的一个项目,因此在该DataTemplate中声明的控件将自动访问项目属性。有关此问题的进一步帮助,请参见MSDN上的Data Templating Overview页面。
同样,来自MSDN的ContentControl.ContentTemplate Property
获取或设置用于显示ContentControl内容的数据模板。同样,它的DataContext将自动设置为作为Content属性设置的对象。请注意,ContentControl仅具有ContentTemplate属性,而没有ItemTemplate属性,后者用于集合项...来自MSDN上的数据模板概述页面:因为myTaskTemplate是资源,所以现在可以将其用于具有采用DataTemplate类型的属性的其他控件。如上所示,对于ItemsControl对象(例如ListBox),它是ItemTemplate属性。对于ContentControl对象,它是ContentTemplate属性。

更新 >>>

为了进一步澄清这种情况,请考虑这个简单的规则:

使用 ContentTemplate 属性定义作为 ContentControlContent 属性设置的对象应该如何显示。

使用 ItemTemplate 属性定义集合控件的 应该如何显示。

这就是最简单的区别。但是,我想指出,由于这些属性都是 DataTemplate 类型,它们的值是可以互换的。

例如,假设您有一个名为 Person 的类,并且在 ListBox 中显示了一组 Person 对象。您可以声明一个 DataTemplate 作为 ListBox.ItemTemplate 属性来定义集合中每个 Person 应该如何显示。但是,如果您只想显示单个 Person,则可以使用一个 ContentControl,并将 Content 设置为 Person 类的实例,仍然可以使用相同的 DataTemplate,但设置为 ContentTemplate

多个对象:

<ListBox ItemsSource="{Binding People}" ItemTemplate="{StaticResource Template}" ... />

...

单个对象:

<ContentControl Content="{Binding Person}" 
    ContentTemplate="{StaticResource Template}" ... />

非常棒的解释。非常感谢,Sheridan。 - Andrew Carl

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接