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