当我们用MVVM的时候要实现INotifyPropertyChanged,如果你是基于.net4.5以下的framework(.net4.5已有新特性我这里就不说了)

你很可能会这么写

 public class MyModel : INotifyPropertyChanged
{
private string _Name;
public string Name
{
get
{
return _Name;
}
set
{
_Name = value;
OnPropertyChanged("Name");//会造成硬编码错误
}
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}

这样的写法很可能会造成硬编码错误

你是不是有点烦每次要写一个字段还要写一个属性还要加上OnPropertyChanged,有没好一点的方法让我们少写

代码呢,能是能用现有的技术实现我们想要的像下面这样

    public class MyModel : PropertyNotifyObject
{
public string Name
{
get
{
return this.GetValue(x => x.Name);
}
set
{
this.SetValue(x => x.Name, value);
}
}
}

哇!这么写看着好简单呀,而且还能有效避免硬编码对你带来的问题。

写一个x.就能出现你要的属性

对!这样你就能省下更多的时间去写加的代码了,

先说明一下用到的技术没有新的只是只用到了泛型和扩展方法和一点linq,要怎么实现呢?来让我们一步一步的实现

我们先写一个公共类方法

public class MyCommMetoh
{
//得到属性的名称
public static string GetPropertyName<T, U>(Expression<Func<T, U>> exp)
{
string _pName = "";
if (exp.Body is MemberExpression)
{
_pName = (exp.Body as MemberExpression).Member.Name;
}
else if(exp.Body is UnaryExpression)
{
_pName = ((exp.Body as UnaryExpression).Operand as MemberExpression).Member.Name;
}
return _pName;
}
}

这个GetPropertyName方法是根据一个Lambda表达式得到属性的名称

像这上面 this.GetValue(x => x.Name) ,这个方法就是用x => x.Name做为参数得到Name这个名字

这样可以有效的防止硬编码错误

实现一下INotifyPropertyChanged接口

    public class NotifyPropertyBase : INotifyPropertyChanged
{
#region INotifyPropertyChanged
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
public static class NotifyPropertyBaseEx
{
public void OnPropertyChanged<T, U>(this T npb, Expression<Func<T, U>> exp) where T : NotifyPropertyBase,new()
{
string _PropertyName = MyCommMetoh.GetPropertyName(exp);
npb.OnPropertyChanged(_PropertyName);
}
}

上边的类我想你并不陌生吧,下这那个是个扩展类,如果你不太明白那就先回去看一下基础吧

是利用扩展根据lambda用上边我们写的公共类方法得到属性的名称,这也是为防止硬编码而做的工作

下面才是我们真正的基类PropertyNotifyObject,这个类是我们存放数据值,修改和查询值的

看一下我是怎么写的

public class PropertyNotifyObject : NotifyPropertyBase,IDisposable
{
public PropertyNotifyObject() { } Dictionary<object, object> _ValueDictionary = new Dictionary<object, object>(); #region 根据属性名得到属性值
public T GetPropertyValue<T>(string propertyName)
{
if (string.IsNullOrEmpty(propertyName)) throw new ArgumentException("invalid " + propertyName);
object _propertyValue;
if(!_ValueDictionary.TryGetValue(propertyName,out _propertyValue))
{
_propertyValue = default(T);
_ValueDictionary.Add(propertyName, _propertyValue);
}
return (T)_propertyValue;
}
#endregion public void SetPropertyValue<T>(string propertyName, T value)
{
if (!_ValueDictionary.ContainsKey(propertyName) || _ValueDictionary[propertyName] != (object)value)
{
_ValueDictionary[propertyName] = value;
OnPropertyChanged(propertyName);
}
} #region Dispose
public void Dispose()
{
DoDispose();
}
~PropertyNotifyObject()
{
DoDispose();
}
void DoDispose()
{
if (_ValueDictionary != null)
_ValueDictionary.Clear();
}
#endregion
}
public static class PropertyNotifyObjectEx
{
public static U GetValue<T, U>(this T t, Expression<Func<T, U>> exp) where T : PropertyNotifyObject
{
string _pN = MyCommMetoh.GetPropertyName(exp);
return t.GetPropertyValue<U>(_pN);
} public static void SetValue<T, U>(this T t, Expression<Func<T, U>> exp, U value) where T : PropertyNotifyObject
{
string _pN = MyCommMetoh.GetPropertyName(exp);
t.SetPropertyValue<U>(_pN, value);
}
}

这是用一个字典把所有的存放了起来,看下面有一个扩展这个扩展就能让我们实现

        public string Name
{
get
{
return this.GetValue(x => Name);
}
set
{
this.SetValue(x => x.Name, value);
}
}

的x => x.Name。这样就能让我们写完x.后就能出现我们要的属性

  

WPF MVVM 写一个健壮的INotifyPropertyChanged基类的更多相关文章

