MVVM写一个健壮的INotifiyPropertyChanged基类

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




  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值