INotifyPropertyChanged接口的实现
何时实现INotifyPropertyChanged接口
官方解释:INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知。官方解释的很模糊,估计是个人看了都不知道到底什么时候需要实现INotifyPropertyChanged接口.小梦通过实际测试给出明确结论:
首先:OneTime模式:毫无意义,因为它的绑定只有初始时候绑定一次,根本谈不上改变!自然也就谈不上实现INotifyPropertyChanged接口.
然后是OneWay模式:我们知道OneWay模式的含义是:绑定源的每一次变化都会通知绑定目标,但是绑定目标的改变不会改变绑定源.当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,当我们改变了数据源,我们会发现绑定目标的UI上的相应的数据不会立即变化.所以这时候就需要我们来实现INotifyPropertyChanged接口.
最后是TwoWay模式:在TwoWay模式下,当绑定源的数据实体类没有实现INotifyPropertyChanged接口时,我们发现.控件的更改会让数据源立即发改变,但是改变数据源,绑定目标控件却不会立即发生改变!所以当我们需要数据源改变时相对应的UI立即改变时,就需要实现INotifyPropertyChanged接口.
总之:就是当数据源改变并需要UI立即改变时我们需要实现INotifyPropertyChanged接口.
我们可以通过这个示例来明确的体会这一点:
C#
<TextBox Header="编号" Text="{Binding ID,Mode=OneTime}" Name="tbxID" ></TextBox>
<TextBox Header="书名" Text="{Binding Title,Mode=OneWay}" Name="tbxTitle" ></TextBox>
<TextBox Header="价格" Text="{Binding Price,Mode=TwoWay}" Name="tbxPrice" ></TextBox>
<Button Content="通过数据源修改控件的值" Click="Button_Click"></Button>
<Button Content="直接修改控件的值" Click="Button_Click_1" />
<Button Content="通过控件修改数据源的值" Click="Button_Click_2" />
</StackPanel>
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |    <StackPanel>        <TextBox  Header="编号" Text="{Binding ID,Mode=OneTime}" Name="tbxID"  ></TextBox>         <TextBox Header="书名" Text="{Binding Title,Mode=OneWay}" Name="tbxTitle" ></TextBox>        <TextBox  Header="价格" Text="{Binding Price,Mode=TwoWay}" Name="tbxPrice" ></TextBox>      <Button Content="通过数据源修改控件的值"  Click="Button_Click"></Button>          <Button Content="直接修改控件的值"     Click="Button_Click_1" />         <Button Content="通过控件修改数据源的值"   Click="Button_Click_2" />        </StackPanel> | 
后台代码:
C#
{
/// <summary>
/// 可用于自身或导航至 Frame 内部的空白页。
/// </summary>
public sealed partial class MainPage : Page
    {
        Book book = new Book();
        public MainPage()
        {
            this.InitializeComponent();
this.NavigationCacheMode = NavigationCacheMode.Required;
            book.ID = 0;
            book.Title = "ASP.NET 开发手册";
            book.Price = 40;
            st.DataContext = book;
        }
  private void Button_Click(object sender, RoutedEventArgs e)//通过修改数据源修改控件的值
        {
            book.ID = 100;
            book.Price = 50;
            book.Title = "SL开发手册";
        }
private async void Button_Click_1(object sender, RoutedEventArgs e)//显示数据源的值
        {
            await new MessageDialog(book.ID.ToString() + " " + book.Title.ToString() + " " + book.Price.ToString()).ShowAsync();
        }
public class Book : INotifyPropertyChanged
//INotifyPropertChanged 接口定义了一个当属性值更改时执行的事件,事件名称为PropertyChanged。
     //这个是在继承这个接口的类必须要实现的事件
{
            private int _id;
            public int ID
            {
                get { return _id; }
                set
                {
                    _id = value;
                    //NotifyPropertyChange("ID");
                }
            }
            private string _title;
            public string Title
            {
                get { return _title; }
                set
                {
                    _title = value;
                    //NotifyPropertyChange("Title");
                }
            }
            private double _price;
            public double Price
            {
                get { return _price; }
                set
                {
                    _price = value;
                    //NotifyPropertyChange("Price");
                }
            }
            public event PropertyChangedEventHandler PropertyChanged;
            //PropertyChangedEventArgs类型,这个类用于传递更改值的属性的名称,实现向客户端已经更改的属性发送更改通知。属性的名称为字符串类型。
            private void NotifyPropertyChange(string propertyName)
            {
                if (PropertyChanged != null)
                {
                    //根据PropertyChanged事件的委托类,实现PropertyChanged事件:
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
                }
            }
        }
    }
}
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | namespace INotifyPropertyChangedDEMO {     /// <summary>     /// 可用于自身或导航至 Frame 内部的空白页。     /// </summary>     public sealed partial class MainPage : Page     {         Book book = new Book();         public MainPage()         {             this.InitializeComponent();             this.NavigationCacheMode = NavigationCacheMode.Required;             book.ID = 0;             book.Title = "ASP.NET 开发手册";             book.Price = 40;             st.DataContext = book;         }   private void Button_Click(object sender, RoutedEventArgs e)//通过修改数据源修改控件的值         {             book.ID = 100;             book.Price = 50;             book.Title = "SL开发手册";         }         private async void Button_Click_1(object sender, RoutedEventArgs e)//显示数据源的值         {             await new MessageDialog(book.ID.ToString() + " " + book.Title.ToString() + " " + book.Price.ToString()).ShowAsync();         }         public class Book : INotifyPropertyChanged //INotifyPropertChanged 接口定义了一个当属性值更改时执行的事件,事件名称为PropertyChanged。      //这个是在继承这个接口的类必须要实现的事件         {             private int _id;             public int ID             {                 get { return _id; }                 set                 {                     _id = value;                     //NotifyPropertyChange("ID");                 }             }             private string _title;             public string Title             {                 get { return _title; }                 set                 {                     _title = value;                     //NotifyPropertyChange("Title");                 }             }             private double _price;             public double Price             {                 get { return _price; }                 set                 {                     _price = value;                     //NotifyPropertyChange("Price");                 }             }             public event PropertyChangedEventHandler PropertyChanged;             //PropertyChangedEventArgs类型,这个类用于传递更改值的属性的名称,实现向客户端已经更改的属性发送更改通知。属性的名称为字符串类型。             private void NotifyPropertyChange(string propertyName)             {                 if (PropertyChanged != null)                 {                     //根据PropertyChanged事件的委托类,实现PropertyChanged事件:                     PropertyChanged(this, new PropertyChangedEventArgs(propertyName));                 }             }         }     } } | 
大家运行这个示例可以明显体会INotifyPropertyChanged接口的作用.
如何实现INotifyPropertyChanged接口
上面示例的INotifyPropertyChanged接口的实现方式是最常见和最普遍的.
我们可以利用CallerMemberNameAttribute特性来简化一下,这个特性可以根据调用方来决定传入哪个属性的名字.:
C#
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
| 1 2 3 4 5 6 | protected void OnPropertyChanged([CallerMemberName] string propertyName = null)         {             var eventHandler = this.PropertyChanged;             if (eventHandler != null)                 eventHandler(this, new PropertyChangedEventArgs(propertyName));         } | 
这样我们在调用时可以这样调用:
NotifyPropertyChange(“ID”) 改为:OnPropertyChanged();
INotifyPropertyChanged接口的最佳实现方式:
这个所谓的最佳实现方式 是channel 9的视频中说的,实现方式如下:
C#
{
public event PropertyChangedEventHandler PropertyChanged;
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var eventHandler = this.PropertyChanged;
            if (eventHandler != null)
                eventHandler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | public class ModelBase : INotifyPropertyChanged     {         public event PropertyChangedEventHandler PropertyChanged;         protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] String propertyName = null)         {             if (object.Equals(storage, value)) return false;             storage = value;             this.OnPropertyChanged(propertyName);             return true;         }         protected void OnPropertyChanged([CallerMemberName] string propertyName = null)         {             var eventHandler = this.PropertyChanged;             if (eventHandler != null)                 eventHandler(this, new PropertyChangedEventArgs(propertyName));         }     } | 
