2016-04-21 42 views
1

我有一個問題,這是非常無聊,我花了很多時間來解決我的問題,最好的方法。在ObservableCollection中添加項目有訂單 - C#UWP

問題:我有兩個ObservableCollections。 (OCAux - Auxiliar OC,OCMain - 主OC綁定UI)

我有請求http,5個請求。對請求的每個響應都添加到物品OCAux中,然後對物品進行排序。將這些添加到每個訂購給我的OCMain的項目後,這會自動通知UI(正在綁定)。問題是,當添加一個新項目,這是不是有序的,因爲我的訂單是OCAux的結果,即只有請求的訂單請求。如果您在將產品添加到OCMain後訂購該產品,它會閃爍。 每次添加項目時,我都可以訂購OCMain,但會在添加項目時導致UI閃爍。

這是規避如下,但是在UI仍然存在,這些「閃爍」:

    foreach (var item in OCMain) 
        { 
         OCAux.Add(item); 
        } 

        ObservableCollection<Movies> moviesSortedByDatetime= new ObservableCollection<Movies> 
        (OCAux.OrderByDescending(item=> item.DateTime)); 

        OCMain.Clear(); 

        foreach (var item in moviesSortedByDatetime) 
        { 
         if (!OCMain.Contains(item)) 
         { 
          OCMain.Add(item); 
         } 
        } 

任何人都知道如何保持在的ObservableCollection的正確位置插入一個項目?

在此先感謝

+0

添加到OCAux。然後訂購它。使用OCAux.indexOf(item)獲取添加項目的索引。然後將其插入OCMain。 OCMain.Insert(索引,項);那是你想要的嗎? – Archana

+0

我在CollectionViewSource中進行排序,但我只知道WPF。另一個訣竅是返回一個IEnumerable,並在枚舉上調用NotifyProperty更改,但在所有情況下都不起作用。很確定,ObservableCollection沒有InsertAt。 – Paparazzi

回答

0

對於批量插入不斷更新UI每一個變化可能(除非你需要實時更新)。除非您有充足的理由保留OCAux,否則我會將OCMain定製的收集與自定義IObservableCollection實施推遲一批完成後的通知。它可以通過兩種方式完成:

1)最簡單的方法是在禁用通知的地方添加一個BeginUpdate()方法。當您完成收藏工作後,您可以使用EndUpdate()重新啓用通知。概念一類的證明,從ObservableCollection<T>繼承:

public void BeginUpdate() { 
    _disableNotifications = true; 
} 

public void EndUpdate() { 
    _disableNotifications = false; 

    if (_changed) { 
     OnCollectionChanged(
      new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 

     _changed = false; 
    } 
} 

protected override OnCollectionChanged(NotifyCollectionChangedEventArgs e) { 
    if (_disableNotifications) 
     _changed = true; 
    else 
     base.OnCollectionChanged(e); 
} 

只是適用同樣的邏輯也爲INotifyPropertyChanged接口籌集事件PropertyChangedCountItems性能。

2)第二個選項稍微複雜一些,但即使您不知道批量操作何時開始和結束,它也可以工作。首先讓我們做一個假設:用戶不會注意到更新是否延遲了100毫秒。在這種情況下,我們可以做的是忽略的變化,並在NotificationDelay毫秒後發送一個NotifyCollectionChangedAction.Reset。不管你有多少更新,只有一個將在第一個NotificationDelay毫秒之後發送。概念驗證:

protected override OnCollectionChanged(NotifyCollectionChangedEventArgs e) { 
    // Another event already queued a delayed notification 
    if (_isTimerRunning) 
     return; 

    // Assuming _timer is a System.Timers.Timer object already configured 
    // and OnTimerElapsed method attached to its Elapsed event. Note that 
    // you may also use System.Threading.Timer, pick the proper one 
    // according to MSDN and your requirements 
    _isTimerRunning = true; 
    _timer.Start(); 
} 

private void OnTimerElapsed(Object source, ElapsedEventArgs e) { 
    _isTimerRunning = false; 
    _timer.Stop(); 

    base.OnCollectionChanged(
     new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); 
} 

再次,您必須爲INotifyPropertyChanged實施做類似的事情。

請注意,在這兩種情況下,我們會丟棄一些信息,因爲CollectionChanged不會觸發,例如,NotifyCollectionChangedAction.Add但僅與NotifyCollectionChangedAction.Reset發生衝突。無論如何,如果它只是用於綁定,那麼你對INotifyPropertyChanged通知更感興趣,這應該不成問題。