11

WPF 中的 ControlTemplates 是否需要 TargetType?我正在重新设置一些控件的样式,并注意到 comboboxitem、listiviewitem 和 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 并为所有三个模板提供一个模板?我正在尝试这样做,但会遇到奇怪的错误和问题。我找不到 ControlTemplates 必须具有类型的任何特定参考。

4

3 回答 3

15

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

  • 指定类型的主要优点是可以访问该类型的所有依赖属性,例如 TemplateBindings 和 Triggers,而无需使用所有者类型限定属性。

  • 如果没有 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>
于 2010-09-03T03:45:20.603 回答
2

它们都派生自System.Windows.Controls.ContentControl,因此您可以改为定位它。

于 2010-09-03T00:08:45.523 回答
1

为了完整起见,请注意文档说明了这一点:

如果模板定义包含 ContentPresenter,则 ControlTemplate需要TargetType 属性。

尽管它没有对此要求进行解释,但很可能是John Bowen 的答案给出的推理,即您必须手动指定基本属性Content,否则会自动连接。

于 2020-08-05T11:33:38.410 回答