2013-06-30 16 views
5

Desidero filtrare una ObservableCollection su un sottoinsieme basato sul tipo (tipo AddPoint) e voglio che venga ordinato in ordine crescente senza duplicati. La mia classe base è ModelBase, con sottoclassi AddPoint, Time, Repeat, ecc. La ObservableCollection MotionSequenceCollection sarà riempita con quei tipi in qualsiasi ordine e alcuni saranno duplicati.Associazione WPF filtrata ObservableCollection ICollectionView a Combobox

Ho provato diverse volte e mostrato di seguito nella proprietà ICollectionView che ho "estratto" da: Bind subset of collection.

COLLECTION osservabile

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

risposta

2

Tutte le raccolte hanno un CollectionView predefinito. WPF si collega sempre a una vista anziché a una raccolta. Se esegui il binding direttamente a una raccolta, WPF si collega effettivamente alla visualizzazione predefinita per quella raccolta. Questa vista predefinita è condivisa da tutti i collegamenti alla raccolta, che fa sì che tutti i collegamenti diretti alla raccolta condividano le caratteristiche di ordinamento, filtro, gruppo e elemento corrente della vista predefinita.

provare a creare CollectionViewSource e impostando la sua logica di filtro in questo modo:

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

Onestamente, sto lottando in modo massiccio con questo. Inizialmente sono andato in @ makc's way w/the CollectionViewSource_FIlter e ho trovato alcuni esempi per aiutare, ma il problema consisteva nel rendere la lista distinta() - era 2 giorni fa e la mia testa era nebbiosa. Il filtro è simile al seguente: – FloppyDisk

+0

Ho bisogno di rivedere il mio commento. Ho fatto funzionare la tua soluzione e ho imparato molto su collectionviewsource. Il problema è che se ci sono duplicati e solo uno mostra nella combobox (vista filtrata), quando ne cambio uno nella raccolta, non si aggiorna aggiungendo il nuovo record modificato. Se ce n'è solo uno, quindi gli aggiornamenti come previsto dopo propertychanged. Questo è il motivo per cui ho seguito un percorso di linq dopo, ma si è rivelato essere disastroso. – FloppyDisk

+0

@FloppyDisk Sono molto contento che non hai appena copiato il passato, ma ho letto e imparato :), non sono sicuro di aver capito completamente il problema, provando a creare un piccolo esempio stand alone e penso che valga la pena una nuova domanda ... – makc

1

Filtro per tipo è facile. Questo dovrebbe funzionare:

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

L'ordinamento è anche abbastanza semplice. Tutto ciò che devi fare è implementare IComparer e assegnarlo alla proprietà CustomSort della vista raccolta.

Non esiste un modo semplice per rimuovere i duplicati (di cui non sono a conoscenza). Ti suggerisco di farlo altrove. Ad esempio, potresti distinguere la tua collezione sottostante.

+0

ho cambiato la mia virata e ha cercato di creare un sottoinsieme di un ObservableCollection con LINQ. Quindi legalo alla mia vista. È stato un serio run-around. Ho un errore che dice che ho bisogno di implementare IComparer. Guardando in quello. Grazie per la risposta. – FloppyDisk

Problemi correlati