转载来源:http://www.cnblogs.com/TianFang/p/6240933.html

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

class NotifyObject : INotifyPropertyChanged
    {
        private int number;
        public int Number
        {
            get { return number; }
            set { number = value; OnPropertyChanged("Number"); }
        }

private string text;
        public string Text
        {
            get { return text; }
            set { text = value; OnPropertyChanged("Text"); }
        }

public event PropertyChangedEventHandler PropertyChanged;
        protected void OnPropertyChanged(string propertyName = "")
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }

这种写法的两个问题是

  1. 对属性名使用了字符串硬编码,容易写错,也不方便重构
  2. 冗余代码,如果属性较多的时候写得想吐

我在博客文章使用CallerMemberName简化InotifyPropertyChanged的实现中介绍了通过Caller Information解决属性名称字符串硬编码的问题。但是仍然不能解决冗余代码的问题。对于第二个问题,往往是通过AOP的方式实现,一般的实现方式有两种:

  1. 通过代理对象封装
  2. 通过编译期间代码注入的方式实现

我增在项目中使用过DynamicObject封装来实现过,主要原理是用实现一个PocoNotifyWrapper的DynamicObject类,托管其属性的读写动作,并附加IntofyPropertyChanged接口实现。

这种方式是动态的AOP了,是一个通用的方式,并且扩展性比较器,可以通过继承PocoNotifyWrapper来实现多态。用它做ViewMode层还是比较方便。

不过一个不大好的地方是DynamicObject是丢失了属性类型信息的,有时绑定时会出错(如将一个TextBox的Text绑定到一个封装后的Int类型对象时会不进行自动类型转换)。要解决它还需要实现一些其它的接口,实现起来还是有些复杂的,并且项目进度比较紧张,没有太多时间来完善它。

另外一种方式是通过编译期间代码注入方式来实现:


最开始见的是PostSharp的一个实现: http://doc.postsharp.net/inotifypropertychanged-add。不过PostSharp是收费的,后来也逐渐由了许多其它的免费的解决方案。本文这里介绍的是一个开源的解决方案:Fody

使用它非常简单,首先通过Nuget安装库:PM> Install-Package PropertyChanged.Fody。然后在需要实现属性通知的类上加一个[ImplementPropertyChanged]即可:

]
  public class Person
  {

    public string GivenNames { get; set; }
    public string FamilyName { get; set; }

    public string FullName => string.Format("{0} {1}", GivenNames, FamilyName);
  }

编译后生成的代码如下:

 

基本上对代码没有注入,不需要安装插件,也不影响调试,实现非常简单,非常方便。

需要注意的是,如果实现了INotifyPropertyChanged接口,即使没有[ImplementPropertyChanged]标记,默认也会注入。另外,如果要实现更多的控制,可以参看如下链接:

除此之外,还有许多关于实现的INotifyPropertyChanged文章,感兴趣的朋友可以看一下:

