原文:https://www.cnblogs.com/TianFang/p/3381484.html

在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知,

  1. class NotifyObject : INotifyPropertyChanged
  2. {
  3. private int number;
  4. public int Number
  5. {
  6. get { return number; }
  7. set { number = value; OnPropertyChanged("Number"); }
  8. }
  9.  
  10. private string text;
  11. public string Text
  12. {
  13. get { return text; }
  14. set { text = value; OnPropertyChanged("Text"); }
  15. }
  16.  
  17. public event PropertyChangedEventHandler PropertyChanged;
  18. protected void OnPropertyChanged(string propertyName = "")
  19. {
  20. PropertyChangedEventHandler handler = PropertyChanged;
  21. if (handler != null)
  22. {
  23. handler(this, new PropertyChangedEventArgs(propertyName));
  24. }
  25. }
  26. }

这么做有一个比较大的隐患,那就是用了字符串的硬编码的方式传递了属性名称,一旦拼写错误或因为重构代码忘记去更新这个字符串时,这样就会导致界面上得不到更新。(本身硬编码的方式来保证两者的一致性就是不靠谱的行为)

虽然这本身并不是问题,但却不是很好的实践。也有人通过一些手段来解决这个问题,有的是通过表达式树,还有的通过Attribute注入的方式。

从性能上来讲,注入是一个比较好的方式,但往往引入了比较复杂的框架。实际上,在C# 5.0中就引入了一个调用方信息的语法方便我们获取调用方的函数名称和位置,通过它可以非常简单快捷的解决上面的这个问题:

  1. class NotifyObject : INotifyPropertyChanged
  2. {
  3. private int number;
  4. public int Number
  5. {
  6. get { return number; }
  7. set { number = value; OnPropertyChanged(); }
  8. }
  9.  
  10. private string text;
  11. public string Text
  12. {
  13. get { return text; }
  14. set { text = value; OnPropertyChanged(); }
  15. }
  16.  
  17. public event PropertyChangedEventHandler PropertyChanged;
  18. protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
  19. {
  20. PropertyChangedEventHandler handler = PropertyChanged;
  21. if (handler != null)
  22. {
  23. handler(this, new PropertyChangedEventArgs(propertyName));
  24. }
  25. }
  26. }

代码很简单,这里就不多介绍了。

更进一步

有的时候,为了减少通知的频率,往往会把通知写出如下形式:

  1. private int number;
  2. public int Number
  3. {
  4. get { return number; }
  5. set
  6. {
  7. if (number == value)
  8. return;
  9.  
  10. number = value;
  11. OnPropertyChanged();
  12. }
  13. }
  14.  
  15. private string text;
  16. public string Text
  17. {
  18. get { return text; }
  19. set
  20. {
  21. if (text == value)
  22. return;
  23.  
  24. text = value;
  25. OnPropertyChanged();
  26. }
  27. }

这种写法非常单调,并且在属性多的时候代码就显得很累赘了。这里我就写了一个通用点的函数把他们统一起来,下次就可以直接用了。

  1. private int number;
  2. public int Number
  3. {
  4. get { return number; }
  5. set { UpdateProper(ref number, value); }
  6. }
  7.  
  8. private string text;
  9. public string Text
  10. {
  11. get { return text; }
  12. set { UpdateProper(ref text, value); }
  13. }
  14.  
  15. protected void UpdateProper<T>(ref T properValue, T newValue, [CallerMemberName] string properName = "")
  16. {
  17. if (object.Equals(properValue, newValue))
  18. return;
  19.  
  20. properValue = newValue;
  21. OnPropertyChanged(properName);
  22. }

由于C#的语法限制,不能在类外部调用event,因此不能写成扩展方法,这里就简单的写成一个对象,下次就直接照着改好了:

  1. class NotifyObject : INotifyPropertyChanged
  2. {
  3. private int number;
  4. public int Number
  5. {
  6. get { return number; }
  7. set { UpdateProper(ref number, value); }
  8. }
  9.  
  10. private string text;
  11. public string Text
  12. {
  13. get { return text; }
  14. set { UpdateProper(ref text, value); }
  15. }
  16.  
  17. protected void UpdateProper<T>(ref T properValue, T newValue, [CallerMemberName] string properName = "")
  18. {
  19. if (object.Equals(properValue, newValue))
  20. return;
  21.  
  22. properValue = newValue;
  23. OnPropertyChanged(properName);
  24. }
  25.  
  26. public event PropertyChangedEventHandler PropertyChanged;
  27. protected void OnPropertyChanged([CallerMemberName]string propertyName = "")
  28. {
  29. PropertyChangedEventHandler handler = PropertyChanged;
  30. if (handler != null)
  31. {
  32. handler(this, new PropertyChangedEventArgs(propertyName));
  33. }
  34. }
  35. }

