Привязка OneWay перестает работать после ручного обновления целевого объекта

У меня есть такой код привязки WPF:

TestModel source = new TestModel();
TestModel target = new TestModel();

Bind(source, target, BindingMode.OneWay);

source.Attribute = "1";
AssertAreEqual(target.Attribute, "1");

target.Attribute = "foo";

source.Attribute = "2";
AssertAreEqual(target.Attribute, "2");

Второе утверждение неверно! Мне это кажется странным.

Кроме того, я попробовал OneWayToSource вместо OneWay, и все работает, как ожидалось.

Bind(source, target, BindingMode.OneWayToSource);

target.Attribute = "1";
AssertAreEqual(source.Attribute, "1");

source.Attribute = "foo";

target.Attribute = "2";
AssertAreEqual(source.Attribute, "2");

Другие детали:

void Bind(TestModel source, TestModel target, BindingMode mode)
{
    Binding binding = new Binding();
    binding.Source = source;
    binding.Path = new PropertyPath(TestModel.AttributeProperty);
    binding.Mode = mode;
    BindingOperations.SetBinding(target, TestModel.AttributeProperty, binding);
}

class TestModel : DependencyObject
{
    public static readonly DependencyProperty AttributeProperty =
        DependencyProperty.Register("Attribute", typeof(string), typeof(TestModel), new PropertyMetadata(null));

    public string Attribute
    {
        get { return (string)GetValue(AttributeProperty); }
        set { SetValue(AttributeProperty, value); }
    }
}

Что не так с моим кодом?

Ответов (4)

Решение

Установка target.Attribute = "foo"; очистил переплет.

MSDN:

Не только динамические ресурсы и привязки работают с тем же приоритетом, что и локальное значение, они действительно являются локальным значением, но со значением, которое является отложенным. Одним из следствий этого является то, что если у вас есть динамический ресурс или привязка для значения свойства, любое локальное значение, которое вы устанавливаете впоследствии, полностью заменяет динамическую привязку или привязку. Даже если вы вызовете ClearValue, чтобы очистить локально установленное значение, динамический ресурс или привязка не будут восстановлены. Фактически, если вы вызываете ClearValue для свойства, имеющего динамический ресурс или привязку (без «буквального» локального значения), они также очищаются вызовом ClearValue.

Не эксперт по связыванию, но я считаю, что вы сталкиваетесь с проблемами приоритета свойств зависимостей WPF. Вероятно, что установка значения напрямую имеет приоритет над значением привязки. Вот почему он отменяет привязку.

Вот полный список свойств зависимостей: http://msdn.microsoft.com/en-us/library/ms743230.aspx

Если вы установите Binding Mode на OneWay, это означает, что привязка работает только одним способом: цель обновляется при изменении источника.

Но целью должно быть свойство зависимости, а имеющийся у вас код - это свойство CLR .NET. Вы должны установить значение для цели, используя зарегистрированное имя свойства зависимости, а не просто обычное имя свойства .NET. Ответ Джареда совершенно правильный, это может вызвать путаницу при разрешении конфликта между свойством зависимости WPF и обычным свойством .NET CLR.

Если вы следуете соглашению, свойство зависимости должно быть в форме «имя свойства» + свойство.

Пример: TextProperty - это свойство зависимости "Text" TextBox. Вызов их в коде должен быть:

TextBox1.TextProperty="value";

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

http://msdn.microsoft.com/en-us/library/ms743643.aspx

Пример: TextProperty - это свойство зависимости "Text" TextBox. Вызов их в коде должен быть:

TextBox1.TextProperty = "значение";

Свойства WPF можно установить двумя способами: путем вызова метода DependencyObject.SetValue (например, instance.SetValue (TextProperty, «некоторый текст»)) или с помощью CLR Wrapper (например, instance.Text = «некоторый текст»).

TextBox.TextProperty - это статический объект DependencyProperty, поэтому вы не можете присвоить строковое значение ссылочному типу.