100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

Control Templates

How ControlTemplate redefines a control's entire visual structure while preserving its behavior, using TemplateBinding and named parts.

ControlsAdvanced11 min readJul 10, 2026
Analogies

Restructuring a Control's Visual Tree

While a Style with Setters can adjust properties like Background or FontSize, a ControlTemplate replaces the entire visual tree a control renders — you can turn a CheckBox into a toggle-switch look, or a Button into a hexagonal shape, without touching a single line of the control's C# logic. Because WPF controls are lookless, ControlTemplate is where the actual rendering lives; the default templates for every built-in control are themselves just XAML, visible in the theme resource files, which is why 'restyle instead of subclass' is the idiomatic WPF approach for visual customization.

🏏

Cricket analogy: Rebuilding a stadium's stand layout (seating, roof, sightlines) while the game's laws stay identical is like a ControlTemplate reshaping a control's visuals while its click/behavior logic remains untouched.

TemplateBinding and Named Parts

Inside a ControlTemplate, TemplateBinding (or the more capable {Binding RelativeSource={RelativeSource TemplatedParent}}) wires template elements back to properties on the control instance being templated — so a Border's Background inside a Button's template can pull from the Button's own Background property set by the consumer. Certain controls expect specific named parts inside their template, marked with x:Name and referenced by TemplatePartAttribute on the control class (e.g. Slider expects a 'PART_Track', ScrollBar expects 'PART_Track' with Thumb children) — omitting a required part silently breaks that control's interactive behavior even though it compiles fine.

🏏

Cricket analogy: TemplateBinding is like a stadium's electronic scoreboard automatically pulling live figures from the official scorer's system — the display (template) always reflects whatever value the source (control property) currently holds.

Triggers Inside a ControlTemplate

A ControlTemplate typically includes Triggers or VisualStateManager groups to react to the control's own state changes — IsMouseOver, IsPressed, IsEnabled — since without them a templated Button would look static and unresponsive to interaction. A Trigger inside Template.Triggers is scoped to that template instance and can only set properties on elements within the same template (or via TargetName), which is a key difference from a Style's own Triggers collection that applies at the control level.

🏏

Cricket analogy: A stadium's crowd-noise system automatically ramping up when a wicket falls (IsPressed-like state) versus staying calm during a dot ball is like a ControlTemplate trigger reacting to the control's interaction state.

xml
<Style TargetType="Button" x:Key="HexButtonStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="Button">
                <Grid>
                    <Path x:Name="HexShape"
                          Data="M50,0 100,25 100,75 50,100 0,75 0,25 Z"
                          Fill="{TemplateBinding Background}"
                          Stretch="Fill"/>
                    <ContentPresenter HorizontalAlignment="Center"
                                      VerticalAlignment="Center"
                                      Content="{TemplateBinding Content}"/>
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter TargetName="HexShape" Property="Fill" Value="OrangeRed"/>
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter TargetName="HexShape" Property="Fill" Value="DarkRed"/>
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

ContentPresenter (for ContentControl-derived controls like Button) and ItemsPresenter (for ItemsControl-derived controls like ListBox) are the standard placeholder elements inside a ControlTemplate that tell WPF where to insert the control's actual Content or item panel. Forgetting them means the template renders your chrome but never shows the control's real content.

If a control class declares required template parts via [TemplatePart(Name = "PART_Track", Type = typeof(Track))] (as Slider does), omitting that named element from a custom ControlTemplate compiles without error but breaks the control's interactivity at runtime — always check a control's documentation for required PART_ names before fully replacing its template.

  • ControlTemplate replaces a control's entire visual tree while its behavioral logic (in C#) stays unchanged.
  • TemplateBinding (or TemplatedParent RelativeSource binding) wires template elements to the control instance's own properties.
  • Some controls require specific named parts (PART_xxx) for their interactive logic to function correctly.
  • ContentPresenter/ItemsPresenter mark where the control's actual content or items render inside the template.
  • Triggers inside ControlTemplate.Triggers react to control state (IsMouseOver, IsPressed) and can target named elements via TargetName.
  • 'Restyle, don't subclass' is the idiomatic WPF approach since all built-in controls are already lookless.

Practice what you learned

Was this page helpful?

Topics covered

#NET#WPFWindowsPresentationFoundationStudyNotes#MicrosoftTechnologies#ControlTemplates#Control#Templates#Restructuring#Visual#StudyNotes#SkillVeris