Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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.

like image 502
dex3703 Avatar asked Sep 03 '10 00:09

dex3703


2 Answers

For completeness, note that 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.

like image 186
StayOnTarget Avatar answered Nov 05 '22 17:11

StayOnTarget


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>
like image 25
John Bowen Avatar answered Nov 05 '22 15:11

John Bowen