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

 

 

你可能感兴趣的:(property)