簡體   English   中英

維護響應式WPF UI

[英]Maintaining a responsive WPF UI

我一直試圖弄清楚如何做這幾天。

這是一個相當普遍的問題,所以我會盡可能地解釋這種情況,以便其他人可以從中獲得一點點用處。

我在我的WPF(使用MVVM)對話框上有一個列表視圖,它綁定到一個可觀察的項目集合,例如,五個屬性顯示在單獨的列中。

我調用一個迭代所有項目並更改其中一個屬性的函數。 此功能需要一段時間才能完成所有項目,因此我希望它能夠隨時更新每個項目。

有哪些選項可以使UI保持響應,哪個是最簡單的實現?

如果您使用的是C# 4.0 ,請使用

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



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

當從其他線程設置ModelView對象時,使用

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

我會使用一個ObservableCollection Extender,它允許你在另一個線程中更新集合。 這是我在處理集合時在我的應用程序中使用的:

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;
}

一種簡單的方法,也適用於正在使用Netframework 3.5的人,可以在后台線程上工作並使用同步競賽進行同步。 試試這個:

        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