gif图标网站,深圳网站建设的基本知识,国外做二手服装网站有哪些问题,织梦 更换网站图标序言 借助WPF/Sliverlight强大的数据绑定功能#xff0c;可以比实现比MFC#xff0c;WinForm更加优雅轻松的数据绑定。但是在使用WPF/Silverlight绑定时#xff0c;有件事情是很苦恼的#xff1a;当ViewModel对象放生改变#xff0c;需要通知UI。我们可以让VM对象实现INot…序言 借助WPF/Sliverlight强大的数据绑定功能可以比实现比MFCWinForm更加优雅轻松的数据绑定。但是在使用WPF/Silverlight绑定时有件事情是很苦恼的当ViewModel对象放生改变需要通知UI。我们可以让VM对象实现INotifyPropertyChanged接口通过事件来通知UI。但问题就出现这里……
一描述问题 情形现在需要将一个Person对象的Name熟悉双向绑定到UI中的TextBox的确这是一件很简单的事情但还是描述下 XAML
TextBox Text{Binding Name,ModeTwoWay}/ C# Code
public class Person : INotifyPropertyChanged{private string m_Name;public string Name{get { return m_Name; }set {if (m_Name value) return; m_Name value;this.Notify(Name);}}public Person(){this.m_Name 墨梅在这里......;}public event PropertyChangedEventHandler PropertyChanged;public void Notify(string propertyName){PropertyChangedEventHandler handler this.PropertyChanged;if (handler ! null)handler(this, new PropertyChangedEventArgs(propertyName));}} 是的这就可以实现了。但是这里一个问题困惑我曾经就在this.Notify(Name)将参数写错UI迟迟得不到响应。这个错误很难发现也很难跟踪但是这个细微的错误可以导致一个很严重的运行时错误。这的确是一件很苦恼的事情。 二解决问题
方法一添加验证
public event PropertyChangedEventHandler PropertyChanged;protected virtual void OnPropertyChanged(string propertyName)
{this.VerifyPropertyName(propertyName);PropertyChangedEventHandler handler this.PropertyChanged;if (handler ! null){var e new PropertyChangedEventArgs(propertyName);handler(this, e);}
}[Conditional(DEBUG)]
[DebuggerStepThrough]
public void VerifyPropertyName(string propertyName)
{// Verify that the property name matches a real, // public, instance property on this object.if (TypeDescriptor.GetProperties(this)[propertyName] null){string msg Invalid property name: propertyName;if (this.ThrowOnInvalidPropertyName)throw new Exception(msg);elseDebug.Fail(msg);}
} 这里对验证事件参数使用条件编译[Conditional(“DEBUG”)],在release版本中这个函数是不会调用的比使用#if 等有更明显有优势。 这个方法虽然可以达到目的但是还是那么的别扭必须到运行时才能知道是否有错误所以还是不怎么好。
方法二使用Lambda表达式静态扩展语法
public static class NotificationExtensions{public static void Notify(this PropertyChangedEventHandler eventHandler, ExpressionFuncobject expression){if( null eventHandler ){return;}var lambda expression as LambdaExpression;MemberExpression memberExpression;if (lambda.Body is UnaryExpression){var unaryExpression lambda.Body as UnaryExpression;memberExpression unaryExpression.Operand as MemberExpression;}else{memberExpression lambda.Body as MemberExpression;}var constantExpression memberExpression.Expression as ConstantExpression;var propertyInfo memberExpression.Member as PropertyInfo;foreach (var del in eventHandler.GetInvocationList()){del.DynamicInvoke(new object[] {constantExpression.Value, new PropertyChangedEventArgs(propertyInfo.Name)});}}}
这里用使用的静态扩展语法我还是比较喜欢这个的但是并不是所有人都喜欢哦。如何使用呢
public class Employee : INotifyPropertyChanged{public event PropertyChangedEventHandler PropertyChanged;private string _firstName;public string FirstName {get { return this._firstName; }set{this._firstName value;this.PropertyChanged.Notify(()this.FirstName);}}}
这里还可以添加一个很实用的扩展
public static void SubscribeToChangeT(this T objectThatNotifies, ExpressionFuncobject expression, PropertyChangedEventHandlerT handler)where T : INotifyPropertyChanged{objectThatNotifies.PropertyChanged (s, e) {var lambda expression as LambdaExpression;MemberExpression memberExpression;if (lambda.Body is UnaryExpression){var unaryExpression lambda.Body as UnaryExpression;memberExpression unaryExpression.Operand as MemberExpression;}else{memberExpression lambda.Body as MemberExpression;}var propertyInfo memberExpression.Member as PropertyInfo;if(e.PropertyName.Equals(propertyInfo.Name)){handler(objectThatNotifies);}};}
通过上面的代码可以订阅熟悉改变事件,如
myObject.SubscripeToChange(()myObject.SomeProperty,SomeProperty_Changed); And then your handler would look like this:private void SomeProperty_Changed(MyObject myObject)
{/* ... implement something here */
}
方法三net4.5框架提供的解决方法
private string m_myProperty;
public string MyProperty
{get { return m_myProperty; }set{m_myProperty value;OnPropertyChanged();}
}private void OnPropertyChanged([CallerMemberName] string propertyName none passed)
{// ... do stuff here ...
}
属性CallerMemberName的解决办法和方法二是基本相同的不同的是这个在net框架中解决的。更多信息可以查看CallerMemberNamenet4.5还提供了
CallerFilePathCallerLineNumber这几很有用的语法
方法四这个也不错哦
public static class SymbolExtensions{public static string GetPropertySymbolT,R(this T obj, ExpressionFuncT,R expr){return ((MemberExpression)expr.Body).Member.Name;}}public class ConversionOptions : INotifyPropertyChanged{private string _outputPath;public string OutputPath{get { return _outputPath;}set{_outputPath value;OnPropertyChanged(o o.OutputPath);}}private string _blogName;public string BlogName{get { return _blogName;}set{_blogName value;OnPropertyChanged(o o.BlogName);}}private string _secretWord;public string SecretWord{get { return _secretWord; }set{_secretWord value;OnPropertyChanged(o o.SecretWord);}}protected virtual void OnPropertyChangedR(ExpressionFuncConversionOptions, R propertyExpr){OnPropertyChanged(this.GetPropertySymbol(propertyExpr));}protected virtual void OnPropertyChanged(string propertyName){if (PropertyChanged ! null)PropertyChanged(this, new PropertyChangedEventArgs(propertyName));}public event PropertyChangedEventHandler PropertyChanged;}
注释这里还有更多参考信息您可以在这里了解更加清楚