• (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。

  • 相关阅读:
    角色转变
    参加Google™ Code Jam 中国编程挑战赛(1)
    开始学习研究Infragistics NetAdvantage For ASP.NET
    建立资料库
    参加Google™ Code Jam 中国编程挑战赛(2)
    极度郁闷,上网时间被限定!
    在Win7下Visual Studio如何使用IIS进行调试
    jQuery 第二课:操作包装集元素
    将DataTable导出到Excel
    CSS选择符
  • 原文地址:https://www.cnblogs.com/fdyang/p/7181410.html
Copyright © 2020-2023  润新知