zoukankan      html  css  js  c++  java
  • (MVVM) ListBox Binding 和 实时刷新

    当需要用Lisbbox 来log 一些记录的时候,ObservableCollection 并不可以是记录实时的反应在WPF 的UI上面。

    这个时候就需要用一个异步collection 来完成。

        /// <summary>
        /// Represents the asynchronous observable collection.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        public class AsyncObservableCollection<T> : ObservableCollection<T>
        {
            /// <summary>
            /// The _synchronization context
            /// </summary>
            private readonly SynchronizationContext synchronizationContext = SynchronizationContext.Current;
    
            /// <summary>
            /// Initializes a new instance of the <see cref="AsyncObservableCollection{T}"/> class.
            /// </summary>
            public AsyncObservableCollection()
            {
            }
    
            /// <summary>
            /// Initializes a new instance of the <see cref="AsyncObservableCollection{T}"/> class.
            /// </summary>
            /// <param name="list">The list.</param>
            public AsyncObservableCollection(IEnumerable<T> list)
                : base(list)
            {
            }
    
            /// <summary>
            /// Inserts the item.
            /// </summary>
            /// <param name="index">The index.</param>
            /// <param name="item">The item.</param>
            protected override void InsertItem(int index, T item)
            {
                this.ExecuteOnSyncContext(() => base.InsertItem(index, item));
            }
    
            /// <summary>
            /// Removes the item.
            /// </summary>
            /// <param name="index">The index.</param>
            protected override void RemoveItem(int index)
            {
                this.ExecuteOnSyncContext(() => base.RemoveItem(index));
            }
    
            /// <summary>
            /// Sets the item.
            /// </summary>
            /// <param name="index">The index.</param>
            /// <param name="item">The item.</param>
            protected override void SetItem(int index, T item)
            {
                this.ExecuteOnSyncContext(() => base.SetItem(index, item));
            }
    
            /// <summary>
            /// Moves the item.
            /// </summary>
            /// <param name="oldIndex">The old index.</param>
            /// <param name="newIndex">The new index.</param>
            protected override void MoveItem(int oldIndex, int newIndex)
            {
                this.ExecuteOnSyncContext(() => base.MoveItem(oldIndex, newIndex));
            }
    
            /// <summary>
            /// Clears the items.
            /// </summary>
            protected override void ClearItems()
            {
                this.ExecuteOnSyncContext(() => base.ClearItems());
            }
    
            /// <summary>
            /// Executes the on synchronize context.
            /// </summary>
            /// <param name="action">The action.</param>
            private void ExecuteOnSyncContext(Action action)
            {
                if (SynchronizationContext.Current == this.synchronizationContext)
                {
                    action();
                }
                else
                {
                    this.synchronizationContext.Send(_ => action(), null);
                }
            }
        } 

     另外还需要启用一个新的线程来更新collection

    后续补充:

    UI 编程中只要搞清楚如下两点:

    1. UI 线程(主线程,入Dispatcher队,只用于更新UI), 在UI线程里面不要做耗时的操作,所有UI线程里面都是用于更新UI的。

    2. 所有的耗时操作全部放到另外的线程里去做。

    搞清楚如上两点,这个Listbox的更新可以通过如下代码来实现了。

               // Start a non-UI thread to do some works without blocking UI thread.
                Task.Factory.StartNew(() =>
                {
                    for (int i = 0; i < 5; i++)
                    {
                        // Put UI change enter dispatcher queue.
                        this.Dispatcher.Invoke(() =>
                        {
                            ((LoggerListBoxViewModel)(this.DataContext)).Logger.Add("Log~~~~.." + i);
                        });
    
                        // Other works.
                        Thread.Sleep(1000); 
                    }
                });

    在ViewModel裏面可以如下更新:

      private void LogMessage(string message)
            {
                // Start a non-UI thread to do some works without blocking UI thread.
                Task.Factory.StartNew(() =>
                {
                    // Put UI change enter dispatcher queue.
                    Application.Current.Dispatcher.Invoke(() =>
                    {
                        this.Logger.Add(message);
                    }); 
                }); 
            }

    注意,如上,Disparter.Invoke是UI线程,里面不能做耗时的工作。仅仅用于更新 UI。

  • 相关阅读:
    PHP 日志专题
    ThinkPHP 3.2 用户注册邮箱验证帐号找回密码
    ThinkPHP 3.2 用户注册邮箱验证激活帐号
    ThinkPHP 3.2 vendor()方法的深入研究及Phpqrcode的正确扩展
    基于Composer的Laravel扩展包开发工作流
    如何利用showdoc自动生成API文档
    PHP中的几个随机数生成函数
    isset在php5.6-和php7.0+的一些差异
    PHP学习方向-进阶2(三)
    Jupyter Notebook 下安装 PHP 内核
  • 原文地址:https://www.cnblogs.com/fdyang/p/7181410.html
Copyright © 2011-2022 走看看