2010-04-18 14 views
5

Estoy tratando de que mi primera aplicación WPF funcione usando MVVM, y he tenido un pequeño problema de enlace.WPF: Configuración de DataContext de un UserControl con Enlace no funciona en XAML

La configuración es que tengo una vista & modelo de vista que mantiene los detalles de los usuarios (los padres), y para tratar de mantener las cosas simples que he puesto una sección de esa visión en una vista separada & modelo de vista (el niño). La vista secundaria se define como un UserControl.

El problema que tengo es cómo configurar el DataContext de la vista secundaria (UserControl). Mi padre modelo de vista tiene una propiedad que expone al niño modelo de vista, así:

class ParentViewModel: INotifyPropertyChanged 
{ 
    public ChildViewModel childViewModel { get; set; } 
    //... 
} 

En el XAML para mi vista padre (que tiene su DataContext conjunto a la ParentViewModel), trato de establecer el DataContext de la vista del niño de la siguiente manera:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

Sin embargo, esto no funciona. El DataContext de la vista secundaria está configurado con el mismo DataContext que la vista principal (es decir, el ParentViewModel), como si no lo estuviera configurando en absoluto. También probé establecer el DataContext en el niño ver en sí, que tampoco funciona:

<UserControl x:Class="DietRecorder.Client.View.ChildView" 
    DataContext="childViewModel" 

he encontrado un par de maneras de evitar esto. En la vista del niño, puedo unir todo mediante la inclusión de la ChildViewModel en la ruta:

<SomeControl Visibility="{Binding Path=childViewModel.IsVisible}"> 

pero no quiero la vista hijo tenga este nivel de conciencia de la jerarquía. Ajuste de la DataContext en el código también funciona - sin embargo, tengo que hacer esto después de mostrar la vista padre, de lo contrario el DataContext simplemente se sobreescribe cuando llamo Show():

parentView.Show(); 
parentView.ChildView.DataContext = parentViewModel.childViewModel; 

Este código también me hace sentir incómoda, lo con la violación de LOD y todo.

Es sólo el DataContext que parece ser el problema - me puedo unir otras cosas en el niño, por ejemplo, he intentado unir el Tamaño de Letra a una propiedad int sólo para probarlo:

<views:ChildView 
    x:Name="ChildView" 
    FontSize="{Binding Path=someVal}"/> 

y que funciona multa.

Pero estoy seguro de que el enlace del DataContext debería funcionar; he visto ejemplos similares de este tipo de cosas. ¿Me he perdido algo obvio aquí? ¿Hay alguna razón por la que esto no funcione? ¿Hay algún error ortográfico en alguna parte? (Cambié el nombre de las cosas para su beneficio, así que no podrá ayudarme allí de todos modos).

Cualquier idea bienvenida.

Editar

Revisando el código de nuevo, parece que he cometido un error en alguna parte, como el siguiente XAML en la vista padre hace ahora parece funcionar:

<views:ChildView 
    x:Name="ChildView" 
    DataContext="{Binding childViewModel}"/> 

estoy no estoy seguro de por qué no pude hacer que funcione originalmente, o lo que podría haber cambiado para que funcione. Tal vez fue el problema INotifyPropertyChanged como sugiere una de las respuestas. Oh, bueno, hacia adelante y hacia arriba ...

Respuesta

2

Sospecho que es porque la propiedad childViewModel no provoca el evento PropertyChanged. Cuando se evalúa el enlace, es posible que esta propiedad sea nula (en cuyo caso el DataContext simplemente volverá a caer en el enlace principal). Cuando se crea una instancia posterior de childViewModel, no se genera ningún evento PropertyChanged y nunca se informa al enlace que ahora hay un DataContext.

Intente levantar evento PropertyChanged en la propiedad childViewModel.

Cheers, Laurent

+0

Buena idea, pero no me alegra, me temo. Estaba pensando que podría ser algo relacionado con el orden, pero el viewModel hijo debería estar disponible cuando se produce la vinculación, y funciona cuando configuro el tamaño de fuente con la propiedad int, que ocurre al mismo tiempo, y eso no funciona. t usa PropertyChanged. –

2

que estaba buscando lo mismo y yo encontramos una manera de hacerlo. Básicamente, I unido al DataContext del niño a la DataContext de algunos de los padres (la ventana) usando

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

donde me he fijado x:Name="_topLevel" en un cierto control de los padres (la ventana).

Intenté usar RelativeSource/FindAncestor en lugar de ElementName, pero no funcionó, pero probablemente fue mi culpa.

Se siente como un truco para mí, pero es mejor que vincularlo al modelo de vista de nivel superior.

+0

Aunque no lo he probado, debería funcionar, así que le daré +1 para el esfuerzo después de todo este tiempo, pero esta solución tiene el mismo problema que una de las soluciones que sugerí anteriormente, que es que el niño sabe sobre el padre. Eso es solo un mal olor o un problema real, dependiendo de si usa al niño en diferentes vistas parentales o no. Al verificar mi código para esta respuesta, descubrí que ahora funciona, aunque no estoy seguro por qué; consulte la edición para obtener más detalles. –

2

Esta no es una respuesta a la pregunta, pero podría ayudar a otros en las mismas circunstancias.

Me golpeó exactamente este problema y encontró que el enfoque

parentView.ChildView.DataContext = parentViewModel.childViewModel; 

funcionaba (aunque me pareció que funcionaba antes de hacer Show()), pero no tenía los mismos escrúpulos tanto como a la pregunta original, por lo que trató el

DataContext="{Binding ElementName=_topLevel, Path=DataContext.childViewModel}" 

enfoque, que también parecía funcionar. Pero luego intenté volver al código original y al XAML original nuevamente, y ahora de repente también funcionó. Esto refleja el comportamiento del autor de la pregunta original, donde el autor pensó que había cometido un error en alguna parte, ya que el XAML parecía comenzar a funcionar sin ninguna razón obvia.

El único cambio que puedo ver es que Visual Studio ahora muestra datos de muestra en el UserControl en tiempo de diseño, por lo que ha almacenado en caché algunos datos de muestra en algún lugar, y parece que funciona. No estoy seguro de cuál de los dos cambios hizo que esto ocurra, desafortunadamente.

El aspecto de los datos de muestra me hace preguntarme si el problema está relacionado con el uso de d: DataContext, que tengo en los archivos XAML padre y secundarios, pero eso es solo una especulación.

Cuestiones relacionadas