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.后就能出现我们要的属性

 本文转自lpxxn博客园博客,原文链接:http://www.cnblogs.com/li-peng/p/3169864.html,如需转载请自行联系原作者

相关文章
|
8月前
|
设计模式 开发框架 前端开发
深入理解WPF中MVVM的设计思想
近些年来,随着WPF在生产,制造,工业控制等领域应用越来越广发,很多企业对WPF开发的需求也逐渐增多,使得很多人看到潜在机会,不断从Web,WinForm开发转向了WPF开发,但是WPF开发也有很多新的概念及设计思想,如:数据驱动,数据绑定,依赖属性,命令,控件模板,数据模板,MVVM等,与传统WinForm,ASP.NET WebForm开发,有很大的差异,今天就以一个简单的小例子,简述WPF开发中MVVM设计思想及应用。
62 0
|
9月前
|
前端开发
WPF-Binding问题-MVVM中IsChecked属性CommandParameter转换值类型空异常
WPF-Binding问题-MVVM中IsChecked属性CommandParameter转换值类型空异常
91 0
|
10月前
|
前端开发 算法 JavaScript
走进WPF之MVVM完整案例
走进WPF之MVVM完整案例
156 0
|
前端开发 C# 图形学
【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入
前言:在C/S架构上,WPF无疑已经是“桌面一霸”了。在.NET生态环境中,很多小伙伴还在使用Winform开发C/S架构的桌面应用。但是WPF也有很多年的历史了,并且基于MVVM的开发模式,受到了很多开发者的喜爱。
568 0
【.NET6+WPF】WPF使用prism框架+Unity IOC容器实现MVVM双向绑定和依赖注入
|
前端开发 C# 数据库
WPF MVVM系统入门-下
本文详细讲解WPF,MVVM开发,实现UI与逻辑的解耦。
|
前端开发 数据可视化 C#
WPF MVVM系统入门-上
本文详细讲解WPF,MVVM开发,实现UI与逻辑的解耦。
|
前端开发 C#
WPF MVVM 如何在 ViewModel 中关闭界面窗口
WPF MVVM 如何在 ViewModel 中关闭界面窗口
WPF学习—INotifyPropertyChanged Interface
WPF学习—INotifyPropertyChanged Interface
WPF学习—INotifyPropertyChanged Interface
|
前端开发 C#
WPF 之 数据与命令绑定 (MVVM方式)
WPF 之 数据与命令绑定 (MVVM方式)
160 0
WPF 之 数据与命令绑定 (MVVM方式)
|
SQL 前端开发 C#
WPF MVVM模式
WPF MVVM模式