[转]使用CallerMemberName简化InotifyPropertyChanged的实现的更多相关文章

  1. 使用CallerMemberName简化InotifyPropertyChanged的实现

    在WPF中,当我们要使用MVVM的方式绑定一个普通对象的属性时,界面上往往需要获取到属性变更的通知,     class NotifyObject : INotifyPropertyChanged   ...

  2. C# 特性学习之一、CallerMemberName、CallerFilePath和CallerLineNumber

    在开发中经常会写个公有静态类记录日志,如下: /// <summary> /// Writes the error. /// </summary> /// <param ...

  3. 如何优雅的实现INotifyPropertyChanged接口

    INotifyPropertyChanged接口在WPF或WinFrom程序中使用还是经常用到,常用于通知界面属性变更.标准写法如下: class NotifyObject : INotifyProp ...

  4. 转载:如何优雅的实现INotifyPropertyChanged接口

    转载来源:http://www.cnblogs.com/TianFang/p/6240933.html 如何优雅的实现INotifyPropertyChanged接口 INotifyPropertyC ...

  5. C# 5.0中使用CallerMemberName、CallerFilePath和CallerLineNumber获取代码的调用方信息(转载)

    很多时候,我们需要在运行过程中记录一些调测的日志信息,如下所示: public void DoProcessing() { TraceMessage("DoProcessing()被XXX调 ...

  6. C# 各版本新特性

    C# 2.0 泛型(Generics) 泛型是CLR 2.0中引入的最重要的新特性,使得可以在类.方法中对使用的类型进行参数化. 例如,这里定义了一个泛型类: class MyCollection&l ...

  7. C# 5.0中新增特性

    C# 5.0随着VisualStudio 2012一起正式发布了,让我们来看看C#5.0中增加了哪些功能. 1. 异步编程 在.Net 4.5中,通过async和await两个关键字,引入了一种新的基 ...

  8. C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) C#各版本新特性 C#版本和.NET版本以及VS版本的对应关系

    C# 语言历史版本特性(C# 1.0到C# 7.1汇总更新) 2017年08月06日 11:53:13 阅读数:6705 历史版本 C#作为微软2000年以后.NET平台开发的当家语言,发展至今具有1 ...

  9. C# 5.0新加特性

    1. 异步编程 在.Net 4.5中,通过async和await两个关键字,引入了一种新的基于任务的异步编程模型(TAP).在这种方式下,可以通过类似同步方式编写异步代码,极大简化了异步编程模型.如下 ...

随机推荐

  1. zookeeper应用 - 配置服务

    一端不停的更新配置,另一端监听这个配置的变化.     需要注意的是:监听端不一定读取到所有的变化.在zk服务器发送通知到客户端,客户端读取数据注册监听之间可能发生了多次数据变化,这些数据变化是得不到 ...

  2. 事件驱动模型 IO多路复用 阻塞IO与非阻塞IO select epool

    一.事件驱动 1.要理解事件驱动和程序,就需要与非事件驱动的程序进行比较.实际上,现代的程序大多是事件驱动的,比如多线程的程序,肯定是事件驱动的.早期则存在许多非事件驱动的程序,这样的程序,在需要等待 ...

  3. Promise 初步

    在JavaScript的世界中,所有代码都是单线程执行的. 由于这个“缺陷”,导致JavaScript的所有网络操作,浏览器事件,都必须是异步执行.异步执行可以用回调函数实现: function ca ...

  4. Linux安装Tomcat服务器发布项目教程

    前面小Alan跟大家聊了在Linux服务器上jdk运行环境的安装以及redis非关系型数据库的安装,今天继续跟大家聊聊Tomcat的安装,以及将我们的项目发布上去并成功的访问. 第一步:将tomcat ...

  5. pytts3语音合成遇到的中文问题

    在使用pytts3语音合成时,遇到中文语音错乱.程序代码本身很简单,也是网上公认的一种写法: #coding: UTF-8import pyttsx3; engine = pyttsx3.init() ...

  6. SPA SEO thought

    angular, vue,ember,backbone等javascript framework大大方便了现代web开发,带来了用户体验的巨大提高,但是同时带来了另一个问题:SEO,由于搜索引擎无法运 ...

  7. 解决 There are no resources that can be added or removed from the server

    网上下载了一个项目,在eclipse中部署时,加载项目到tomcat中项目名称无法显示,报出There are no resources that can be added or removed fr ...

  8. ORACLE 参数设置绑定变量

    使用 CURSOR_SHARING 参数 EXACT  默认,不替换 SIMIAR 当替换不会影响到执行计划时,才会将字面量替换成绑定变量 FORCE 只要有可能,字面量会被替换为绑定变量

  9. Python实例---CRM管理系统分析180331

    注意:一个项目基本都设计增删改查,且第一个需要做的就是设计表结构 思维导图: 组件使用: Django  +   bootStrap  +   Jquery 数据库表结构设计: 外键关联: 2种方式, ...

  10. Hadoop HBase概念学习系列之HBase里的4维坐标系统(第一步定位行键 -> 第二步定位列簇 -> 第三步定位列修饰符 -> 第四步定位时间戳)(十八)

    HBase里的4维坐标系统(第一步定位行键   ->   第二步定位列簇  ->  第三步定位列修饰符   ->  第四步定位时间戳) HBase里的4维坐标系统(第一步定位行键   ...