2

I've been trying to follow a StackOverflow post as well as the official documentation on MSDN to implement a read-only dependency property on a sub-class of the WPF Canvas control to be used by a ViewModel.

I have defined my sub-class of Canvas as:

public class LayerCanvas : Canvas
{
    private static readonly DependencyPropertyKey ReadOnlyCursorLocationPropertyKey =
        DependencyProperty.RegisterReadOnly("CursorLocation", typeof(Point), typeof(LayerCanvas),
        new PropertyMetadata(new Point(0, 0)));

    public static readonly DependencyProperty CursorLocationProperty =
        ReadOnlyCursorLocationPropertyKey.DependencyProperty;

    public LayerCanvas()
        : base()
    {

    }

    public Point CursorLocation
    {
        get { return (Point)GetValue(CursorLocationProperty); }
        private set { SetValue(ReadOnlyCursorLocationPropertyKey, value); }
    }

    protected override void OnMouseMove(MouseEventArgs e)
    {
        base.OnMouseMove(e);
        this.CursorLocation = e.GetPosition(this);
    }
}

Bound to the property in View's XAML as:

<local:LayerCanvas CursorLocation="{Binding Path=CursorLocation, Mode=OneWayToSource}" ... />

Implemented the property in the ViewModel as:

public Point CursorLocation
{
    get { return this.cursorLocation; }
    set
    {
        this.cursorLocation = value;
        // ... logic ...
    }
}

I receive the error "CursorLocation cannot be data-bound." in the View's XAML and a compile-time error "The property 'LayerCanvas.CursorLocation' cannot be set because it does not have an accessible set accessor." which I thought Mode=OneWayToSource would fix. I am using a read-only dependency property instead of using the code-behind to try and keep a clean MVVM implementation. Is this the correct approach?

Community
  • 1
  • 1
Noren
  • 793
  • 3
  • 10
  • 23

1 Answers1

4

From MSDN:

By virtue of not being settable, read-only dependency properties aren't appropriate for many of the scenarios for which dependency properties normally offer a solution (namely: data binding, directly stylable to a value, validation, animation, inheritance).

Even if you would make the setter of your property public, data binding would not work. So the answer is No, this is not the correct approach. The property must not be read-only in order to support data binding, even if the binding is OneWayToSource only.

Clemens
  • 123,504
  • 12
  • 155
  • 268