WPF MVVM 写一个健壮的INotifyPropertyChanged基类
当我们用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基类的更多相关文章
- java 写一个JSON解析的工具类
上面是一个标准的json的响应内容截图,第一个红圈”per_page”是一个json对象,我们可以根据”per_page”来找到对应值是3,而第二个红圈“data”是一个JSON数组,而不是对象,不能 ...
- 模仿.NET框架ArrayList写一个自己的动态数组类MyArrayList,揭示foreach实现原理
通过.NET反编译工具可以查看到ArrayList内部的代码,发现ArrayList并非由链表实现,而是由一个不断扩容的数组对象组成. 下面模仿ArrayList写一个自己的MyArrayList. ...
- [WPF][Rubyer] 写一个自己的 UI 库 (二) - Icon
前言 制作 WPF 的图标包,主要介绍从 iconfont 下载的图标包导入到 WPF 使用: 1. 添加文件 Ruyber 下添加 自定义控件(WPF) Icon.cs.类 IconType.cs. ...
- 用node.js给C#写一个数据表的实体类生成工具
虽然微软提供了T4模板,但是我感觉非常难用.哪儿比得上直接用脚本来写模板来的爽. 因为要给一个老项目做周边的工具,需要连接到数据库. 我习惯性用EntityFrameworkCore来做,因为毕竟从出 ...
- 一个关于C#中基类与接口混合继承的疑问总结
思路参照 http://www.cnblogs.com/allenlooplee/archive/2004/11/16/64553.html,对原文进行了简化和补充,感谢原作者. 问题很简单,如下所示 ...
- 写一个操作 .ini文件的类
class IniHelp { private string iniPath; [DllImport("kernel32")] private static extern long ...
- 工作线程基类TaskSvc
工作线程基类TaskSvc 前端时间用ACE写代码,发ACE_Task确实好用.不但能提供数量一定的线程,还能够让这些继承的线程函数自由访问子类的private和protected变量.此外,ACE_ ...
- WPF/MVVM 快速开始指南(译)(转)
WPF/MVVM 快速开始指南(译) 本篇文章是Barry Lapthorn创作的,感觉写得很好,翻译一下,做个纪念.由于英文水平实在太烂,所以翻译有错或者译得不好的地方请多指正.另外由于原文是针对W ...
- 自己写一个java.lang.reflect.Proxy代理的实现
前言 Java设计模式9:代理模式一文中,讲到了动态代理,动态代理里面用到了一个类就是java.lang.reflect.Proxy,这个类是根据代理内容为传入的接口生成代理用的.本文就自己写一个Pr ...
随机推荐
- Eclipse中使用Git-让版本管理更简单
详细步骤: 第一部分 GIT介绍 (1)GIT往世今生 2005年开发Samba的Andrew试图破解BitKeeper(一款商业的版本控制系统)的协议(这么干的其实也不只他一个),被BitMove ...
- Warning:mailcious javascript detected on this domain来由
http://www.thenewslens.com/post/144232/ 这是原文介绍,可能国内要用网络加速器才能查看. 以下是国外的一些文档介绍:Cyberspace Administrati ...
- D_S 线性结构
线性结构的定义:若结构是非空有限集,则有且仅有一个开始结点和一个终端结点,并且所有结点都最多只有一个直接前驱和一个直接后继. 线性结构的特点: 只有一个首结点和尾结点 除首尾结点外,其他结点只有一个直 ...
- Linux命令的类型
1.内建命令: 由shell程序自带的命令,最常见的有cd.pwd等. 使用type命令即可查看命令属于哪种,比如: #type cd cd is a shell builtin ————>看到 ...
- WCF 删除队列
Configuration config = ConfigurationManager.OpenExeConfiguration (ConfigurationUserLevel.None); Serv ...
- Hadoop question list
1.我们在开发普通的web app的时候,总会用到orm框架,如hibernates ,ibates等,在hadoop中我们一直使用writable对象,当然如果我们想实现自己的对象类,需要继承这个w ...
- POJ 1679 The Unique MST --Kruskal应用
这题可以用次小生成树解,这里用Kruskal算法来做.每条边除维护u,v,w外,还维护: used:表示这条边是否加过 eq:表示有没有与这条边相等的边 del:删除标记,以便删边之用 如果对于一个最 ...
- VA助手(Visual Assist X) 笔记
官方网站:http://www.wholetomato.com/ 一. 快捷键 Shift+Alt+F Find References 查找引用 Shift+Alt+S FindSynbolDialo ...
- JMeter学习(十九)JMeter测试MongoDB
JMeter测试MongoDB性能有两种方式,一种是利用JMeter直接进行测试MongoDB,还有一种是写Java代码方式测试MongoDB性能. 第一种方法 1.编写Java代码,内容如下: pa ...
- View (四)视图状态及重绘流程分析
相 信大家在平时使用View的时候都会发现它是有状态的,比如说有一个按钮,普通状态下是一种效果,但是当手指按下的时候就会变成另外一种效果,这样才会给 人产生一种点击了按钮的感觉.当然了,这种效果相信几 ...