Binding works without INotifyPropertyChanged, why?
Asked Answered
D

1

12

This is how we do it normally:

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));
}

Now our property can be used by multiple elements in the view, e.g.:

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

Changing value in TextBox will update content of TextBlock. As well as we can set value in the view model and view will update it automatically.

If we write view model like this

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

then the view is still working (e.g. changing value in TextBox will update TextBlock). Of course it's not possible to easily update Test value from view model anymore (no more event to rise). But my question is about view: Why view is able to work? Does it construct something more in background or is it a logic which checks for something?

Diphenyl answered 5/12, 2016 at 10:56 Comment(3)
Hmm..i'm not sure I understand your example. You say that if you don't implement OnPropertyChanged the view is still working (e.g. changing value in TextBox will update TextBlock) Of course, the view updates the Source (that's why you set up when in UpdateSourceTrigger). But in the second case, if you change the value of Test in your viewmodel, the View won't be notifyed and you won't see that update in the view..Topsoil
@Pikoh, my question is why replacing first view model with second one is still OK for the view. I just don't understand the logic behind what makes it working: we don't have full property, nothing is rised in setter, yet it works for the view without problem: binding to same property in multiple elements will properly track when its value is changed.Diphenyl
If you want to take a look at a full working example for this magical behavior, you can take a look at my question here.Stevana
W
9

[...] you are encountering a another hidden aspect of WPF, that's it WPF's data binding engine will data bind to PropertyDescriptor instance which wraps the source property if the source object is a plain CLR object and doesn't implement INotifyPropertyChanged interface. And the data binding engine will try to subscribe to the property changed event through PropertyDescriptor.AddValueChanged() method. And when the target data bound element change the property values, data binding engine will call PropertyDescriptor.SetValue() method to transfer the changed value back to the source property, and it will simultaneously raise ValueChanged event to notify other subscribers (in this instance, the other subscribers will be the TextBlocks within the ListBox.

And if you are implementing INotifyPropertyChanged, you are fully responsible to implement the change notification in every setter of the properties which needs to be data bound to the UI. Otherwise, the change will be not synchronized as you'd expect.

See: Data binding without INotifyPropertyChanged

Walz answered 5/12, 2016 at 11:6 Comment(1)
Ok, so view subscribes for each such binding to ValueChanged event and in turn rises notification by itself when updating source. That explains how it works, thanks.Diphenyl

© 2022 - 2024 — McMap. All rights reserved.