2016-12-05 8 views
3

Это, как мы это делаем обычно:Связывание без INotifyPropertyChanged, почему?

public class ViewModel : INotifyPropertyChanged 
{ 
    string _test; 
    public string Test 
    { 
     get { return _test; } 
     set 
     { 
      _test = value; 
      OnPropertyChanged(); 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    public void OnPropertyChanged([CallerMemberName] string property = "") => 
     PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(property)); 
} 

Теперь наша собственность может быть использована несколькими элементами в представлении, например .:

<TextBox Text="{Binding Test, UpdateSourceTrigger=PropertyChanged}" /> 
<TextBlock Text="{Binding Test}" /> 

Изменение значения в TextBox будет обновлять содержание TextBlock. Как и мы можем установить значение в модели просмотра, и представление автоматически обновит его.

Если мы напишем вид модели, как этот

public class ViewModel 
{ 
    public string Test { get; set; } 
} 

затем вид еще работает (например, изменение значения в TextBox обновит TextBlock). Конечно, невозможно легко обновить значение Test из модели просмотра (больше не нужно подниматься). Но мой вопрос о представлении: Почему просмотр способен работать? Составляет ли он что-то еще в фоновом режиме или это логика, которая что-то проверяет?

+1

Hmm..i'm не уверен, что я понимаю ваш пример. Вы говорите, что если вы не реализуете 'OnPropertyChanged', представление все еще работает (например, изменение значения в TextBox будет обновлять TextBlock). Конечно, представление обновляет Source (именно поэтому вы настраиваете его в' UpdateSourceTrigger'). Но во втором случае, если вы измените значение Test в своей модели просмотра, представление не будет уведомлено, и вы не увидите это обновление в представлении. – Pikoh

+0

@Pikoh, мой вопрос в том, почему замена первой модели представления на второй - все еще в порядке для представления. Я просто не понимаю логики того, что заставляет его работать: у нас нет полного свойства, в сеттере ничего не возникает, но он работает для представления без проблем: привязка к тому же свойству в нескольких элементах будет правильно отслеживаться, когда его значение изменяется. – Sinatr

+0

Если вы хотите взглянуть на полный рабочий пример этого магического поведения, вы можете взглянуть на мой вопрос [здесь] (https://stackoverflow.com/q/46803196/1977871). – VivekDev

ответ

4

[...] вы столкнулись с один скрытый аспект WPF, это все данные WPF в связывании двигатель будет связывать данные PropertyDescriptor экземпляра, который оборачивает исходный свойство, если исходный объект является простым объектом CLR и не реализовать интерфейс INotifyPropertyChanged. И привязка данных будет пытаться подписаться на событие с измененным свойством через метод PropertyDescriptor.AddValueChanged(). И когда целевые данные связанный элемент меняет значения свойств, механизм привязки данных будет вызывать метод PropertyDescriptor.SetValue() для передачи измененного значения обратно в исходное свойство и одновременно поднять событие ValueChanged для уведомления других подписчиков (в данном случае, то другие абоненты будут TextBlocks в ListBox.

И если вы реализуете INotifyPropertyChanged, вы полностью ответственность осуществлять уведомление об изменении в каждом сеттер свойства которых должно быть данные связанные к пользовательскому интерфейсу. В противном случае изменение не будет синхронизировано, как вы ожидали.

См: Data binding without INotifyPropertyChanged

+0

Итак, просмотрите подписки на каждую такую ​​привязку к событию ValueChanged и, в свою очередь, самостоятельно повышаете уведомление при обновлении источника.Это объясняет, как это работает, спасибо. – Sinatr