Привязка свойства зависимостей и обновление к пользовательскому элементу управления - оно обновляется, но, видимо, не в обе стороны? - PullRequest
3 голосов
/ 05 января 2012

ViewModel:

public class MyViewModel : INotifyPropertyChanged
{
    public string MyText { ... }
}

XAML:

<my:MySpecialTextBox Text="{Binding MyText}" />

Пользовательский элемент управления:

public class MySpecialTextBox : TextBox
{
    static MySpecialTextBox()
    {
        TextProperty.OverrideMetadata(typeof(MySpecialTextBox),
            new FrameworkPropertyMetadata
            {
                BindsTwoWayByDefault = true,
                DefaultValue = string.empty,
                PropertyChangedCallback = OnTextPropertyChanged
            });
    }

    private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var control = d as MySpecialTextBox;

        if (control != null)
        {
            control.Text = SomeAdjustedValue((string)e.NewValue);
        }
    }
}

Проблема заключается в том, что, хотя свойство DependencyProperty вЭлемент управления корректируется должным образом, он не обновляет ViewModel.Я понимаю, что этот кажется таким, как если бы он был CoerceValueCallback из-за именования SomeAdjustedValue, но Coercion также не изменяет значение ViewModel.Я не могу обновить значение в моем ViewModel, если оно было триггером для обратного вызова OnTextPropertyChanged для начала ... Я сделал отладочную трассировку, и она не проходит через ViewModel во второй раз с новым значением.Не уверен, что нужно сделать, чтобы это исправить.

Ответы [ 4 ]

0 голосов
/ 26 апреля 2012

Вы пробовали это?

private static void OnTextPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var control = d as MySpecialTextBox;

    if (control != null)
    {
        control.SetCurrentValue(TextBox.TextProperty, SomeAdjustedValue((string)e.NewValue));
    }
}

Метод SetCurrentValue () обеспечивает сохранение привязки, где простой SetValue (), который вызывается под капотом, если вы используете установщик свойства Textудалит любую привязку.

0 голосов
/ 05 января 2012

Вначале отказ от ответственности - это пахнет логикой, которая должна жить внутри ViewModel, а не в привязке пользовательского интерфейса.

Тем не менее, если вы настроены на это таким образом, я думаю, что вам нужносначала проверьте, отличается ли «Скорректированное значение» от уже предоставленного (чтобы избежать бесконечного зацикливания), затем используйте DependencyProperty.SetValue , чтобы установить значение свойства зависимости для элемента управления, а не просто установить егоСвойство текста.

0 голосов
/ 05 января 2012

TextBox.Text - это привязка, и вы заменяете эту привязку строковым значением в OnTextPropertyChanged, поэтому свойство больше не привязано к вашему источнику данных.

Я думаю, вам нужно получитьпривязка к TextBox.Text и обновление источника, однако я бы не рекомендовал этого делать, поскольку вы будете смешивать свой слой бизнес-логики со слоем пользовательского интерфейса.

Если вам нужно только отображать некоторое пользовательское форматирование,будет делать это в конвертере, чтобы он не изменил значение вашего источника данных.Если вы хотите изменить фактическое значение источника данных, я бы сделал это с помощью события PropertyChanged ViewModel

0 голосов
/ 05 января 2012

В FrameworkPropertyMetadata есть разные конструкторы, которые вы можете использовать.Используйте один с параметром FrameworkPropertyMetadataOptions.Параметр FrameworkPropertyMetadataOptions.BindsTwoWayByDefault по умолчанию включает двухстороннее связывание, в противном случае это только один способ.

Редактировать: Итак, я должен прекратить попытки отвечать на вопросы, когда я болен.

...