相应的调用方式进一步简化:
C#
public string Name
        {
            get { return name; }
            set
            { this.SetProperty(ref this.name, value); }
        }
| 1 2 3 4 5 6 7 8 |    private string name;         public string Name         {             get { return name; }             set             { this.SetProperty(ref this.name, value); }         } | 
// 实现 INotifyPropertyChanging 是为了最大限度地减少内存使用量(NotifyPropertyChanging 的用法:在属性赋值之前调用) /* * 为什么会减少内存使用量呢? * 因为 LINQ to SQL 更改跟踪是通过维护每个对象的两个副本进行工作的,第一个副本保存原始数据,第二个副本有程序更改,这样提交更新时 LINQ to SQL 就知道哪些数据被更改了,从而只提交这些被更改的数据 * INotifyPropertyChanging 接口允许应用程序在将修改后的数据提交到数据库前通知 DataContext,DataContext 可以将该通知用作创建副本的触发器,这样就不用保留第二个副本了,从而减少内存使用 */ public event PropertyChangingEventHandler PropertyChanging; protected void NotifyPropertyChanging(string propertyName) { if (PropertyChanging != null) { PropertyChanging(this, new PropertyChangingEventArgs(propertyName)); } }
INotifyPropertyChanged接口的实现的更多相关文章
- 如何优雅的实现INotifyPropertyChanged接口
		INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ... 
