wpf - example - UserControl''s DataContext
grid datacontext wpf c# (5)
¿Por qué no puedes usar <UserControl DataContext="{RelativeSource Self}">
?
Así es como usarías el control
<Grid DataContext="{StaticResource ViewModel}">
<!-- Here we''d expect this control to be bound to -->
<!-- ColorToUse on our ViewModel resource -->
<controls:ColorWithText Color="{Binding ColorToUse}" />
</Grid>
Ahora que codificamos nuestro contexto de datos en el control, intentará buscar la propiedad ColorToUse en el objeto ColorWithText, no su ViewModel, que obviamente fallará.
Es por eso que no puede configurar DataContext en el control de usuario. Gracias a Brandur por hacerme entender eso.
¿Cuál es la mejor manera de hacer algo como esto?
En su lugar, debe establecer DataContext en el primer elemento de UI secundario bajo su control.
En tu caso quieres
<StackPanel
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"
Orientation="Horizontal" >
Ahora tiene un DataContext que se refiere a su control para que pueda acceder a cualquier propiedad de ese control utilizando enlaces relativos.
Estoy creando un UserControl
. Quiero usar algo como esto:
<controls:ColorWithText Color="Red" Text="Red color" />
Hasta ahora, he implementado controles similares como este:
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" >
<Border Width="15" Height="15" Background="{Binding Color, ElementName=ThisControl}" />
<TextBlock Text="{Binding Text, ElementName=ThisControl}" />
</StackPanel>
</UserControl>
donde Color
y Text
son propiedades de dependencia del control definido en el código. Esto funciona, pero especificar ElementName
cada vez parece innecesario.
Otra opción que funciona es usar
<UserControl x:Class=… DataContext="{Binding ElementName=ThisControl}" Name="ThisControl">
y no especificando ElementName
s, pero tampoco me parece una solución limpia.
Tengo dos preguntas:
- ¿Por qué no funciona
<UserControl DataContext="{RelativeSource Self}">
? - ¿Cuál es la mejor manera de hacer algo como esto?
Deberías estar usando
{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=Color}
para el enlace de datos Las dudas relacionadas siempre refieren esta hoja.
http://www.nbdtech.com/Blog/archive/2009/02/02/wpf-xaml-data-binding-cheat-sheet.aspx
Para el primero, intente:
<UserControl DataContext="{Binding RelativeSource={RelativeSource Self}}">
Y para la segunda pregunta, creo que usar ElementName
o AncestorBinding
es la mejor forma de vincular las propiedades de UserControl
.
Puede establecer el contexto de datos en el propio constructor.
public ColorWithText()
{
InitializeComponent();
DataContext = this;
}
Ahora puedes decir simplemente
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" >
<Border Width="15" Height="15" Background="{Binding Color}" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
</UserControl>
Sé que esto ha sido respondido, pero ninguna de las explicaciones da una comprensión de DataContext y cómo funciona. Este enlace hace un gran trabajo para eso.
TODO LO QUE QUISE SABER SOBRE EL DATABO EN WPF, SILVERLIGHT Y WP7 (SEGUNDA PARTE)
En respuesta a tu pregunta n. ° 1
¿Por qué no funciona <UserControl DataContext="{RelativeSource Self}">
?
Este es un resumen del enlace de arriba. DataContext no se debe establecer en Self en UserControl Element level. Esto se debe a que rompe la herencia del DataContext. Si lo establece en sí mismo y coloca este control en una ventana u otro control, no heredará el DataContext de Windows.
DataContext se hereda para todos los elementos inferiores de XAML y para todos los XAML de UserControls a menos que se sobrescriba en alguna parte. Al configurar UserControl DataContext para sí mismo, esto sobrescribe el DataContext y rompe la herencia. En su lugar, anide un Elemento en el XAML, en su caso, el StackPanel. Coloque el enlace DataContext aquí y conéctelo al UserControl. Esto preserva la herencia.
Consulte también este enlace a continuación para obtener una explicación detallada de esto.
UN PATRÓN SIMPLE PARA CREAR CONTROLES DE USUARIO REUTILIZABLES EN WPF / SILVERLIGHT
En respuesta a su pregunta n. ° 2
¿Cuál es la mejor manera de hacer algo como esto?
Vea el ejemplo de código a continuación.
<UserControl x:Class="Namespace.ColorWithText" Name="ThisControl">
<StackPanel Orientation="Horizontal" DataContext={Binding ElementName=ThisControl}>
<Border Width="15" Height="15" Background="{Binding Color" />
<TextBlock Text="{Binding Text}" />
</StackPanel>
Tenga en cuenta que una vez que haga esto, no necesitará ElementName en cada enlace.