wpfbindingpropertiesreadonlyactualwidth

WPF: Binding to readonly property in code


I'm currently doing some rescaling on data in a valueconverter whenever a panel is redrawn. I want to move some of this processing to the viewmodel as the most of the processing only occurs if the control size or a few other properties change.

To ensure the rescaled data looks acceptable I need the ActualWidth of the container in the viewmodel. I want to bind it to a property of the viewmodel one way so when it changes I can trigger the rescaling processing.

All the examples I could find bind a CLR or dependency property to an element rather than the other way and I'm clearly missing something in my understanding to work out how I should do it. I have have tried a few different things setting up the binding but am just not getting it right.

Any hints? thanks.

In MyView XAML:

<myItemsControl/>

In MyView code behind, something like:

Binding b = new Binding(MyWidthProperty);
b.Mode = BindingMode.OneWay;
b.Source = myItemsControl.Name;
.........?

and

public static readonly DependencyProperty MyWidthProperty = 
DependencyProperty.Register( "MyWidth", typeof(Double), typeof(MyViewModel));

In MyViewModel:

    public Double MyWidth{
        get { return _myWidth; }
        set { _myWidth = value; ViewChanged(this); } }

Solution

  • You cannot do it this way. You cannot set a Binding to ActualWidth, as it's read-only.

    You can only set a binding to MyWidth. But for this, you need first to convert MyWidth into a DependencyProperty. Then you will be able to do something like

    Binding b = new Binding("ActualWidth") { Source = myItemsControl };
    this.SetBinding(MyViewModel.MyWidthProperty, b);
    

    For converting into a dependency property, you'll need to replace your definition of MyWidth with the following:

    public static readonly DependencyProperty MyWidthProperty =
        DependencyProperty.Register("MyWidth", typeof(double), typeof(MyViewModel),
                                            new UIPropertyMetadata(
                                                0.0,
                                                (d, e) =>
                                                {
                                                    var self = (MyViewModel)d;
                                                    ViewChanged(self);
                                                }));
    

    But be careful with dependency properties; it's better to read the documentation first.

    Edit: You would also need to define the property this way:

    public double MyWidth
    {
        get { return (double)this.GetValue(MyWidthProperty); }
        set { this.SetValue(MyWidthProperty, value); } 
    }