[. NET Deep breath] real story of INotifyPropertyChanged interface, inotify

Source: Internet
Author: User
Tags inotify

[. NET Deep breath] real story of INotifyPropertyChanged interface, inotify

I have seen many friends discussing the INotifyPropertyChanged interface, whether in the hooligan Q & A community, in the black post, or in the "toilet waiting for you" forum. Many friends think that this interface is used for Bidirectional binding. Is this true?

The INotifyPropertyChanged interface is located in the System. ComponentModel namespace and has another interface: INotifyPropertyChanging. The INotifyPropertyChanging interface defines the PropertyChanging event, which should be triggered when the property value is changing. The INotifyPropertyChanged interface defines the PropertyChanged event, which should be triggered after the property value has changed.

The INotifyPropertyChanging interface is only available in the complete. net Library and is not defined in the portable library. Therefore, the INotifyPropertyChanged interface is frequently used. In most cases, we only care about whether the attribute value has changed, but not about the modification process of the attribute value.

There was a lot of nonsense above, and the subject of this article came up. Is the INotifyPropertyChanged interface only related to bidirectional binding?

 

Next we will consider the first situation.

In one-way binding, what is the difference between using the INotifyPropertyChanged interface and not using the INotifyPropertyChanged interface.

We define a class. This class has a common Value attribute. When the class is instantiated, the Value attribute is updated every three seconds through the Timer class. The attribute Value uses a random integer. The Code is as follows:

    public class TestDemo    {        Timer _timer = null;        Random _rand = null;        public TestDemo ()        {            _rand = new Random();            TimerCallback cb = ( s ) =>                {                    Value = _rand.Next();                };            _timer = new Timer(cb, null, TimeSpan.FromSeconds(0), TimeSpan.FromSeconds(3));        }        int _val;        public int Value        {            get { return _val; }            set { _val = value; }        }    }

I don't want to explain the code. I believe you can understand it because it is not complicated. Note that Timer objects will be timing immediately after they are instantiated.
Now, this demonstration class is used for one-way binding to display the Value Attribute Value on TextBlock.

<Window x:Class="SampleApp1.MainWindow"        ……        xmlns:local="clr-namespace:SampleApp1"        Title="MainWindow" Height="350" Width="525">    <Grid>        <Grid.Resources>            <local:TestDemo x:Key="td"/>        </Grid.Resources>        <TextBlock FontSize="24" Text="{Binding Source={StaticResource td},Path=Value,Mode=OneWay}"/>    </Grid></Window>

One-way is a one-way binding. When you run the application, you will find that the text value on TextBlock has not changed. Does the timer fail to start timing?

Through breakpoint debugging, it is found that the timer is timed successfully, and the Value attribute is also modified smoothly, such:

 

It is reasonable to say that one-way binding will allow data to flow from the data source to the bound target. Why is the TextBlock control not updated in real time? The reason is that Binding does not receive the property change notification, so it does not get the latest value.

The following describes how to implement the INotifyPropertyChanged interface for the demonstration class.

