wpf data-binding user-controls

¿Cuáles son las ventajas/desventajas de las diferentes formas de vincular el contenido en un UserControl de WPF a sus propiedades?



data-binding user-controls (2)

utilizo el enlace de elementos para controles de usuario cuando se vinculan a sus propias propiedades de dependencia.

<UserControl x:Class="MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" x:Name="uc"> <StackPanel> <TextBox Text="{Binding ElementName=uc,Path=TheText}" /> </StackPanel> </UserControl>

Cuando comencé a trabajar con UserControls de WPF, me encontré con varias formas de vincular el contenido de un UserControl a una de sus propiedades.

Aquí hay un código de ejemplo C # para mi control:

public sealed partial class MyUserControl : UserControl { public MyUserControl() { InitializeComponent(); } public static readonly DependencyProperty TheTextProperty = DependencyProperty.Register("TheText", typeof (string), typeof(MyUserControl), new FrameworkPropertyMetadata(0, FrameworkPropertyMetadataOptions. BindsTwoWayByDefault) ); public string TheText { get { return (string)GetValue(TheTextProperty); } set { SetValue(TheTextProperty, value); } } }

Y aquí están las diferentes formas en que encontré para vincular el contenido a esta propiedad:

El contenido utiliza el enlace con RelativeSource / AncestorType

<UserControl x:Class="MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <StackPanel> <TextBox Text="{Binding TheText, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" /> </StackPanel> </UserControl>

DataContext de la raíz del árbol visual se establece en UserControl en XAML

<UserControl x:Class="MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <StackPanel DataContext="{Binding RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"> <TextBox Text="{Binding TheText}" /> </StackPanel> </UserControl>

DataContext de la raíz del árbol visual se establece en UserControl en el constructor

<UserControl x:Class="MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"> <StackPanel x:Name="VisualTreeRoot"> <TextBox Text="{Binding TheText}" /> </StackPanel> </UserControl>

Aquí está el constructor:

public MyUserControl() { InitializeComponent(); VisualTreeRoot.DataContext = this; }

Por último, pero no menos importante: una advertencia para otras personas nuevas en la programación UserControls en WPF

La primera vez que quise vincular el contenido de un UserControl a una de sus propiedades, pensé "hey, simplemente establezcamos el DataContext del UserControl directamente a sí mismo":

<UserControl x:Class="MyUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" DataContext="{Binding RelativeSource={RelativeSource Self}}">

O:

public MyUserControl() { InitializeComponent(); this.DataContext = this; }

Sin embargo, esto no funciona si un usuario de UserControl desea vincular sus propiedades a otras fuentes de enlace. El UserControl necesita heredar el DataContext de su padre para que esto funcione. Al sobreescribirlo como se muestra arriba, los enlaces ya no encontrarán sus fuentes.

Mis últimas preguntas:

  • ¿Cuáles son las ventajas y desventajas de cada uno de los métodos presentados?
  • ¿Cuándo deberías usar qué método?
  • ¿Hay más métodos?

  • Bueno, en el primer caso no hay ningún DataContext para el conjunto de TextBox en ninguno de sus padres. Por lo tanto, tiene que decirle al TextBox dónde en el VisualTree está el control con esa propiedad directamente en él.
  • Segundo caso, DataContext se establece en StackPanel que TextBox hereda en consecuencia. Esto es mejor que acercarse a uno si tiene múltiples controles en el StackPanel
  • Establecer DataContext en el UserControl sí no siempre es incorrecto (a través de constructor o xaml). Digo esto porque si tiene 20 controles de los cuales 15 necesitan usar propiedades definidas en su clase UserControl actual y 5 que necesitan el padre del DataContext del UserControl , siempre puede usar un enlace RelativeSource FindAncestor en la minoría.

Solo puedo pensar en el "método" que puede mostrar pt3 que mencioné es algo así como

<!-- Can change type to another userControl too and specify Ancestorlevel --> <TextBlock Text="{Binding TheText, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />

^^ Esto funcionará bien incluso si el UserControl padre de TextBlock tiene a sí mismo como es DataContext

En cuanto a cuándo usar qué.

Esa es solo una opción lógica, si tiene varios hermanos que necesitan el mismo DataContext , Establecer DataContext para su padre es la respuesta correcta. Siempre tiendo a configurar DataContext en el elemento Top-most posible y si alguno o dos elementos necesitan variaciones, agréguelos en consecuencia.

Si en MVVM, su VM se convierte en el DataContext casi siempre del elemento de Nivel superior de la Vista. todo lo demás se une directamente al elemento cuya propiedad necesitan bastante.