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。

  • 相关阅读:
    C# 实现 Snowflake算法生成唯一性Id
    kafka可视化客户端工具(Kafka Tool)的基本使用(转)
    docker 安装kafka
    Model类代码生成器
    使用docker 部署rabbitmq 镜像
    Vue 增删改查 demo
    git 提交代码到库
    Android ble蓝牙问题
    mac 配置 ssh 到git (Could not resolve hostname github.com, Failed to connect to github.com port 443 Operation timed out)
    okhttp
  • 原文地址:https://www.cnblogs.com/fdyang/p/7181410.html
Copyright © 2011-2022 走看看