2013-06-30 13 views
5

Chcę filtrować ObservableCollection do podzestawu na podstawie typu (typ AddPoint) i chcę, aby był on sortowany rosnąco bez żadnych duplikatów. Moja klasa bazowa to ModelBase, w/sub-klasy AddPoint, Time, Repeat, etc ... ObservableCollection MotionSequenceCollection zostanie wypełniony w/tych typach w dowolnej kolejności, a niektóre będą duplikatami.Wiązanie buforowane WPF ObservableCollection ICollectionView to Combobox

Próbowałem już kilka razy i pokazałem je poniżej w właściwości ICollectionView, którą "wyciągnąłem" z: Bind subset of collection.

obserwowalnych KOLEKCJA

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

Odpowiedz

2

Wszystkie kolekcje mają domyślny CollectionView. WPF zawsze wiąże widok, a nie kolekcję. Jeśli wiążesz bezpośrednio z kolekcją, to WPF faktycznie łączy się z domyślnym widokiem dla tej kolekcji. Ten widok domyślny jest współużytkowany przez wszystkie powiązania z kolekcją, co powoduje, że wszystkie bezpośrednie powiązania z kolekcją dzielą charakterystykę sortowania, filtrowania, grupy i bieżącego elementu dla jednego domyślnego widoku.

spróbuj utworzyć CollectionViewSource i ustawienie jego logiki filtrowania tak:

//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

Szczerze mówiąc, walczę z tym masowo. Pierwotnie poszedłem na ścieżkę @ makc w/CollectionViewSource_FIlter i znalazłem kilka przykładów pomocy, ale problem polegał na tym, że lista była odmienna() - to było 2 dni temu i moja głowa jest zamglona. Filtr wygląda następująco: – FloppyDisk

+0

Muszę poprawić mój komentarz. Zrobiłem twoje rozwiązanie działające i nauczyłem się dużo o zbiorachviewview. Problem polega na tym, że jeśli są duplikaty i tylko jeden pokazuje w combobox (filtrowany widok), to kiedy edytuję jeden w kolekcji, nie aktualizuje się przez dodanie nowych edytowany rekord. Jeśli jest tylko jeden, to aktualizacje są zgodne z oczekiwaniami po przeprojektowaniu. Dlatego poszedłem ścieżką linq, ale to okazało się katastrofalne. – FloppyDisk

+0

@FloppyDisk Bardzo się cieszę, że nie skopiowałeś przeszłości, ale przeczytałeś i nauczyłeś się :), nie jestem pewien czy rozumiem problem całkowicie próbując stworzyć mały, samodzielny przykład i myślę, że warto postawić nowe pytanie ... – makc

1

filtrowanie według typu jest łatwe. Powinno to zadziałać:

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

Sortowanie również jest łatwe. Wszystko, co musisz zrobić, to zaimplementować IComparer i przypisać ją do właściwości widoku kolekcji CustomSort.

Nie ma łatwego sposobu na usunięcie duplikatów (nie jestem tego świadomy). Proponuję ci to zrobić gdzie indziej. Na przykład możesz odróżnić swoją kolekcję podstawową.

+0

zmieniłem taktykę i próbował stworzyć podzbiór ObservableCollection z LINQ. Następnie przywiąż to do mojego widoku. To był poważny problem. Mam błąd, który mówi, że muszę wdrożyć program IComparer. Patrząc w to. Dzięki za odpowiedzi. – FloppyDisk