2011-02-07 3 views
8

Ho un'applicazione wpf-mvvm.Posso filtrare una raccolta da xaml?

Ho un raccolta osservabile nel mio ViewModel

public ObservableCollection<BatchImportResultMessageDto> ImportMessageList { get; set; } 

"BatchImportResultMessageDto" contiene due proprietà ..

messaggio risultato type..and. Il tipo di risultato può essere positivo o negativo.

Devo visualizzare il successo in una casella di riepilogo .. e l'errore in un'altra casella di riepilogo.

Posso farlo .. avendo 2 collezioni osservabili in viewmodel per contenere successo/fallimento.

public ObservableCollection<BatchImportResultMessageDto> ImportFailureMessageList { get; set; } // To hold the failure messages. 
public ObservableCollection<BatchImportResultMessageDto> ImportSuccessMessageList { get; set; } // To hold the sucess messages. 

Ma c'è qualche altro modo migliore per filtrarlo (senza nuove due raccolte)?

+0

Sì - con le estensioni di markup, vedi http://stackoverflow.com/questions/6461826/in-wpf-can-you-filter-a-collectionviewsource-without-code-behind – Slugart

risposta

11

È possibile utilizzare un CollectionViewSource e trasformarlo in una proprietà del modello di visualizzazione e associarlo a quella invece della raccolta ImportMessageList direttamente da XAML. Impostare la propria collezione ImportMessageList come origine di CollectionViewSource, quindi configurare un predicato per eseguire il filtraggio su CollectionViewSource.

Qualcosa di simile:

private ICollectionView messageListView; 
public ICollectionView MessageListView 
{ 
    get { return this.messageListView; } 
    private set 
    { 
     if (value == this.messageListView) 
     { 
     return; 
     } 

     this.messageListView = value; 
     this.NotifyOfPropertyChange(() => this.MessageListView); 
    } 
} 

... 


this.MessageListView = CollectionViewSource.GetDefaultView(this.ImportMessageList); 
this.MessageListView.Filter = new Predicate<object>(this.FilterMessageList); 

... 

public bool FilterMessageList(object item) 
{ 
    // inspect item as message here, and return true 
    // for that object instance to include it, false otherwise 
    return true; 
} 
+0

come filtrare in CollectionViewSource? – Relativity

+0

esempio di filtro aggiunto – devdigital

+0

Quindi .. per lisbox possiamo passare "MessageListView"? – Relativity

10

È possibile farlo attraverso la creazione di due CollectionViewSource oggetti e impostando un filtro su ciascuno.

Come creare un CVS in XAML da una VM vincolante (Source):

<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> 
    <Window.Resources> 
     <CollectionViewSource Source="{Binding}" x:Key="customerView"> 
      <CollectionViewSource.GroupDescriptions> 
       <PropertyGroupDescription PropertyName="Country" /> 
      </CollectionViewSource.GroupDescriptions> 
     </CollectionViewSource> 
    </Window.Resources> 
    <ListBox ItemSource="{Binding Source={StaticResource customerView}}" /> 
</Window> 

come filtrare un CVS in un codice dietro (È possibile utilizzare la reflection per esaminare le proprietà del modello, se si non si vuole fare un riferimento ad esso Source):.

<CollectionViewSource x:Key="MyCVS" 
           Source="{StaticResource CulturesProvider}" 
           Filter="MyCVS_Filter" /> 

con (codice dietro)

void MyCVS_Filter(object sender, FilterEventArgs e) 
{ 
    CultureInfo item = e.Item as CultureInfo; 
    if (item.IetfLanguageTag.StartsWith("en-")) 
    { 
     e.Accepted = true; 
    } 
    else 
    { 
     e.Accepted = false; 
    } 
} 
+1

Il code-behind viola MVVM-patern. –

+9

Non sempre viola lo schema mvvm per inserire tale codice nel code-behind. Se si tratta puramente di una vista correlata (solo filtraggio), allora va bene usare il code-behind. Potrebbe non essere bello come una proprietà binding o xaml, ma CollectionViewSource non supporta quello per i filtri. – bzuillsmith