wpf中数据绑定和INotifyPeropertyChanged的理解

原创:转载请注明出处。

先说数据绑定:

XAML代码:

<Window x:Class="数据绑定和INotifyPropertyChanged.Window1" Loaded="Window_Loaded"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="数据绑定和INotifyPropertyChanged" Height="300" Width="300">
    <Grid>
        <Label Height="28" Margin="15,35,0,0" Name="lbAge" VerticalAlignment="Top" HorizontalAlignment="Left" Width="42">年龄:</Label>
        <Label Height="28" HorizontalAlignment="Left" Margin="15,83,0,0" Name="lbName" VerticalAlignment="Top" Width="42">姓名:</Label>
        <TextBox Height="23" Margin="79,37,79,0" Name="TxtAge" VerticalAlignment="Top" Text="{Binding Name}"/>
        <TextBox Height="23" Margin="79,83,79,0" Name="TxtName" VerticalAlignment="Top" Text="{Binding Age}"/>
    </Grid>
</Window>

C#代码:

步骤如下:

先定义一个类

 1 public class Person:INotifyPropertyChanged
 2     {
 3         private string _name;
 4 
 5         public string Name
 6         {
 7             get { return _name; }
 8             set { _name = value; }
 9         }
10 
11         private int _age;
12 
13         public int Age
14         {
15             get { return _age; }
16             set { _age = value; }
17         }
18     }

然后在后台写代码:

 1 private Person p1;
 2 
 3         public Person P1
 4         {
 5             get { return p1; }
 6             set { p1 = value; }
 7         }
 8         public Window1()
 9         {
10             InitializeComponent();
11         }
12 
13         private void Window_Loaded(object sender, RoutedEventArgs e)
14         {
15             p1 = new Person();
16             p1.Name = "aaa";
17             p1.Age = 15;
18 
19             TxtAge.DataContext = p1;
20             TxtName.DataContext = p1;
21         }

注意:

这里牵扯到一个很重要的东西,“数据上下文”,即DataContext,必须把界面控件的DataContext和类的实例绑定起来,这样界面才会显示类中属性的值。
要想控件获得类中的属性值并显示,控件必须绑定类中的属性。

 

接下来说一下INotifyPropertyChanged,这个是MVVM的基础,也是数据双向绑定很重要很关键的部分。通过他,类的属性值改变才会改变UI界面显示的值。(有一个很重要的知识点:事件,这个不懂得赶紧去学下再来接着往下看)。

上代码,这个代码是数据绑定部分代码的基础上进一步完善。

XMAL代码:

 1 <Window x:Class="数据绑定和INotifyPropertyChanged.Window1" Loaded="Window_Loaded"
 2     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4     Title="数据绑定和INotifyPropertyChanged" Height="300" Width="300">
 5     <Grid>
 6         <Label Height="28" Margin="15,35,0,0" Name="lbAge" VerticalAlignment="Top" HorizontalAlignment="Left" Width="42">年龄:</Label>
 7         <Label Height="28" HorizontalAlignment="Left" Margin="15,83,0,0" Name="lbName" VerticalAlignment="Top" Width="42">姓名:</Label>
 8         <TextBox Height="23" Margin="79,37,79,0" Name="TxtAge" VerticalAlignment="Top" Text="{Binding Name}"/>
 9         <TextBox Height="23" Margin="79,83,79,0" Name="TxtName" VerticalAlignment="Top" Text="{Binding Age}"/>
10         <Button Height="23" HorizontalAlignment="Left" Margin="30,0,0,80" Name="BtnAgePP" VerticalAlignment="Bottom" Width="75" Click="BtnAgePP_Click">Age++</Button>
11         <Button Height="23" Margin="132,0,71,80" Name="BtnDisplayAge" VerticalAlignment="Bottom" Click="BtnDisplayAge_Click">显示年龄</Button>
12     </Grid>
13 </Window>

C#代码:

 1 private Person p1;
 2 
 3         public Person P1
 4         {
 5             get { return p1; }
 6             set { p1 = value; }
 7         }
 8         public Window1()
 9         {
10             InitializeComponent();
11         }
12 
13         private void Window_Loaded(object sender, RoutedEventArgs e)
14         {
15             p1 = new Person();
16             p1.Name = "aaa";
17             p1.Age = 15;
18 
19             TxtAge.DataContext = p1;
20             TxtName.DataContext = p1;
21         }
22 
23         private void BtnDisplayAge_Click(object sender, RoutedEventArgs e)
24         {
25             MessageBox.Show(p1.Age.ToString());
26             MessageBox.Show(p1.Name);
27         }
28 
29         private void BtnAgePP_Click(object sender, RoutedEventArgs e)
30         {
31             p1.Age++;
32             p1.Name = "ccc";
33         }

类:person也要改,

 1 public class Person:INotifyPropertyChanged
 2     {
 3         private string _name;
 4 
 5         public string Name
 6         {
 7             get { return _name; }
 8             set { _name = value; if (PropertyChanged != null) { PropertyChanged(this,new PropertyChangedEventArgs("Name")); } }
 9         }
10 
11         private int _age;
12 
13         public int Age
14         {
15             get { return _age; }
16             set { _age = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("Age")); } }
17         }
18 
19         #region INotifyPropertyChanged 成员
20 
21         public event PropertyChangedEventHandler PropertyChanged;//数据绑定会监听这个PropertyChanged事件
22 
23         #endregion
24     }

有没有注意到类Person有什么变化,对,Person类实现了INotifyPropertyChanged接口。
解释一下:

1、Person类实现INotifyPropertyChanged接口,这个接口只有一个PropertyChanged事件成员。

看源码:

1     // 摘要:
2     //     向客户端发出某一属性值已更改的通知。
3     public interface INotifyPropertyChanged
4     {
5         // 摘要:
6         //     在更改属性值时发生。
7         event PropertyChangedEventHandler PropertyChanged;
8     }

2、数据绑定会检测Person类是否实现了INotifyPropertyChanged接口,
3、如果Person类实现了INotifyPropertyChanged接口,那就监听PropertyChanged事件。

4、如果Property改变了,那么就产生PropertyChanged事件,即PropertyChanged!=null。

5、向前端UI发送属性值改变的额通知,控件绑定了属性,控件收到属性改变的通知,就把自身的值也改变 。

 

 

补充:在数据绑定的时候,是一个一个控件绑定的,当控件少的时候这没问题,但是控件多的话,就要重复写很多次的datacontext了。这时候,可以用this.DataContext来统一指定当前窗口的所有控件的数据上下文。

譬如,本文中的例子可以变成this.DataContext = p1。这样的话,DataContext就可以作用到全部的控件,而不需要一个一个去指定了。

当然,也可以在this的DataContext指定后,给某个控件指定DataContext,这样子特定的控件就有它自己的DataContext了。

 

posted @ 2018-02-02 09:27  liu_xh  阅读(453)  评论(0编辑  收藏  举报