2016-04-21 7 views
1

Ich habe ein Problem, das ist sehr langweilig und ich verbringe viel Zeit, um mein Problem mit dem besten Weg zu lösen.Artikel in ObservableCollection hinzufügen Ordered - C# UWP

Problem: Ich habe zwei ObservableCollections. (OCAux - Auxiliary OC, OCMain - Haupt OC Binde UI)

Ich habe Anfrage http, 5 Anfragen. für jede Antwort auf die Anfrage wird zu den Artikeln OCAux hinzugefügt, und dann werden die Artikel bestellt. Nachdem dies jedem Artikel hinzugefügt wurde, der zu meinem OCMain bestellt wurde, wird automatisch die Benutzeroberfläche benachrichtigt (ist bindend). Das Problem ist, dass beim Hinzufügen eines neuen Artikels, dieser nicht bestellt wird, weil ich Bestellung das Ergebnis von OCAux bin, dh nur Bestellungen auf Anfrage anfordern. Wenn Sie das Element bestellen, nachdem Sie es zu OCMain hinzugefügt haben, blinkt es. Ich könnte das OCMain für jedes Mal bestellen, das Elemente hinzugefügt hat, aber verursacht, dass die UI beim Hinzufügen der Elemente blinkt.

Dies wurde umgangen, wie folgt, aber es bleibt diese „blinkt“ in der Benutzeroberfläche:

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

Wer weiß, wie in der richtigen Position eines ObservableCollection ein Element halten einfügen?

Vielen Dank im Voraus

+0

Fügen Sie es zu OCAux hinzu. Dann bestelle es. Holen Sie den Index des hinzugefügten Artikels mit OCAux.indexOf (item). Dann fügen Sie es in OCMain ein. OCMain.Insert (Index, Element); Ist es das was du wolltest? – Archana

+0

Ich mache die Sortierung in der CollectionViewSource, aber ich kenne nur WPF.Und ein weiterer Trick besteht darin, ein IEnumerable zurückzugeben, das Sie sortieren und NotifyProperty-Änderung für das Enumerable aufrufen, aber das funktioniert nicht in allen Situationen. Ziemlich sicher und ObservableCollection hat kein InsertAt. – Paparazzi

Antwort

0

Für Batch-Einsätze ständig UI aktualisieren für jede Änderung (es sei denn, Sie Echtzeit Updates müssen) sein kann. Wenn Sie keinen guten Grund haben, OCAux zu behalten, dann würde ich OCMain eine geordnete Sammlung mit kundenspezifischer IObservableCollection Implementierung machen, um Benachrichtigungen zu verschieben, nachdem ein Stapel abgeschlossen worden ist. Es kann auf zwei Arten erfolgen:

1) Am einfachsten ist es, eine BeginUpdate() Methode hinzufügen, wo Sie Benachrichtigungen deaktivieren. Wenn Sie Ihren Job mit der Sammlung abgeschlossen haben, aktivieren Sie die Benachrichtigungen erneut mit EndUpdate(). Proof-of-Concept für eine Klasse geerbt von 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); 
} 

Nur gleiche Logik gilt auch für INotifyPropertyChanged Schnittstelle Ereignis PropertyChanged für Count und Items Eigenschaften zu erhöhen.

2) Zweite Option ist etwas komplizierter, aber es funktioniert auch, wenn Sie nicht wissen, wann Batch-Vorgang beginnt und endet. Lassen Sie uns zunächst eine Annahme machen: Benutzer werden nicht bemerken, wenn Aktualisierungen um 100 ms verzögert werden. In diesem Fall können wir ignorieren Änderungen und senden nur eine NotifyCollectionChangedAction.Reset nach NotificationDelay Millisekunden. Es spielt keine Rolle, wie viele Updates Sie haben, nur eine wird nach NotificationDelay Millisekunden von der ersten gesendet. Proof of Concept:

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

Wieder haben Sie etwas ähnliches für INotifyPropertyChanged Implementierung zu tun.

Beachten Sie, dass wir in beiden Fällen einige Informationen löschen, da CollectionChanged nicht z. B. mit NotifyCollectionChangedAction.Add, sondern nur mit NotifyCollectionChangedAction.Reset ausgelöst wird. Wie auch immer, wenn es nur für die Bindung ist, dann sind Sie an INotifyPropertyChanged Benachrichtigungen interessiert und dies sollte kein Problem sein.