2011-09-12 16 views
16

Quiero reutilizar mis UserControls en otros UserControls como página o ventana como DataTemplates, en este ejemplo dentro de un ListBox. Todo es MVVM.UserControl como DataTemplate dentro de ListBox

Tengo un UserControl llamado "CardControl" para mostrar un objeto simple "Tarjeta". La tarjeta tiene dos propiedades, "ID" y "CardImage". Los controles DataContext se configuran a través de XAML. Si abro este UserControl en VS o Blend, me muestra la Tarjeta ficticia que he definido en el ViewModel correspondiente.

Ahora tengo otro UserControl llamado "CardSetControl", que debería mostrar una colección de Tarjetas. Entonces ViewModel tiene una propiedad del tipo ObservableCollection <Card> llamada "Cards".

Aquí está el código:

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 

     <!-- WORKING, but not what i want --> 
     <TextBlock Text="{Binding ID}" /> // would display ID of Card 
     <Image Source="{Binding Image}" /> // would display Image of Card 

     <!-- NOT WORKING, but this is how i want it to work --> 
     <UserControls:CardControl DataContext="{Binding "Current listbox item as DataContext of CardControl???"}" /> 

     </StackPanel> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Después de leer un montón de artículos sobre MVVM y DataContext/Encuadernación yo todavía no consigo que funcione. ¿Cómo se hace todo esto jerárquicamente USerControls/DataContexts de la mejor manera limpia?

Respuesta

13

para el control ListBox se crea un ListBoxItem inferido para cada elemento de la fuente artículos. El elemento se establece como el DataContext y su ItemTemplate se establece como la plantilla. Dado que DataContext hereda, no tiene que establecerlo explícitamente porque ya es la instancia de Card en su DataTemplate.

Para este caso, no tiene que configurar el DC en CardControl porque está configurado para usted.

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <StackPanel> 

     <!-- WORKING, but not what i want --> 
     <TextBlock Text="{Binding ID}" /> // would display ID of Card 
     <Image Source="{Binding Image}" /> // would display Image of Card 

     <!-- NOT WORKING, but this is how i want it to work --> 
     <UserControls:CardControl /> 

     </StackPanel> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Depende de usted.

14

En su ejemplo, el DataContext del UserControl sería la tarjeta seleccionada actualmente. Fluye al UserControl y sus controles secundarios como cualquier otro UIElement recibe el DataContext de su control principal.

esto funcionaría:

<ListBox x:Name="MyList" ItemsSource="{Binding CardSet.Cards}"> 
    <ListBox.ItemTemplate> 
    <DataTemplate> 
     <UserControls:CardControl /> 
    </DataTemplate> 
    </ListBox.ItemTemplate> 
</ListBox> 

Dónde CardControl es:

<UserControl x:Class="MySolution.CardControl" 
      OtherProperties="Not shown to keep this example small"> 
     <StackPanel> 
     <TextBlock Text="{Binding ID}" /> 
     <Image Source="{Binding Image}" /> 
     </StackPanel> 
</UserControl> 
+0

Will, mis disculpas básicamente dio exactamente la misma respuesta que usted.Debería actualizar la página antes de responder la próxima vez;) –

+0

De esta forma, un modelo (Tarjeta) pasa como un DataContext al control del usuario. ¿Qué sucede si me gustaría tener ese control de usuario para usar su modelo de vista? ¿Cómo debo pasar este modelo recibido a un modelo de vista y vincular el modelo de vista a la vista del control? –

+0

@OndrejJanacek: UserControls no debe diseñarse para tener sus propios modelos de vista. Deben tener propiedades públicas vinculables en su superficie que los usuarios enlazarán a sus propios modelos de vista. Esta respuesta se configura más para el OP que las mejores prácticas:/ – Will

1

Gracias por sus respuestas, pero descubrí que mi problema era otro que había mencionado. Si lo hace como lo describió, puedo ver mis UserControls (CardControl) que se utilizan como plantilla para los Elementos ListBox y el ID y la Imagen se muestran correctamente.

Además de eso, siempre me pregunté por qué se pueden mostrar la ID y la Imagen, mientras que no puedo vincularme a otras propiedades que he definido en ViewModel.

Hoy he encontrado un artículo interesante sobre DataContext hierachy. Allí se dice que el DataContext dentro de un ListBox NO ES el mismo DataContext que en la página en la que está el ListBox. No lo vi antes, así que pensé que tenía que configurar el DataContext de alguna manera como mencioné en el pregunta. Ahora puedo enlazar a todas las propiedades.

Aquí está el artículo: http://blog.thekieners.com/2010/09/08/relativesource-binding-with-findancestor-mode-in-silverlight/

Cuestiones relacionadas