Randy Voet
Randy Voet

Reputation: 3830

using a ControlTemplate to reduce duplication between multiple UserControls

I have multiple UserControl XAML files that use a similar structure. I want to remove this duplication and thought to use a Style that overrides the Template of the UserControl (and then use ContentPresenter for the custom part).

But apparently the Template of a UserControl can't be overwritten.

How do I this the clean way? Derive from something else then UserControl?

<UserControl x:Class="Class1">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <sdk:Label Grid.Row="0" Content="Title1" Style="{StaticResource Header1}" />
    <Border Grid.Row="1">
    ...
</UserControl>

<UserControl x:Class="Class2">
  <Grid>
    <Grid.RowDefinitions>
      <RowDefinition Height="Auto"/>
      <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <sdk:Label Grid.Row="0" Content="Title2" Style="{StaticResource Header1}" />
    <Border Grid.Row="1">
    ...
</UserControl>

Upvotes: 1

Views: 91

Answers (2)

Andrew
Andrew

Reputation: 905

You could define a custom control like this. (I'm not sure if you need to specify the Title separate from the content, but here it is just in case.)

public class MyControl : ContentControl
{
    public static readonly DependencyProperty TitleProperty =
        DependencyProperty.Register("Title", typeof(string), typeof(MyControl), new PropertyMetadata(null));

    public string Title
    {
        get { return (string)GetValue(TitleProperty); }
        set { SetValue(TitleProperty, value); }
    }

    // ... other properties ...
}

Then define its template:

<ControlTemplate x:Key="MyControlTemplate" TargetType="mynamespace:MyControl">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <sdk:Label Grid.Row="0" Content="{TemplateBinding Title}" Style="{StaticResource Header1}" />
        <Border Grid.Row="1">
            <ContentPresenter />
        ...
    </Grid
</ControlTemplate>

You could then define a default style, as shown here. (Alternatively, you could give it an x:Key and explicitly set the style each time you use MyControl. You could also just set the Template property each time you use MyControl, instead of specifying this Style at all.)

<Style TargetType="mynamespace:MyControl">
    <Setter Property="Template" Value="{StaticResource MyControlTemplate}" />
</Style>

Then to use it:

<mynamespace:MyUserControl Title="Title1">
    <!-- Content here -->
</mynamespace:MyUserControl>

<mynamespace:MyUserControl Title="Title2">
    <!-- Content here -->
</mynamespace:MyUserControl>

Upvotes: 2

EugenSoft
EugenSoft

Reputation: 536

Perhaps you need to use ContentControl as a base class for your controls (It should be not User Control but Custom Control).

Then you'll be able to define ControlTemplate and use ContentPresenter within it. Than you need to set Content property for your controls to define control's content.

Upvotes: 0

Related Questions