WPF ControlTemplates must have TargetType or not?
Do ControlTemplates in WPF require a TargetType? I am restyling some controls, 开发者_运维知识库and notice that the comboboxitem, listiviewitem and listboxitem all have the same template:
<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>
Is it possible to just remove the TargetType and have one template for all three? I'm trying to do this but get strange errors and problems. I can't find any specific reference that ControlTemplates must have a type.
There isn't a requirement for a TargetType, but if you don't specify one it will behave the same as if you specify a TargetType of Control.
The main advantage that specifying a type gives you is access to all of that type's Dependency Properties in things like TemplateBindings and Triggers without having to qualify the property with the owner type.
Without a TargetType you can also lose implicit bindings, like ContentPresenter to the ContentControl.Content property.
Once you do specify a TargetType that template can only be applied to controls of that type or derived from that type. To share between different types just specify a common base class - ContentControl in this case.
The following simple templates will give the same basic result but the first is preferable and more common:
<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>
Without the type all of the Content properties need to be wired up manually:
<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>
They all derive from System.Windows.Controls.ContentControl
, so you could target that instead.
The documentation states this:
the TargetType property is required on a ControlTemplate if the template definition contains a ContentPresenter.
Although it gives no explanation for this requirement, most likely it is the reasoning given by John Bowen's answer, that you will have to manually specify basic properties like Content
that would otherwise be wired automatically.
精彩评论