2011-02-07 47 views
8

Tengo una aplicación wpf-mvvm.¿Puedo filtrar una colección de xaml?

que tienen una colección observable en mi modelo de vista

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

"BatchImportResultMessageDto" contiene dos propiedades ..

mensaje de resultado type..and. El tipo de resultado puede ser exitoso o fallido.

Necesito mostrar el éxito en un cuadro de lista ... y error en otro cuadro de lista.

Puedo hacer esto ... al tener 2 colecciones observables en viewmodel para mantener el éxito/fracaso.

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

¿Pero hay alguna otra manera mejor para poder filtrarla (sin dos nuevas colecciones)?

+0

Sí - con las extensiones de marcado, consulte http://stackoverflow.com/questions/6461826/in-wpf-can-you-filter-a-collectionviewsource-without-code-behind – Slugart

Respuesta

11

Puede usar un CollectionViewSource y convertirlo en una propiedad de su modelo de vista, y vincularlo a ese en lugar de su colección ImportMessageList directamente desde el XAML. Establezca su colección ImportMessageList como Origen del CollectionViewSource, y luego configure un predicado para filtrar en el CollectionViewSource.

Algo así como:

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

cómo filtrar en CollectionViewSource? – Relativity

+0

filtro ejemplo agregado – devdigital

+0

Entonces ... ¿para lisbox podemos pasar "MessageListView"? – Relativity

10

Usted puede hacer esto mediante la creación de dos CollectionViewSource objetos y establecer un filtro en cada uno.

Como crear un CVS en XAML de una máquina virtual de unión (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> 

cómo filtrar un CVS en un código detrás (Puede utilizar la reflexión para ver las propiedades del modelo si no quieren hacer una referencia a él Source):.

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

con (código detrás)

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

El código subyacente infringe MVVM-patern. –

+9

No siempre viola el patrón mvvm para poner dicho código en el código subyacente. Si está puramente relacionado con la vista (solo filtrado), entonces está bien usar código subyacente. Puede que no sea tan bueno como una propiedad vinculante o xaml, pero CollectionViewSource no es compatible con los filtros. – bzuillsmith

Cuestiones relacionadas