Search code examples
c#wpfxamluser-controls

WPF Creating a base UserControl that can be used to extend another UserControl


I'm quite new to WPF and I wanted to create a base UserControl, thats reusable.

For example I've got this UserControl: TestBase

<UserControl x:Class="UserControls.TestBase"
             xmlns=""
             xmlns:x=""
             xmlns:mc="" 
             xmlns:d="" 
             xmlns:local="clr-namespace:UserControls"
             mc:Ignorable="d" 
             Style="{StaticResource TestBaseDefault}"
             d:DesignHeight="150" d:DesignWidth="150">
    <UserControl.Template>
        <ControlTemplate>
            <Grid>
                <TextBlock Text="Base Text" 
                           HorizontalAlignment="Center" VerticalAlignment="Center"
                           Foreground="White"/>
            </Grid>
        </ControlTemplate>
    </UserControl.Template>
</UserControl>

The UserControl TestBase is using this Style (TestBaseDefault):

<Style x:Key="TestBaseDefault" TargetType="{x:Type UserControl}">
    <Setter Property="Margin" Value="5"/>
    <Setter Property="VerticalAlignment" Value="Top"/>
        
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type UserControl}">
                <Border CornerRadius="10" BorderThickness="2" BorderBrush="{StaticResource ForegroundBrush}" Background="{StaticResource BackgroundBrush}" Padding="10">
                    <ContentPresenter/>
                </Border>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Now I wanted to create a second UserControl that extends from the TestBase.

Which curerntly looks like this: Test1

<UserControl x:Class="UserControls.Test1"
                xmlns=""
                xmlns:x=""
                xmlns:mc="" 
                xmlns:d="" 
                xmlns:local="clr-namespace:UserControls"
                x:Name="self"
                mc:Ignorable="d" 
                d:DesignHeight="150" d:DesignWidth="150">
    <Grid>

        <TextBlock Text="Overriden Text" 
                   HorizontalAlignment="Center" VerticalAlignment="Center"
                   Foreground="White"/>
    </Grid>
</UserControl>

Had to remove the links from the UserControls, else I couldnt publish the question.

What I want to know, is it possible to extend the Test1 from the TestBase instead of the UserControl, so that I can access the properties from the base, use the Style from it and override the default content?

If not, is there some other way it can be achieved?


Solution

  • The base class should be defined as a class without any XAML:

    public class TestBase : UserControl
    {
        public TestBase()
        {
            Style = FindResource("TestBaseDefault") as Style;
        }
    }
    

    You can then use it as the base class for Test1.

    Test1.xaml:

    <local:TestBase x:Class="WpfApp1.Test1"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 mc:Ignorable="d" 
                 d:DesignHeight="450" d:DesignWidth="800">
        <Grid>
    
            <TextBlock Text="Overriden Text" 
                       HorizontalAlignment="Center" VerticalAlignment="Center"
                       Foreground="White"/>
        </Grid>
    </local:TestBase>
    

    Test1.xaml.cs:

    public partial class Test1 : TestBase
    {
        public Test1()
        {
            InitializeComponent();
        }
    }
    

    You cannot override a template so the template you have defined in TestBase.xaml should be removed or merged into the template that the style defines.