1

I've created a custom control similar to a button. I want to override his default properties, but it works strangely.

UserControl Xaml

<UserControl x:Class="project.MyButton" 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="50" d:DesignWidth="50"> <Grid> <Ellipse x:Name="structure" Fill="Black" Stroke="White" StrokeThickness="2"/> <Label x:Name="content" Content="&#xE081;" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontFamily="Segoe MDL2 Assets" FontWeight="Bold" FontSize="16"/> </Grid> </UserControl> 

UserControl Code Behind (C#)

 /// <summary>A simple custom button.</summary> public partial class MyButton : UserControl { /// <summary>Background color.</summary> public new Brush Background { get => structure.Fill; set => structure.Fill = value; } /// <summary>Foreground color.</summary> public new Brush Foreground { get => content.Foreground; set => content.Foreground = value; } /// <summary>Stroke color.</summary> public Brush Stroke { get => structure.Stroke; set => structure.Stroke = value; } /// <summary>Stroke thickness.</summary> public double StrokeThickness { get => structure.StrokeThickness; set => structure.StrokeThickness = value; } /// <summary>Font family.</summary> public new FontFamily FontFamily { get => content.FontFamily; set => content.FontFamily = value; } /// <summary>Font weight.</summary> public new FontWeight FontWeight { get => content.FontWeight; set => content.FontWeight = value; } /// <summary>Font size.</summary> public new double FontSize { get => content.FontSize; set => content.FontSize = value; } /// <summary>Content.</summary> public new object Content { get => content.Content; set => content.Content = value; } /// <summary>Inizialize new <see cref="MyButton"/>.</summary> public MyButton() { InitializeComponent(); } } 

Result

Custom round button

But, when I try to set the Background property it colors the background of the control, and not the ellipse, when I try to set the Content, it overrides the button, etc...

Example: Background="Red"

Background Red

3
  • 3
    Instead of hiding base class properties you should just use them, and bind the internal elements' properties to them, e.g. <Ellipse Fill="{Binding Background, RelativeSource={RelativeSource AncestorType=UserControl}}"/>. Commented Aug 14, 2018 at 8:37
  • Works for all properties except than the Background. It colors the entire control, other than the ellipse. There is a way to color only the ellipse, by reusing this property? Commented Aug 14, 2018 at 9:21
  • You'd have to replace the UserControl's ControlTemplate by one that only contains a ContentPresenter. Commented Aug 14, 2018 at 9:33

2 Answers 2

3

You could define a ControlTemplate for the UserControl:

<UserControl x:Class="project.MyButton" 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" xmlns:local="clr-namespace:WpfApp4" mc:Ignorable="d" d:DesignHeight="50" d:DesignWidth="50"> <UserControl.Template> <ControlTemplate TargetType="UserControl"> <Grid> <Ellipse x:Name="structure" Fill="{TemplateBinding Background}" Stroke="White" StrokeThickness="2"/> <Label x:Name="content" Content="{TemplateBinding Content}" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontFamily="Segoe MDL2 Assets" FontWeight="Bold" FontSize="16"/> </Grid> </ControlTemplate> </UserControl.Template> </UserControl> 

Using a TemplateBinding for a property of en element in the template, you can set this property of the UserControl to change the property of the element in the template:

<local:Button Background="Red" Content="&#xE081;" /> 
Sign up to request clarification or add additional context in comments.

Comments

0

UserControl has its Backround and Content properties, which are wrappers for DependencyProperties.

You are trying to shadow them using new keyword before property, but it fails. (set a breakpoint in setter: breakpoint is never hit)

When setting Background="smth" or Content="smth" from xaml, base properties are detected, and additionally WPF doesn't use wrapper properties, it uses DependencyObject.SetValue() directly. And setting base Content simply removes existing Grid with Ellipse.

Rename Background -> CustomBackground, Content -> CustomContent and set them. Then MyButton will work.

Much better is to reuse base Content and Background though (bind them to Ellipse and Lable in MyButton xaml).

Comments