This is something that has bitten me several times, so I thought I’d write it down. Maybe I’ll remember, and maybe I’ll help others when they hit this too.
The scenario happens when you want to create a new control that can have a template applied to it. Let’s start with this control definition:
1: using System;
2: using System.Windows.Controls;
3: using System.Windows.Markup;
4:
5: namespace ControlTemplate
6: {
7: [ContentProperty("Content")]
8: public class MyTemplatedControl : ContentControl
9: {
10:
11: }
12: }
Then you create your generic.xaml file under the themes folder, and you add a template for your control.
1: <ResourceDictionary
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:local="clr-namespace:ControlTemplate">
5:
6: <Style TargetType="local:MyTemplatedControl">
7: <Setter Property="Template">
8: <Setter.Value>
9: <ControlTemplate TargetType="local:MyTemplatedControl">
10: <TextBlock Text="This is my custom control template" />
11: </ControlTemplate>
12: </Setter.Value>
13: </Setter>
14: </Style>
15: </ResourceDictionary>
Then you put your custom control on a page.
1: <UserControl x:Class="ControlTemplate.Page"
2: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3: xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4: xmlns:local="clr-namespace:ControlTemplate">
5: <Grid x:Name="LayoutRoot" Background="White">
6: <local:MyTemplatedControl />
7: </Grid>
8: </UserControl>
When you run the app, you expect to see “This is my custom control template” inside the page, but you don’t. You get a plain white page. You start trying all kinds of things, trying to figure out why your textblock isn’t showing up. Eventually you beat your head against the desk a few times and then ask someone to come look to see what you’re doing wrong.
“You need to set the DefaultStyleKey property on your control.”
“Ahh… I forgot again!” You add 3 lines of code to your control, run, and poof… it works! Here’s what your control looks like now:
1: using System;
2: using System.Windows.Controls;
3: using System.Windows.Markup;
4:
5: namespace ControlTemplate
6: {
7: [ContentProperty("Content")]
8: public class MyTemplatedControl : ContentControl
9: {
10: public MyTemplatedControl()
11: {
12: this.DefaultStyleKey = typeof(MyTemplatedControl);
13: }
14: }
15: }
Without setting the DefaultStyleKey property to the control’s own type, the template doesn’t get applied. Set that property in your constructor and you’re good to go.