菲佣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的代码实现。外国人写的确实有灵性。

 

 

posted @ 2013-02-14 21:19  qiurideyun  阅读(1496)  评论(2编辑  收藏  举报