- INotifyPropertyChanged接口的PropertyChanged 事件
		INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知. 例如,考虑一个带有名为 FirstName 属性的 Person 对象. 若要提供 ... 
- 【.NET深呼吸】INotifyPropertyChanged接口的真故事
		无论是在流氓腾的问问社区,还是在黑度贴吧,或是“厕所等你”论坛上,曾经看到过不少朋友讨论INotifyPropertyChanged接口.不少朋友认为该接口是为双向绑定而使用的,那么,真实的情况是这样 ... 
- [译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)
		应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"C ... 
- 转载:WPF MVVM之INotifyPropertyChanged接口的几种实现方式
		原文地址:http://www.cnblogs.com/xiwang/ 序言 借助WPF/Sliverlight强大的数据绑定功能,可以比实现比MFC,WinForm更加优雅轻松的数据绑定.但是在使用 ... 
- C# ListView 控件和 INotifyPropertyChanged 接口
		ListView 控件和 DataGridView 控件 ListView 是跟 Winform 中 DataGridView 用法以及显示效果差不多的一个 WPF 控件,可以通过列表的方式方便的显示 ... 
- INotifyPropertyChanged 接口 CallerMemberName属性
		调用方信息 使用调用方信息属性,可以获取关于调用方的信息传递给方法. 可以获取源代码.行号在源代码和调用方的成员名称的文件路径. 此信息用于跟踪,调试和创建诊断工具非常有用.若要获取此信息,则使用适用 ... 
- INotifyPropertyChanged 接口
		INotifyPropertyChanged 接口 用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知. 例如,考虑一个带有名为 FirstName 属性的 Person 对象.若要提供 ... 
- 转载:如何优雅的实现INotifyPropertyChanged接口
		转载来源:http://www.cnblogs.com/TianFang/p/6240933.html 如何优雅的实现INotifyPropertyChanged接口 INotifyPropertyC ... 
- ListView 控件和 INotifyPropertyChanged 接口
		原文:ListView 控件和 INotifyPropertyChanged 接口 ListView 控件和 DataGridView 控件 ListView 是跟 Winform 中 DataGri ... 
随机推荐
- Google Protocol Buffer的安装与.proto文件的定义(转)
			转自(https://www.cnblogs.com/yinheyi/p/6080244.html) 什么是protocol Buffer呢? Google Protocol Buffer( 简称 P ... 
- 001_chrome工具详解
			一.chrome https://segmentfault.com/a/1190000000683599 
- js中parentNode,parentElement,childNodes,children
			首先了解parentNode,parentElement,childNodes,children四大属性之前,必须对Dom树有一定的了解,在Dom文档结构中,HTML页面每一部分都是由节点组成的,节点 ... 
- 使用JS实现俄罗斯方块游戏
			简单的JS俄罗斯方块游戏源码 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <meta charset=&q ... 
- [转]编译hadoop
			安装maven hadoop源码是使用maven组织管理的,必须下载maven.从maven官网下载,下载地址是http://maven.apache.org/download.cgi,选择 apac ... 
- spring-cloud-sleuth+zipkin追踪服务实现(四)
			1.前言 在上一篇spring-cloud-sleuth+zipkin追踪服务实现(三)的处理实现后,很多朋友告诉我,在zipkin server的管理页面无法看到项目依赖关系. 当时也没有多想,以为 ... 
- shell学习(二)
			1.EOF Shell中通常将EOF与 <<和cat 结合使用,表示后续的输入作为子命令或子Shell的输入,直到遇到EOF为止,再返回到主调Shell. 可以把EOF替换成其他东西,意思 ... 
- Serilog 记录日志
			Serilog 记录日志 Serilog是.net里面非常不错的记录日志的库,另外一个我认为比较好的Log库是NLog. 在我个人的asp.net web api 2 基础框架(Github地址)里, ... 
- 003.LVM扩容
			一 LVM扩容步骤 创建分区 创建PV 扩容VG 扩容LV 载大小 二 创建分区 使用分区工具(如fdisk等)创建LVM分区,却将分区标识为LVM的分区类型8e. [root@kauai ~]# f ... 
- 踩过无数坑实现的哈夫曼压缩(JAVA)
			最近可能又是闲着没事干了,就想做点东西,想着还没用JAVA弄过数据结构,之前搞过算法,就试着写写哈夫曼压缩了. 本以为半天就能写出来,结果,踩了无数坑,花了整整两天时间!!orz...不过这次踩坑,算 ... 
