zoukankan      html  css  js  c++  java
  • 菲佣WPF——3(关于INotifyPropertyChanged的使用的想法)

    WPF的使用都离不开这个接口。这个接口实现当ViewModel的数据发生变化的时候,通知前台页面的功能;

    通常我们的ViewModel的写法都是这样的。Look:下面的代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    
    namespace WpfApplication4
    {
        public class DemoViewModel:INotifyPropertyChanged
        {
            #region << Property >>
            public event PropertyChangedEventHandler PropertyChanged;
    
            private string name = string.Empty;
            public string Name
            {
                get { return name; }
                set
                {
                    if (name != value)
                    {
                        name = value;
                        Notify("Name");
                    }
                }
            }
            #endregion
    
            #region << Method >>
            public void Notify(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion
        }
    }

    上面的代码是凭感觉写的,没有实际调试过,不过一般都这种写法。

    第二种 写法来之prism:

    巧用了Lambda Expression。(确实不错)

    1.封装了抽象类NotifyObject类

    主要是封装了Notify方法(使用Lambda Expression)

    protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpression)
            {
                var propertyName = PropertySupport.ExtractPropertyName(propertyExpression);
                this.RaisePropertyChanged(propertyName);
            }
     public static string ExtractPropertyName<T>(Expression<Func<T>> propertyExpression)
            {
                if (propertyExpression == null)
                {
                    throw new ArgumentNullException("propertyExpression");
                }
    
                var memberExpression = propertyExpression.Body as MemberExpression;
                if (memberExpression == null)
                {
                    throw new ArgumentException(Resources.PropertySupport_NotMemberAccessExpression_Exception, "propertyExpression");
                }
    
                var property = memberExpression.Member as PropertyInfo;
                if (property == null)
                {
                    throw new ArgumentException(Resources.PropertySupport_ExpressionNotProperty_Exception, "propertyExpression");
                }
    
                var getMethod = property.GetGetMethod(true);
                if (getMethod.IsStatic)
                {
                    throw new ArgumentException(Resources.PropertySupport_StaticExpression_Exception, "propertyExpression");
                }
    
                return memberExpression.Member.Name;
            }

    ExtracPropertyName唯一的目的就是解析Lambda Expression。获取属性名称。

    prism中的使用就是这样

    (手工写,不编译了)

    private string name = string.Empty;

    public string Name

    {

      get { return name;}

      set

      {

        name = value;

        RaisePropertyChanged(()=>Name);

      }

    }

    要使用这个方法,就必须继承抽象类NotifyObject

    方法3:来之之前开发,和查看CodeProject时候,自己的想法写的:Look

    先看使用的代码

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    
    namespace WpfApplication4
    {
        public class MainWindowsViewModel:NotifyObject
        {
            #region << Property >>
            public string Name
            {
                get { return GET(() => Name); }
                set { SET(() => Name, value); }
            }
    
            public string ButtonName
            {
                get { return GET(() => ButtonName); }
                set { SET(() => ButtonName, value); }
             }
    
            public ICommand DemoClick { get; set; }
            #endregion
    
            #region << Constructor >>
            public MainWindowsViewModel()
            {
                DemoClick = new DeletegateCommand(DemoMethod);
            }
            #endregion
    
            #region << Method >>
            public void DemoMethod()
            {
               // MessageBox.Show("Demo CheckBox Click");
                Name = "Notify";
                ButtonName = "NotifyButton";
            }
    
            public bool CanDemoMethod()
            {
                return false;
            }
            #endregion
    
        }
    }

    接着看实现(简单的实现)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.ComponentModel;
    using System.Linq.Expressions;
    
    namespace WpfApplication4
    {
        public abstract class NotifyObject:INotifyPropertyChanged
        {
            #region << Field >>
            private object notifyObj = null;
            #endregion
    
            #region << Property >>
            public event PropertyChangedEventHandler PropertyChanged;
            #endregion
    
            #region << Method >>
            public T GET<T>(Expression<Func<T>> express)
            {
                if (notifyObj == null)
                    return default(T);
                else
                    return (T)notifyObj;
            }
    
            public void SET<T>(Expression<Func<T>> express, object obj)
            {
                var memExpress = (MemberExpression)express.Body;
    
                if (memExpress == null)
                    throw new Exception("The expression is valid");
    
                if (!Object.ReferenceEquals(notifyObj, obj))
                {
                    var propertyName = memExpress.Member.Name;
                    if (!string.IsNullOrEmpty(propertyName))
                    {
                        notifyObj = obj;
                        Notify(propertyName);
                    }
                }
            }
    
            private void Notify(string propertyName)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            #endregion
        }
    }

    这个方法最大的问题 每个属性都有自己的副本,实际上是两份的。这个会导致消耗内存。

    第二个问题 是object box & unbox的性能损耗;

    第三个问题 就是解析Lambda Expression的性能损耗;

    对于一般的使用,估计影响不会太大。

    也许这种写法,有很多的弊端。但毕竟有好的想法是不错的。这样写会使代码美观点。

    我还是建议做WPF的多看看prism的代码实现。外国人写的确实有灵性。

  • 相关阅读:
    Python 基础 -2.4.2 生成器,迭代器
    Python 基础 -2.4.1 装饰器
    Python 基础 -2.4 函数进阶,名称空间,闭包,高阶函数,递归,匿名函数,生产式,生成器,迭代器
    Python 基础 -2.3 函数
    python中字典,元组,列表和字符串之间的转换
    input和raw_input区别
    Python 基础 -2.2 文件操作
    Golang之AES/DES加密解密
    Golang与MySQL
    RTFM
  • 原文地址:https://www.cnblogs.com/qiurideyun/p/2912570.html
Copyright © 2011-2022 走看看