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。

  • 相关阅读:

    HttpClient发送get/post请求
    maven创建ssm项目依赖(pom.xml文件)
    java的Scanner类总结
    java多线程总结
    java跨域问题
    Idea打包项目war并且发布到服务器
    Mybatis入门案例之增删改查
    springMVC中的@RequestBody和@ResponseBody以及@RequestParam
    Gson解析json
  • 原文地址:https://www.cnblogs.com/fdyang/p/7181410.html
Copyright © 2011-2022 走看看