Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Binding works without INotifyPropertyChanged, why?

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?

like image 418
Sinatr Avatar asked Dec 05 '16 10:12

Sinatr


People also ask

Why implement INotifyPropertyChanged?

Implementing INotifyPropertyChanged will help you keep your code clean and get the most out of the hard work that other developers have done to implement binding clients. Special thanks to Jason Wergin for the base class code, and for pointing out this new and very useful interface.

How do I use onpropertychanged () method with a binding counter?

The OnPropertyChanged () method should receive as a parameter the name of the property that is being changed. This should correspond to the name of the property that was bound to the UI control {Binding Counter}. Line 41 is equivalent to OnPropertyChanged ("Counter");.

Should onpropertychanged have the parameter page?

Shouldn't this.OnPropertyChanged have the parameter "Page" not "page" no, Page is the class name. page is my variable name. i need to raise the event when my variable is changed. EDIT: also propertychanged works like it needs to i checked it. its somthing with the binding that is wrong i think.

What is the onpropertychanged () method?

Finally, write the OnPropertyChanged () method. When the PropertyChanged event is raised, this method will instantiate an object containing the name of the property that was changed so the UI control can connect to the appropriate property.


1 Answers

[...] 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

like image 51
Leon Husmann Avatar answered Sep 30 '22 17:09

Leon Husmann