2011-09-21 18 views
10

En WPF puede utilizar un IValueConverter o IMultiValueConverter para convertir un valor enlazado a datos de decir una int a un Color.¿Hay alguna forma de convertir los miembros de una colección utilizada como ItemsSource?

tengo una colección de objetos del modelo que me gustaría convertir a sus representaciones ViewModel pero en este escenario ,

<ListBox ItemsSource="{Binding ModelItems, 
    Converter={StaticResource ModelToViewModelConverter}" /> 

el convertidor se escribiría para convertir toda la colección ModelItems a la vez.

Deseo convertir los elementos de la colección individualmente, ¿hay alguna manera de hacerlo?

Respuesta

21

No puede establecer el convertidor en la colección en sí, porque obtendría la colección como entrada. Tiene dos opciones:

  1. Asegúrese de que su convertidor también pueda ocuparse de las colecciones (IEnumerable).
  2. Usa el convertidor dentro de la plantilla del artículo.

Si desea utilizar el segundo enfoque, a continuación, utilizar algo como esto:

<ListBox ItemsSource="{Binding ModelItems}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <ContentPresenter Content="{Binding Converter={StaticResource ModelToViewModelConverter}}" 
         ContentTemplate="{StaticResource MyOptionalDataTemplate}"/> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Si no necesita un DataTemplate costumbre, entonces puede saltarse el atributo ContentTemplate.

+0

Gracias, creo que debería funcionar para mí, lo intentaré. – Grokodile

2

Sí, puedes. Está actuando de la misma manera que con IValueConverter. Simplemente trata el parámetro de valor para el método Convert como una colección.

Aquí es un ejemplo de convertidor para una colección:

public class DataConvert : IValueConverter 
{ 
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     ObservableCollection<int> convertible = null; 
     var result = value as ObservableCollection<string>; 

     if (result != null) 
     { 
      convertible = new ObservableCollection<int>(); 
      foreach (var item in result) 
      { 
       if (item == "first") 
       { 
        convertible.Add(1); 
       } 
       else if (item == "second") 
       { 
        convertible.Add(2); 
       } 
       else if (item == "third") 
       { 
        convertible.Add(3); 
       } 
      } 
     } 

     return convertible; 
    } 

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
    { 
     throw new NotImplementedException(); 
    } 
} 

En este caso es sólo una prueba de concepto, pero creo que debe mostrar muy bien la idea. El convertidor convierte desde una simple colección de cadenas como esto:

ModelItems = new ObservableCollection<string>(); 
     ModelItems.Add("third"); 
     ModelItems.Add("first"); 
     ModelItems.Add("second"); 

en una colección de números enteros que corresponden al significado cadena.

Y aquí es el XAML correspondiente (loc es la referencia de los conjuntos actual en la que es el convertidor):

<Window.Resources> 
    <loc:DataConvert x:Key="DataConverter"/> 
</Window.Resources> 
<Grid x:Name="MainGrid"> 
    <ListBox ItemsSource="{Binding ModelItems, Converter={StaticResource DataConverter}}"/> 
</Grid> 

Si desea hacer una doble vía de unión, hay que aplicar también al convertir de nuevo . A partir de la experiencia de trabajar con MVVM, sugiero usar algo como el Patrón de fábrica para transformarlo de Modelo en ViewModel y viceversa.

+1

Gracias louie, pero esto no es lo que busco, podría utilizar un CollectionViewSource y tener cierta lógica de filtrado, así que no quiero tener que iterar sobre toda la colección cada vez que algo cambia, por lo tanto, el último oración de mi pregunta. – Grokodile

+0

Lo siento, no vi la última frase. Buena suerte. – louie

0

Aquí hay otro ejemplo. Estoy usando MVVM Caliburn Micro. MyObjects es una lista de enumeraciones en mi caso.

<ListBox x:Name="MyObjects"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <TextBlock Text="{Binding ., Converter={StaticResource MyConverter}}"/> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 
Cuestiones relacionadas