Libor
Libor

Reputation: 3303

WPF Custom Control Property Setter

I have a very simple Button-based control that displays an ellipse with color taken from custom dependency control called "Brush".

The template displays ellipse with proper color, but the Setters in Trigger do not recognize the "Brush" property (errors highlighted in the XAML file below).

How to access the "Brush" property in the setter so I can change its value on MouseOver?

XAML:

<Button x:Class="WpfTest.EllipseButton"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:WpfTest"
        Style="{DynamicResource localStyle}"
        Name="ellipseButton">

  <Button.Resources>
    <Style x:Key="localStyle"
           TargetType="local:EllipseButton">
      <Style.Setters>
        <Setter Property="Template">
          <Setter.Value>
            <ControlTemplate>
              <Grid>
                <Ellipse Fill="{Binding ElementName=ellipseButton, Path=Brush}" />
              </Grid>
            </ControlTemplate>
          </Setter.Value>
        </Setter>
      </Style.Setters>
      <Style.Triggers>
        <Trigger Property="IsMouseOver"
                 Value="True">

          <!-- ERROR HERE: The property "Brush" is not a dependency property. -->
          <Setter Property="Brush"
                  Value="Blue" />
          <!-- ERROR HERE: The "BrushProperty" is not recognized or is not accessible.  -->
          <Setter Property="BrushPropety"
                  Value="Blue" />

        </Trigger>
      </Style.Triggers>
    </Style>
  </Button.Resources>
  <Grid>
  </Grid>
</Button>

code-behind:

public partial class EllipseButton : Button
{
    public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
        "Fill",
        typeof(Brush),
        typeof(EllipseButton),
        new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Gray)));

    public Brush Brush
    {
        get
        {
            return (Brush)GetValue(BrushProperty);
        }
        set
        {
            SetValue(BrushProperty, value);
        }
    }

    public EllipseButton()
    {
        InitializeComponent();
    }
}

Upvotes: 1

Views: 5814

Answers (2)

Libor
Libor

Reputation: 3303

Okay, several things needed to be done:

1) Rename dependency property name to "Brush" (it was wrongly named "Fill") - thanks to HighCore

2) When the control is used in code, remove setting the "Brush" property - the local value overriden the setters from style.

3) Move the style from custom control to higher level (e.g. under "Themes\Generic.xaml")

4) Remove x:Key attribute from the style and keep just the type name (still don't know why...)

5) Add default value of the "Brush" property to the style setter (again, not sure why...)

Fixed EllipseButton.xaml:

<Button x:Class="WpfTest.EllipseButton" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
    <Grid/>
</Button>

fixed code-behind:

public partial class EllipseButton
{
    public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
        "Brush",
        typeof(Brush),
        typeof(EllipseButton),
        new FrameworkPropertyMetadata(null));

    public Brush Brush
    {
        get
        {
            return (Brush)GetValue(BrushProperty);
        }
        set
        {
            SetValue(BrushProperty, value);
        }
    }

    public EllipseButton()
    {
        InitializeComponent();
    }
}

fixed style (Generic.xaml):

<ResourceDictionary
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:WpfTest">

    <Style TargetType="local:EllipseButton">
        <Style.Setters>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate>
                        <Grid>
                            <Ellipse Fill="{Binding ElementName=ellipseButton, Path=Brush}"/>
                        </Grid>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
            <Setter Property="Brush" Value="Pink"/>
        </Style.Setters>
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Brush" Value="Red"/>
            </Trigger>
        </Style.Triggers>
    </Style>

</ResourceDictionary>

Upvotes: 1

Fede
Fede

Reputation: 44038

Your property is called "Fill" not "Brush":

public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
        "Fill", //Error is here
        typeof(Brush),
        typeof(EllipseButton),
        new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Gray)));

Change that to:

public static readonly DependencyProperty BrushProperty = DependencyProperty.Register(
        "Brush", 
        typeof(Brush),
        typeof(EllipseButton),
        new FrameworkPropertyMetadata(new SolidColorBrush(Colors.Gray)));

Upvotes: 1

Related Questions