WPF控件模板必须有TargetType吗?

11

WPF中的ControlTemplates是否需要TargetType?我正在重新设计一些控件,注意到ComboBoxItem、ListViewItem和ListBoxItem都有相同的模板:

    <ControlTemplate x:Key="ListBoxItemCT" TargetType="{x:Type ListBoxItem}">

    <Border x:Name="Bd" 
        SnapsToDevicePixels="true" 
        Background="{TemplateBinding Background}" 
        BorderBrush="{TemplateBinding BorderBrush}" 
        BorderThickness="{TemplateBinding BorderThickness}" 
        Padding="{TemplateBinding Padding}"
        CornerRadius="1">
        <ContentPresenter x:Name="cpItemContent"
            HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
            VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
            SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
            />
    </Border>

</ControlTemplate>

是否可以仅删除TargetType,并拥有一个适用于所有三个的模板?我正在尝试这样做,但遇到了奇怪的错误和问题。我找不到任何特定的参考,说明控件模板必须具有类型。

3个回答

16

没有TargetType的要求,但如果您不指定一个,它将表现得与指定一个TargetType为Control相同。

  • 指定类型的主要优点是,您可以在TemplateBindings和Triggers等地方访问该类型的所有Dependency Properties,而无需使用属主类型限定属性。

  • 如果没有TargetType,您也可能会失去隐式绑定,例如ContentPresenter到ContentControl.Content属性的绑定。

一旦您指定了TargetType,该模板只能应用于该类型或从该类型派生的控件。要在不同类型之间共享,请指定一个公共基类--在本例中为ContentControl。

以下简单的模板将提供相同的基本结果,但第一个是更可取和更常见的:

<ControlTemplate x:Key="CommonContentTemplate" TargetType="{x:Type ContentControl}">
    <Border x:Name="Bd" 
            SnapsToDevicePixels="true" 
            Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}" 
            Padding="{TemplateBinding Padding}"
            CornerRadius="1">
        <ContentPresenter x:Name="cpItemContent"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
    </Border>
</ControlTemplate>

如果没有类型,所有的Content属性都需要手动连接:

<ControlTemplate x:Key="CommonTemplate">
    <Border x:Name="Bd" 
            SnapsToDevicePixels="true" 
            Background="{TemplateBinding Background}" 
            BorderBrush="{TemplateBinding BorderBrush}"
            BorderThickness="{TemplateBinding BorderThickness}" 
            Padding="{TemplateBinding Padding}"
            CornerRadius="1">
        <ContentPresenter x:Name="cpItemContent"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" 
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}" 
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          Content="{TemplateBinding ContentControl.Content}"
                          ContentTemplate="{TemplateBinding ContentControl.ContentTemplate}"
                          ContentTemplateSelector="{TemplateBinding ContentControl.ContentTemplateSelector}"
                          ContentStringFormat="{TemplateBinding ContentControl.ContentStringFormat}"/>
    </Border>
</ControlTemplate>

谢谢!我花了最近两周时间制作了这个大的依赖属性图,所以这很有道理。我猜我本来可以试一下的... :) - dex3703
这就可以解释我遇到的奇怪错误(关于找不到从Control派生的东西)以及为什么内容不会显示出来。 - dex3703

2

它们都派生自 System.Windows.Controls.ContentControl,因此您可以针对该目标进行操作。


谢谢!与上面的答案相同,但更简洁。 :) - dex3703

2
这段文本的意思是:“

文档中说明:

如果模板定义包含 ContentPresenter,那么 ControlTemplate 上的 TargetType 属性是必需的

虽然它没有解释这个要求的原因,但很可能是由John Bowen's answer给出的理由,即您将不得不手动指定基本属性(如 Content),否则这些属性会被自动连接。”


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