2013-06-30 9 views
5

Ich möchte eine ObservableCollection auf eine Teilmenge basierend auf Typ (Typ AddPoint) filtern und will es aufsteigend ohne Duplikate geordnet. Meine Basisklasse ist ModelBase, mit den Unterklassen AddPoint, Time, Repeat usw. Die ObservableCollection MotionSequenceCollection wird mit diesen Typen in beliebiger Reihenfolge gefüllt und einige werden Duplikate sein.WPF Bindung gefiltert ObservableCollection ICollectionView zu Combobox

Ich habe mehrere verschiedene Male ausprobiert und zeigte sie unten in der ICollectionView-Eigenschaft, die ich 'zog' aus: Bind subset of collection.

BEOBACHTBARER COLLECTION

private ObservableCollection<ModelBase> _motionSequenceCollection = 
     new ObservableCollection<ModelBase>(); 

    public ObservableCollection<ModelBase> MotionSequenceCollection 
    { 
     get 
     { 
      return _motionSequenceCollection; 
     } 

     set 
     { 
      if (_motionSequenceCollection == value) 
      { 
       return; 
      } 

      var oldValue = _motionSequenceCollection; 
      _motionSequenceCollection = value; 

      // Update bindings, no broadcast 
      RaisePropertyChanged(); 
     } 
    } 

    public ICollectionView Location 
    { 
     get 
     { 
      var location = CollectionViewSource.GetDefaultView(_motionSequenceCollection); 

      //DOES NOT WORK. PROBLEM: GetType() creates type of system.type() and AddPoint, which don't work. Need a cast, or something?? 
      // found at https://stackoverflow.com/questions/9621393/bind-subset-of-collection The problem is that there is an error: 
      // Cannot apply operator '==' to operands of type 'System.Type' and 'MotionSeq.Model.AddPoint', 
      // candidates are: 
      //   bool ==(System.Reflection.MemberInfo, System.Reflection.memberInfo) (in class MemberInfo) 
      //   bool ==(System.type, System.Type) (in class Type) 
      //location.Filter = p => (p as ModelBase).GetType() == AddPoint; 

      //DOES NOT WORK. PROBLEM: Affects the main collection and won't let TIME type added. 
      //location.Filter = o1 => (o1 is AddPoint); 

      //DOES NOT WORK. PROBLEM: Sorts fine, but also sorts MotionSequenceCollection!! What up w/ that!? 
      //location.SortDescriptions.Add(new SortDescription("AddPointClassName", ListSortDirection.Ascending)); 

      //DOES NOT WORK. PROBLEM: MotionSequenceCollection does not update. 
      //location.Filter = p => (p as ModelBase) == AddPoint; 

      //DOES NOT WORK. PROBLEM: Source is not instantiated(?) and exmaple from stackoverflow and not sure how that got there in the first place. 
      //source.Filter = p => (p as ModelBase).GetType() == "AddPoint"; 
      //return source; 

      return location; 
     } 
    } 

Antwort

2

Alle Sammlungen verfügen standardmäßig über CollectionView. WPF bindet immer an eine Ansicht und nicht an eine Sammlung. Wenn Sie direkt an eine Sammlung binden, bindet WPF tatsächlich an die Standardansicht für diese Sammlung. Diese Standardansicht wird von allen Bindungen an die Auflistung gemeinsam verwendet, wodurch alle direkten Bindungen an die Auflistung die Eigenschaften von sort, filter, group und current item der einen Standardansicht gemeinsam nutzen.

try CollectionViewSource und Einstellen seiner Filterlogik wie folgt zu schaffen:

//create it as static resource and bind your ItemsControl to it 
<CollectionViewSource x:Key="csv" Source="{StaticResource MotionSequenceCollection}" 
        Filter="CollectionViewSource_Filter"> 
    <CollectionViewSource.GroupDescriptions> 
     <PropertyGroupDescription PropertyName="YYY"/> 
    </CollectionViewSource.GroupDescriptions> 
    <CollectionViewSource.SortDescriptions> 
     <scm:SortDescription PropertyName="YYY" Direction="Ascending"/> 
    </CollectionViewSource.SortDescriptions> 
</CollectionViewSource> 

private void CollectionViewSource_Filter(object sender, FilterEventArgs e) 
{ 
    var t = e.Item as ModelBase; 
    if (t != null) 

    { 
     //use your filtering logic here 

    } 
} 
+0

Ehrlich, ich kämpfe massiv damit. Ich ging ursprünglich @ Makc Weg mit dem CollectionViewSource_FIlter und fand ein paar Beispiele zu helfen, aber das Problem war mit der Erstellung der Liste distinct() - es war vor 2 Tagen und mein Kopf ist nebelig. Der Filter ist wie folgt: – FloppyDisk

+0

Ich muss meinen Kommentar revidieren. Ich habe Ihre Lösung funktioniert und viel über collectionviewource gelernt. Das Problem ist, dass, wenn es Dubletten gibt und nur eine in der Combobox (gefilterte Ansicht) zeigt, wenn ich eine in der Sammlung bearbeite, wird es nicht durch Hinzufügen der neu aktualisiert bearbeiteter Datensatz Wenn nur eine vorhanden ist, wird diese nach der Änderung der Eigenschaft wie erwartet aktualisiert. Deshalb bin ich nachher auf einen Linq-Pfad gegangen, aber das hat sich als katastrophal erwiesen. – FloppyDisk

+0

@FloppyDisk Ich bin sehr froh, dass du nicht nur kopiert hast, sondern gelesen und gelernt hast :), ich bin mir nicht sicher, ob ich das Problem vollständig verstehe, versuche ein kleines Stand-alone-Beispiel zu erstellen und ich denke, es ist eine neue Frage wert ... – makc

1

Filtern nach Typ ist einfach. Das sollte funktionieren:

location.Filter = p => p.GetType() == typeof(AddPoint); 

Sortieren ist auch ziemlich einfach. Alles was Sie tun müssen, ist IComparer zu implementieren und es CustomSort Eigenschaft der Sammlung anzuzeigen.

Es gibt keine einfache Möglichkeit, Duplikate zu entfernen (nicht, dass ich davon weiß). Ich schlage dir vor, es woanders zu machen. Zum Beispiel könnten Sie Ihre zugrunde liegende Sammlung unterscheiden.

+0

änderte ich meinen Tack und versuchte, eine Teilmenge einer ObservableCollection mit LINQ zu erstellen. Dann verbinde das wieder mit meiner Sicht. Es war ein ernsthafter Umweg. Ich habe einen Fehler, der besagt, dass ich IComparer implementieren muss. Ein Blick darauf. Danke für die Antwort. – FloppyDisk