Public class TestDemo: INotifyPropertyChanged {Timer _ timer = null; Random _ rand = null; public TestDemo () {_ rand = new Random (); TimerCallback cb = (s) ==>{ Value = _ rand. next () ;}; _ timer = new Timer (cb, null, TimeSpan. fromSeconds (0), TimeSpan. fromSeconds (3);} int _ val; public int Value {get {return _ val;} set {if (_ val! = Value) {_ val = value; // trigger the property change notification event if (this. PropertyChanged! = Null) {PropertyChanged (this, new PropertyChangedEventArgs ("Value") ;}}// public event PropertyChangedEventHandler PropertyChanged to implement the INotifyPropertyChanged interface ;}

At this time, run the application again and you will find that the value in TextBlock can be automatically updated.

 

What is the above example? It indicates that the property change notification is not only used in bidirectional binding, but also required in unidirectional binding.

 

Next we will look at the situation of two-way binding.

Let's first verify the question: Is it necessary to implement the INotifyPropertyChanged interface to be updated by the UI as the data source type?

First define a class for testing.

    public class Employee    {        private string _name;        private string _city;        public string Name        {            get            {                return _name;             }            set            {                _name = value;            }        }        public string City        {            get             {                return _city;             }            set            {                _city = value;            }        }    }

 

<Window x: Class = "SampleApp2.MainWindow" xmlns =" http://schemas.microsoft.com/winfx/2006/xaml /Presentation "xmlns: x =" http://schemas.microsoft.com/winfx/2006/xaml "Xmlns: local =" clr-namespace: SampleApp2 "Title =" MainWindow "Height =" 350 "Width =" 525 "> <Grid. resources> <local: Employee x: Key = "emp" Name = "James" City = "Chongqing"/> </Grid. resources> <Grid. rowDefinitions> <RowDefinition Height = "auto"/> <RowDefinition Height = "auto"/> </Grid. rowDefinitions> <GroupBox Grid. row = "0"> <GroupBox. header> <TextBlock Text = "Modify information" FontSize = "24" Foreground = "Blue"/> </GroupBox. header> <StackPanel DataContext = "{Binding Source = {StaticResource emp}"> <TextBlock Text = "Gong Name: "/> <TextBox Width =" 200 "HorizontalAlignment =" Left "Text =" {Binding Path = Name, Mode = TwoWay, updateSourceTrigger = PropertyChanged} "/> <TextBlock Margin =", "Text =" City: "/> <TextBox Width =" 200 "HorizontalAlignment =" Left "Text =" {Binding Path = City, Mode = TwoWay, updateSourceTrigger = PropertyChanged} "/> </StackPanel> </GroupBox> <GroupBox Grid. row = "1" Margin = "0, 20, 0, 0"> <GroupBox. header> <TextBlock Text = "display information" Foreground = "Blue" FontSize = "24"/> </GroupBox. header> <TextBlock DataContext = "{Binding Source = {StaticResource emp}"> employee Name; <Run Text = "{Binding Name}"/> <LineBreak/> city: <Run Text = "{Binding City}"/> </TextBlock> </GroupBox> </Grid> </Window>

 

The Employee class does not implement the INotifyPropertyChanged interface, but after running the above program, we will find that the TextBlock below can be automatically updated after the data is modified in TextBox. Next we will change the above example. Instead of updating data through Binding, we will use code to manually change the data.

<StackPanel DataContext = "{Binding Source = {StaticResource emp}"> <TextBlock Text = "Gong name:"/> <! -- <TextBox Width = "200" HorizontalAlignment = "Left" Text = "{Binding Path = Name, Mode = TwoWay, updateSourceTrigger = PropertyChanged} "/> --> <TextBox Width =" 200 "HorizontalAlignment =" Left "x: Name =" txtName "/> <TextBlock Margin =, 0, 0 "Text =" City: "/> <! -- <TextBox Width = "200" HorizontalAlignment = "Left" Text = "{Binding Path = City, Mode = TwoWay, updateSourceTrigger = PropertyChanged} "/> --> <TextBox Width =" 200 "HorizontalAlignment =" Left "x: name = "txtCity"/> <Button Content = "newer" Click = "OnClick" Width = "200" HorizontalAlignment = "Left" Margin =, 0, 0 "/> </StackPanel>

 

        private void OnClick ( object sender, RoutedEventArgs e )        {            Employee emp = layoutRoot.Resources["emp"] as Employee;            if (emp != null)            {                emp.Name = txtName.Text;                emp.City = txtCity.Text;            }        }

 

In this case, the attributes of the sample object are modified through code. After running the sample program, you will find that the following TextBlock control will not be automatically updated after the content is modified. Through breakpoint debugging, it is found that the property value of the Employee instance has been updated, but the TextBlock does not display the new value.

 

Then let's implement the Employee class

    public class Employee : INotifyPropertyChanged    {        private string _name;        private string _city;        public string Name        {            get            {                return _name;             }            set            {                if (_name != value)                {                    _name = value;                    OnPropertyChanged();                }            }        }        public string City        {            get             {                return _city;             }            set            {                if (_city != value)                {                    _city = value;                    OnPropertyChanged();                }            }        }        private void OnPropertyChanged([CallerMemberName] string propName=""){            if (PropertyChanged != null)            {                PropertyChanged(this, new PropertyChangedEventArgs(propName));            }        }        public event PropertyChangedEventHandler PropertyChanged;    }

After each attribute value is changed, the PropertyChanged event is triggered. Here, an OnPropertyChanged method is used to encapsulate the event. The parameter is the name of the changed attribute. In this case, a technique is used to add the CallerMemberNameAttribute feature to the parameter and give the parameter a default value: Null String.
When the OnPropertyChanged method is called in the set accessors of the attribute, you do not need to write the attribute name. CallerMemberNameAttribute automatically assigns the member name of the caller to the method parameter, since the OnPropertyChanged method is called within the modified attribute, CallerMemberNameAttribute gets the name of this attribute, which saves us a lot of trouble.

 

Run the application now. After modifying the object attributes, TextBlock can be automatically updated.

 

The preceding examples show that the INotifyPropertyChanged interface is not absolutely related to bidirectional Binding. When Binding is used completely for Bidirectional processing, update can be obtained even if the INotifyPropertyChanged interface is not implemented, of course, the source of Binding must be the same instance. However, if the data modification is not completed through Binding, each customer who uses the data source will not be notified of the property change. Therefore, the INotifyPropertyChanged interface must be implemented at this time.

 

After the above demonstration, we can find that the INotifyPropertyChanged interface does not have to be used for Bidirectional binding, but in order to allow the code using data to receive the attribute change notification in a timely manner, all data source objects should implement the INotifyPropertyChanged interface. You can see that the entity types generated by the development tool in the Linq to SQL or object model all implement the INotifyPropertyChanged interface, this is precisely because all data needs to be updated in a timely manner.

I hope that you will have a new understanding of INotifyPropertyChanged in this article.

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.