为了解决NotifyPorpertyChanged的线程与界面绑定异步更新冲突问题,所以查看相关资料后,将自己的NotifyPropertyChanged作了改进。
在开发C#应用程序,通常后使用到界面控件特定属性(Enable | Text)与指定的类成员绑定。但如果指定类成员变量在线程中和界面需异步更新时,会出现异常情况(界面显示异常)。
以下代码未作异步更新,示例如下:
public class TubeConsumedRecord : INotifyPropertyChanged { /// <summary> /// The lock tube /// </summary> private object lockTube; /// <summary> /// The available count /// </summary> private int availableCount; /// <summary> /// 在属性值更改时发生。 /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Gets or sets the available tube count. /// </summary> /// <value>The available tube count.</value> public int AvailableTubeCount { get { return availableCount; } set { if (this.availableCount == value) { return; } this.availableCount = value; OnPropertyChanged(new PropertyChangedEventArgs("AvailableTubeCount")); } } /// <summary> /// Handles the <see cref="E:PropertyChanged" /> event. /// </summary> /// <param name="e">The <see cref="PropertyChangedEventArgs"/> instance containing the event data.</param> private void OnPropertyChanged(PropertyChangedEventArgs e) { if (PropertyChanged != null) PropertyChanged(this, e); } /// <summary> /// Initializes a new instance of the <see cref="TubeConsumedRecord"/> class. /// </summary> public TubeConsumedRecord() { this.lockTube = new object(); } }
为了解决属性绑定的界面和线程异步更新时冲突问题,对INotifyPropertyChanged作了相应的改造。
改造后的类AsynNotifyPropertyChanged, 直接继承使用。
设置异步上下文类为SynchronizationContextProvider,需要用户设置界面的异步上下文,在创造主窗体Main()中添加。
SynchronizationContextProvider.CreateSynchronizationContext(WindowsFormsSynchronizationContext.Current);
AsynNotifyPropertyChanged代码如下:
public class AsynNotifyPropertyChanged : INotifyPropertyChanged { /// <summary> /// Initializes a new instance of the <see cref="AsyncBindingData"/> class. /// </summary> public AsynNotifyPropertyChanged() { } /// <summary> /// Occurs when a property value changes. /// </summary> public event PropertyChangedEventHandler PropertyChanged; /// <summary> /// Called when [property changed]. /// </summary> /// <param name="propertyName">Name of the property.</param> public void OnPropertyChanged(string propertyName) { if (this.PropertyChanged == null||string.IsNullOrEmpty(propertyName)) { return; } if (SynchronizationContextProvider.UISynchronizationContext != null) { SynchronizationContextProvider.UISynchronizationContext.Send(new SendOrPostCallback(AysnPropertyChanged), propertyName); } else { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } private void AysnPropertyChanged(object state) { string propertyName = state.ToString(); if (this.PropertyChanged != null) { this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public void OnPropertyChanged(object sender, PropertyChangedEventHandler propertyChanged, string propertyName) { if (propertyChanged == null || string.IsNullOrEmpty(propertyName)) { return; } if (SynchronizationContextProvider.UISynchronizationContext != null) { SynchronizationContextProvider.UISynchronizationContext.Send(new SendOrPostCallback(AysnPropertyChanged), propertyName); } else { propertyChanged(sender, new PropertyChangedEventArgs(propertyName)); } } }
SynchronizationContextProvider类代码如下:
public class SynchronizationContextProvider { /// <summary> /// The current /// </summary> private static SynchronizationContext current; /// <summary> /// Gets the UI synchronization context. /// </summary> /// <value>The UI synchronization context.</value> internal static SynchronizationContext UISynchronizationContext { get { if(SynchronizationContext.Current==null) { SynchronizationContext.SetSynchronizationContext(current); } return current; } } /// <summary> /// Creates the synchronization context. /// </summary> /// <param name="context">The context.</param> public static void CreateSynchronizationContext(SynchronizationContext context) { current = context; } }
来源:http://www.icode9.com/content-4-27351.html
联系客服