  1. java 写一个JSON解析的工具类

    上面是一个标准的json的响应内容截图,第一个红圈”per_page”是一个json对象,我们可以根据”per_page”来找到对应值是3,而第二个红圈“data”是一个JSON数组,而不是对象,不能 ...

  2. 模仿.NET框架ArrayList写一个自己的动态数组类MyArrayList,揭示foreach实现原理

    通过.NET反编译工具可以查看到ArrayList内部的代码,发现ArrayList并非由链表实现,而是由一个不断扩容的数组对象组成. 下面模仿ArrayList写一个自己的MyArrayList. ...

  3. [WPF][Rubyer] 写一个自己的 UI 库 (二) - Icon

    前言 制作 WPF 的图标包,主要介绍从 iconfont 下载的图标包导入到 WPF 使用: 1. 添加文件 Ruyber 下添加 自定义控件(WPF) Icon.cs.类 IconType.cs. ...

  4. 用node.js给C#写一个数据表的实体类生成工具

    虽然微软提供了T4模板,但是我感觉非常难用.哪儿比得上直接用脚本来写模板来的爽. 因为要给一个老项目做周边的工具,需要连接到数据库. 我习惯性用EntityFrameworkCore来做,因为毕竟从出 ...

  5. 一个关于C#中基类与接口混合继承的疑问总结

    思路参照 http://www.cnblogs.com/allenlooplee/archive/2004/11/16/64553.html,对原文进行了简化和补充,感谢原作者. 问题很简单,如下所示 ...

  6. 写一个操作 .ini文件的类

    class IniHelp { private string iniPath; [DllImport("kernel32")] private static extern long ...

  7. 工作线程基类TaskSvc

    工作线程基类TaskSvc 前端时间用ACE写代码,发ACE_Task确实好用.不但能提供数量一定的线程,还能够让这些继承的线程函数自由访问子类的private和protected变量.此外,ACE_ ...

  8. WPF/MVVM 快速开始指南(译)(转)

    WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...

  9. 自己写一个java.lang.reflect.Proxy代理的实现

    前言 Java设计模式9:代理模式一文中,讲到了动态代理,动态代理里面用到了一个类就是java.lang.reflect.Proxy,这个类是根据代理内容为传入的接口生成代理用的.本文就自己写一个Pr ...

随机推荐

  1. 每日Scrum--No.7

    Yesterday:学习和设计路线的编程 Today:编写代码 Problem:.在设计查询参观路线的时候,整个逻辑特别的混乱,设想了各种树,图以及网的遍历问题,但经过多次与同学的交流以及网上的查询资 ...

  2. SQL基础(1)-创建及修改表

    1. 建表语句 CREATE TABLE fdh_client_info ( id varchar2(50) primary key, name varchar2(30) not null, sex ...

  3. POI教程之第二讲:创建一个时间格式的单元格,处理不同内容格式的单元格,遍历工作簿的行和列并获取单元格内容,文本提取

    第二讲 1.创建一个时间格式的单元格 Workbook wb=new HSSFWorkbook(); // 定义一个新的工作簿 Sheet sheet=wb.createSheet("第一个 ...

  4. web.xml文件报错:cvc-complex-type.2.4.a: Invalid content was found starting with element 'init-param'.

    <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" ...

  5. Hadoop could not find or load main class

    Error: Could not find or load main class <class_name> 我在尝试使用hadoop definitive guide的代码做练习时,遇到一 ...

  6. Bellman-Ford算法解决单源最短路问题

    #include<stdio.h> #include<stdlib.h> #include<stdbool.h> #define max 100 #define I ...

  7. DAC使用基本准则

    DAC Nyquist Zones, Zero Order Hold, and Images why do the Fout images exist in every Nyquist zone? W ...

  8. 如何利用ZBrush中的DynaMesh创建身体(二)

    之前的ZBrush教程我们在了解了人体比例和结构的前提下,使用ZBrush®软件中的Append功能和InsertSphere笔刷添加躯干.本讲将参照图片继续对“亡灵僵尸”的形体结构进行细致刻画和使用 ...

  9. zstu-3769 数回文子串

    思路:用manacher求出每个位置的半径,相加即可. 代码:[rad[i]/2]即i这个位置的回文半径,添加的'#'代表长度为偶数的串. #include<stdio.h> #inclu ...

  10. HDU 3491 最小点权割集

    题意:有n个城市,m条双向边,有一群小偷从s前往t偷东西,警察叔叔们想要逮捕小偷们,现在告诉你在每座城市需要多少警察才能抓住这个城市的小偷,为什么说这个城市,因为小偷们会分开跑:然后题目还说不能在s和 ...