转载:如何优雅的实现INotifyPropertyChanged接口的更多相关文章

  1. 转载:WPF MVVM之INotifyPropertyChanged接口的几种实现方式

    原文地址:http://www.cnblogs.com/xiwang/ 序言 借助WPF/Sliverlight强大的数据绑定功能,可以比实现比MFC,WinForm更加优雅轻松的数据绑定.但是在使用 ...

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

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

  3. 优雅实现INotifyPropertyChanged接口——利用Lambda表达式

    原文:优雅实现INotifyPropertyChanged接口--利用Lambda表达式 参考文章 在14年的时候,曾经读过上面的参考文章,不过当时并没有怎么理解,慢慢地也就将这篇文章忘诸脑后了. 直 ...

  4. WPF系列之三:实现类型安全的INotifyPropertyChanged接口,可以不用“Magic string” 么?

    通常实现INotifyPropertyChanged接口很简单,为你的类只实现一个PropertyChanged 的Event就可以了. 例如实现一个简单的ViewModel1类: public cl ...

  5. WPF MVVM之INotifyPropertyChanged接口的几种实现方式(转)

    原地址:https://www.cnblogs.com/xiwang/archive/2012/11/25/2787358.html 序言 借助WPF/Sliverlight强大的数据绑定功能,可以比 ...

  6. INotifyPropertyChanged接口的PropertyChanged 事件

    INotifyPropertyChanged 接口用于向客户端(通常是执行绑定的客户端)发出某一属性值已更改的通知. 例如,考虑一个带有名为 FirstName 属性的 Person 对象. 若要提供 ...

  7. 【.NET深呼吸】INotifyPropertyChanged接口的真故事

    无论是在流氓腾的问问社区,还是在黑度贴吧,或是“厕所等你”论坛上,曾经看到过不少朋友讨论INotifyPropertyChanged接口.不少朋友认为该接口是为双向绑定而使用的,那么,真实的情况是这样 ...

  8. [译]WPF MVVM 架构 Step By Step(5)(添加actions和INotifyPropertyChanged接口)

    应用不只是包含textboxs和labels,还包含actions,如按钮和鼠标事件等.接下来我们加上一些像按钮这样的UI元素来看MVVM类怎么演变的.与之前的UI相比,这次我们加上一个"C ...

  9. C# ListView 控件和 INotifyPropertyChanged 接口

    ListView 控件和 DataGridView 控件 ListView 是跟 Winform 中 DataGridView 用法以及显示效果差不多的一个 WPF 控件,可以通过列表的方式方便的显示 ...

随机推荐

  1. mpvue

    使用mpvue开发小程序 首先安装 我们使用@vue/cli 无法使用vue init 可以全局安装一个@vue/cli-init npm install -g @vue/cli-init 然后初始化 ...

  2. 字符串排序--string类的使用

    最近帮他们做了一个简单的c++的题目,以前做过,当时是借鉴的别人的代码,现在也忘得差不多了,不过思路还有,现在正好可以再温习一下. 题目要求如下: 先输入你要输入的字符串的个数.然后换行输入该组字符串 ...

  3. JS和CSS交互的方法

    用JavaScript获取伪元素(pseudo-element)属性  var  color=window.getComputedStyle( document.querySelector('.ele ...

  4. Spring Boot+Spring Security:获取用户信息和session并发控制

    说明 (1)JDK版本:1.8(2)Spring Boot 2.0.6(3)Spring Security 5.0.9(4)Spring Data JPA 2.0.11.RELEASE(5)hiber ...

  5. python 运用numpy库与matplotlib库绘制数据图

    代码一 import numpy as np import matplotlib.pyplot as plt x=np.linspace(0,6,100) y=np.cos(2*np.pi*x)*np ...

  6. dax学习

    增长率 = (DIVIDE(SUM('业绩达成'[实际业绩]),CALCULATE(SUM('业绩达成'[实际业绩]),PREVIOUSMONTH('业绩达成'[周期])))-1)*100上月业绩 = ...

  7. TypeError: Fetch argument 0 has invalid type <type 'int'>, must be a string or Tensor. (Can not convert a int into a Tensor or Operation.)

    6月5日的時候,修改dilated_seg.py(使用tensorflow)出現了報錯: TypeError: Fetch argument 0 has invalid type <type ' ...

  8. OpenStack构架简介

    OpenStack既是一个社区,也是一个项目和一个开源软件,提供开放源码软件,建立公共和私有云,它提供了一个部署云的操作平台或工具集,其宗旨在于:帮助组织运行为虚拟计算或存储服务的云,为公有云.私有云 ...

  9. thinkphp51 重定向 redirect()

    thinkphp51 重定向 跨域 redirect() 可以重新定义新的路由,是fetch() 无法做到的.

  10. 使用spring-session共享springmvc项目的session

    一.说在前面 spring mvc项目,使用nginx,tomcat部署. 之前没做session共享,而nginx采用sticky模块进行分发. 但发现有时不能正确地指向同一台服务器,从而导致ses ...