ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

NotifyPropertyChanged线程与界面绑定异步更新

2018-09-28 11:00:19  阅读:188  来源: 互联网

标签:


         为了解决NotifyPorpertyChanged的线程与界面绑定异步更新冲突问题,所以查看相关资料后,将自己的NotifyPropertyChanged作了改进。

1.问题起因

        在开发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();
        }

    }

2. 解决方法

为了解决属性绑定的界面和线程异步更新时冲突问题,对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;
        }
    }

 

标签:
来源: https://blog.csdn.net/zhengxu25689/article/details/82877545

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有