Search code examples
.netwpftemplatescontroltemplatetargettype

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.


Solution

  • 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>