WPF inherited property change notification

358 views Asked by At

How to make an inherited property changes to update a custom control?

I have defined view model Circle with property Radius as:

public class Circle : Freezable
{
    public static readonly DependencyProperty RadiusProperty =
        DependencyProperty.Register("Radius", typeof(double), typeof(Circle),
            new FrameworkPropertyMetadata(10.0));

    public double Radius
    {
        get { return (double)GetValue(RadiusProperty); }
        set { SetValue(RadiusProperty, value); }
    }        

    protected override Freezable CreateInstanceCore() =>
        new Circle();            
}

Now comes the control itself with couple of properties: Direct (AffectsRender) and Inherited (AffectsRender|Inherits) of type Circle:

class View : FrameworkElement
{
    // Inherited

    public static readonly DependencyProperty InheritedProperty =
        DependencyProperty.RegisterAttached(
            "Inherited", typeof(Circle), typeof(View),
                new FrameworkPropertyMetadata(
                    null, 
                    FrameworkPropertyMetadataOptions.AffectsRender | 
                    FrameworkPropertyMetadataOptions.Inherits));

    public static void SetInherited(UIElement element, Circle value)
    {
        element.SetValue(InheritedProperty, value);
    }

    public static Circle GetInherited(UIElement element)
    {
        return (Circle)element.GetValue(InheritedProperty);
    }

    public Circle Inherited
    {
        get { return GetInherited(this); }
        set { SetInherited(this, value); }
    }

    // Direct

    public static readonly DependencyProperty DirectProperty = 
        DependencyProperty.RegisterAttached(
            "Direct", typeof(Circle), typeof(View),
                new FrameworkPropertyMetadata(
                    null, 
                    FrameworkPropertyMetadataOptions.AffectsRender));

    public static void SetDirect(UIElement element, Circle value)
    {
        element.SetValue(DirectProperty, value);
    }

    public static Circle GetDirect(UIElement element)
    {
        return (Circle)element.GetValue(DirectProperty);
    }

    public Circle Direct
    {
        get { return GetDirect(this); }
        set { SetDirect(this, value); }
    }

    // Render

    protected override void OnRender(DrawingContext drawingContext)
    {
        base.OnRender(drawingContext);
        drawingContext.DrawEllipse(Brushes.Black, null, 
            new Point(), Inherited.Radius, Direct.Radius);
    }
}

Now the question. This way:

<local:View x:Name="_view">
    <local:View.Inherited>
        <local:Circle/>
    </local:View.Inherited>
    <local:View.Direct>
        <local:Circle/>
    </local:View.Direct>
</local:View>

The following code re-renders the view:

    private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        _view.Inherited.Radius+=10;
    }

    private void Window_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
    {
        _view.Direct.Radius++;
    }

But when XAML looks this way:

<local:View.Inherited>
    <local:Circle/>
</local:View.Inherited>
<local:View x:Name="_view">
    <local:View.Direct>
        <local:Circle/>
    </local:View.Direct>
</local:View>

This line stops updating the screen:

_view.Inherited.Radius+=10;

What did I do wrong?

0

There are 0 answers