Свойство WPF CheckBox IsChecked не соответствует значению источника привязки - PullRequest
2 голосов
/ 08 марта 2010

В моем приложении WPF у меня есть CheckBox, чье значение IsChecked связано со свойством в моей модели представления. Обратите внимание, что я закомментировал фактическую строку, которая устанавливает значение в моей модели представления. Это стандартный шаблон:

View.xaml

<CheckBox IsChecked="{Binding Path=SomeProperty}" />

ViewModel.cs

public bool SomeProperty
{
    get { return this.mSomeProperty; }
    set
    {
        if (value != this.mSomeProperty)
        {
            //this.mSomeProperty = value;
            NotifyPropertyChanged(new PropertyChangedEventArgs("SomeProperty"));
        }
    }
}

Когда я нажимаю CheckBox, я ожидаю, что ничего не произойдет, так как значение this.mSomeProperty не устанавливается. Однако наблюдаемое поведение таково, что CheckBox проверяется и не проверяется независимо от значения this.mSomeProperty.

Что происходит? Почему моя привязка не заставляет CheckBox показывать, какая базовая модель данных установлена?

1 Ответ

3 голосов
/ 08 марта 2010

Поскольку WPF автоматически не перезагружается из источника привязки после обновления источника. Вероятно, это отчасти связано с производительностью, но в основном для обработки ошибок связывания. Например, рассмотрим TextBox, связанный с целочисленным свойством. Предположим, что пользователь вводит 123A. WPF хочет продолжить показ того, что пользователь набрал, чтобы они могли его исправить, вместо того, чтобы внезапно сбросить содержимое TextBox к старому значению свойства.

Поэтому, когда вы нажимаете CheckBox, WPF предполагает, что он должен продолжать отображать состояние control , а не перепроверять привязанное свойство.

Единственный способ, который я нашел в связи с этим, что не очень элегантно, - вызывать PropertyChanged после WPF после вызова метода установки свойств. Это можно сделать с помощью Dispatcher.BeginInvoke:

set
{
  // ...actual real setter logic...
  Action notify = () => NotifyPropertyChanged(...);
  Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.ApplicationIdle, notify);
}

Это можно сделать немного менее ужасно, объединив его в реализацию NotifyPropertyChanged, чтобы вам не пришлось загрязнять отдельные свойства этой проблемой реализации. Вы также можете использовать NotifyOnSourceUpdated и прикрепленное событие SourceUpdated, но я не исследовал эту возможность.

...