简体   繁体   English

维护响应式WPF UI

[英]Maintaining a responsive WPF UI

I've been trying to figure out how to do this for a couple of days now. 我一直试图弄清楚如何做这几天。

It's a fairly common problem so I'll explain the situation as generically as possible so maybe others can get a bit of use out of it. 这是一个相当普遍的问题,所以我会尽可能地解释这种情况,以便其他人可以从中获得一点点用处。

I have a list view on my WPF (using MVVM) dialog, it's bound to an observable collection of items with, say, five properties which are displayed in seperate columns. 我在我的WPF(使用MVVM)对话框上有一个列表视图,它绑定到一个可观察的项目集合,例如,五个属性显示在单独的列中。

I call a function which iterates over all the items and changes one of their properties. 我调用一个迭代所有项目并更改其中一个属性的函数。 This function takes a while to get through all the items so I want it to update each item as it goes. 此功能需要一段时间才能完成所有项目,因此我希望它能够随时更新每个项目。

What are the options to do this so the UI remains responsive, and which is the simplest to implement? 有哪些选项可以使UI保持响应,哪个是最简单的实现?

If you are using C# 4.0 , use 如果您使用的是C# 4.0 ,请使用

Task.Factory.StartNew(new Action(() =>
{
    .....
     //CALL YOUR UPDATE METHOD



 })).ContinueWith( { //something to execute after, if need}..)

and when set ModelView object from other thread, use 当从其他线程设置ModelView对象时,使用

Application.Current.Dispatcher.Invoke(new Action(() =>
{
    //set ModelView object properties here
}));

I would use an ObservableCollection Extender that allows you to update the collection in another thread. 我会使用一个ObservableCollection Extender,它允许你在另一个线程中更新集合。 This is what I use in my applications when dealing with collections: 这是我在处理集合时在我的应用程序中使用的:

public class ObservableCollectionExtender<T> : ObservableCollection<T>
{
    /// <summary>
    /// Source: New Things I Learned
    /// Title: Have worker thread update ObservableCollection that is bound to a ListCollectionView
    /// http://geekswithblogs.net/NewThingsILearned/archive/2008/01/16/have-worker-thread-update-observablecollection-that-is-bound-to-a.aspx
    /// Note: Improved for clarity and the following of proper coding standards.
    /// </summary>
    /// <param name="e"></param>
    protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
    {
        // Use BlockReentrancy
        using (BlockReentrancy())
        {
            var eventHandler = CollectionChanged;

            // Only proceed if handler exists.
            if (eventHandler != null)
            {
                Delegate[] delegates = eventHandler.GetInvocationList();

                // Walk thru invocation list
                foreach (NotifyCollectionChangedEventHandler handler in delegates)
                {
                    var currentDispatcher = handler.Target as DispatcherObject;

                    // If the subscriber is a DispatcherObject and different thread
                    if ((currentDispatcher != null) &&
                        (currentDispatcher.CheckAccess() == false))
                    {
                        // Invoke handler in the target dispatcher's thread
                        currentDispatcher.Dispatcher.Invoke(
                            DispatcherPriority.DataBind, handler, this, e);
                    }

                    else
                    {
                        handler(this, e);
                    }
                }
            }
        }
    }

    /// <summary>
    /// Overridden NotifyCollectionChangedEventHandler event.
    /// </summary>
    public override event NotifyCollectionChangedEventHandler CollectionChanged;
}

A simple way, and also for people who are working on Netframework 3.5, could be work on a background thread and synchronize using the synchronization contest. 一种简单的方法,也适用于正在使用Netframework 3.5的人,可以在后台线程上工作并使用同步竞赛进行同步。 Try this: 试试这个:

        var sync = SynchronizationContext.Current;
        BackgroundWorker w = new BackgroundWorker();
        w.DoWork+=(_, __)=>
            {                    
                foreach (var item in collection)
                {
                   //calculate other things
                   sync.Post(p => { ...Actualize UI code... }, null);                  
                }
             }, null);
            };
        w.RunWorkerAsync();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM