WPF: привязка к свойству только для чтения в коде

В настоящее время я выполняю некоторое масштабирование данных в преобразователе значений всякий раз, когда панель перерисовывается. Я хочу переместить часть этой обработки в модель представления, так как большая часть обработки происходит только в том случае, если изменяется размер элемента управления или несколько других свойств.

Чтобы масштабированные данные выглядели приемлемо, мне нужен ActualWidth контейнера в модели представления. Я хочу привязать его к свойству модели представления одним способом, чтобы при его изменении я мог запустить обработку масштабирования.

Все примеры, которые я мог найти, привязывают CLR или свойство зависимости к элементу, а не наоборот, и мне явно чего-то не хватает в моем понимании, чтобы понять, как я должен это сделать. Я пробовал несколько разных вещей, настраивающих привязку, но я просто не понимаю это правильно.

Любые подсказки? Спасибо.

В MyView XAML:

<myItemsControl/>

В коде MyView позади что-то вроде:

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

а также

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

В MyViewModel:

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

person DocGigawatts    schedule 15.11.2010    source источник
comment
Я бы прочитал немного больше о DependencyProperty. В частности, ваш объект должен быть DependencyObject, и вы должны использовать методы GetValue и SetValue для доступа к базовому значению. Наконец, вы не получите вызов установщика, когда система привязки обращается к DP (этот момент легко пропустить), поэтому вам нужно будет передать обработчик Changed как часть вызова Register.   -  person Dan Bryant    schedule 15.11.2010


Ответы (1)


Вы не можете сделать это таким образом. Вы не можете установить Binding в ActualWidth, так как он доступен только для чтения.

Вы можете установить привязку только к MyWidth. Но для этого вам нужно сначала преобразовать MyWidth в DependencyProperty. Тогда вы сможете сделать что-то вроде

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

Для преобразования в свойство зависимостей вам необходимо заменить определение MyWidth следующим:

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

Но будьте осторожны со свойствами зависимостей; сначала лучше прочитать документацию.

Изменить: вам также нужно будет определить свойство следующим образом:

public double MyWidth
{
    get { return (double)this.GetValue(MyWidthProperty); }
    set { this.SetValue(MyWidthProperty, value); } 
}
person Vlad    schedule 15.11.2010
comment
Спасибо за этот очень полный ответ. Избегал свойств зависимостей из-за неприятного синтаксиса, в то время как я добился прогресса в остальной части WPF. Первый раз, когда я был вынужден использовать его... похоже, мне лучше взять их на себя, так как я ожидаю, что это произойдет снова. - person DocGigawatts; 16.11.2010