Enlace de datos

El modelo de enlace de datos

  • Objeto fuente (propiedad)
  • Objeto destino (propiedad)

Extensión {Binding}

  • Source. Indica cual es el objeto que deseamos utilizar como fuente de datos (cualquier objeto .NET). Si el objeto en cuestión está declarado en un diccionario de recursos necesitaríamos utilizar la extensión {StaticResource} para referenciarlo. P.e.: Source={StaticResource album1}
  • Path. Es la ruta para llegar al valor deseado, es la propiedad predeterminada por lo que podemos evitar poner de manera explícita. P.e.: {Binding Path=Nombre, … } o bien {Binding Nombre, …} o bien {Binding Path=Nombre.Length, …}
  • Mode. Indica el modo para el enlace de datos:
    • OneTime: Se establece el enlace pero fuente y destino no se vuelven a comunicar. Útil para utilizar en propiedades que no se van a cambiar.
    • OneWay: Se establece un enlace y cuando hay un cambio en la fuente el destino tendrá conocimiento de ese cambio. Es el modo predeterminado.
    • TwoWay: Similar al OneWay pero la comunicación se realiza en ambos sentidos.

Ejemplo:

<TextBox Text="{Binding Source={StaticResource persona1}, Path=Titulo, Mode=TwoWay}" />

Ahora declaramos el objeto tipo Persona en el diccionario de recursos del UserControl:

<UserControl.Resources>
  <local:Persona x:Key="personal"
    Nombre="Perico"
    Pais="Spain"
    Edad="33" />
</UserControl.Resources>

Ahora escribimos las expresiones de enlaces necesarias.

<TextBox Text="{Binding Source={StaticResource persona1}, Path=Nombre, Mode=OneTime}"/>
<TextBox Text="{Binding Source={StaticResource persona1}, Path=Pais, Mode=OneTime}"/>
<TextBox Text="{Binding Source={StaticResource persona1}, Path=Edad, Mode=OneTime}"/>

Contexto de datos

<Grid x:Name="LayoutRoot" Background="LightGray" DataContext="{Binding Source={StaticResource persona1}}}">
  <StackPanel Width="200" HorizontalAligment="Left" Margin="10">
    <TextBlock Text="Nombre:" />
    <TextBox Text="{Binding Path=Nombre, Mode=OneTime}"/>
    <TextBlock Text="País:" />
    <TextBox Text="{Binding Path=Pais, Mode=OneTime}"/>
    <TextBlock Text="Edad:" />
    <TextBox Text="{Binding Path=Edad, Mode=OneTime}"/>
  </StackPanel>
</Grid>

Cómo se puede observar hemos quitado la declaración explícita.

Incluso podríamos establecer el contexto de datos a nivel de UserControl.

Por otro lado también podríamos establecer un contexto de datos de manera dinámica.

this.Loaded += (s,a) => {
  LayoutRoot.DataContext = new persona() {
    Nombre = "Federico", Pais="Francia", Eddad=23 };
};


De forma más limpia el código XAML podría quedar así:

<Grid x:Name="LayoutRoot" Background="LightGray" DataContext="{Binding Source={StaticResource persona1}}}">
  <StackPanel Width="200" HorizontalAligment="Left" Margin="10">
    <TextBlock Text="Nombre:" />
    <TextBox Text="{Binding Nombre}"/>
    <TextBlock Text="País:" />
    <TextBox Text="{Binding Pais}"/>
    <TextBlock Text="Edad:" />
    <TextBox Text="{Binding Edad}"/>
    <Button Height="30" Content="Cambiar" margin="0 5" Click="Button_Click" />
  </StackPanel>
</Grid>

Código botón:

private void Button_Click(object sender, RoutedEventArgs e) {
  var persona1 = this.Resources["persona1"] as Persona;
  persona1.Nombre = "Juanjo";
  persona1.Pais = "Gata";
  persona1.Edad = 44;
}

 

Para los modos OneWay y TwoWay hay un requisito: el objeto fuente debe implementar alguna de las interfaces INotifyPropertyChanged o INotifyCollectionChanged para que el enlace funcione correctamente.

public class Persona : INotifyPropertyChanged {
  string nombre;
  public string Nombre {
    get {return nombre;} 
    set {nombre=value;
         OnPropertyChanged("Nombre");
        }
  }
  string pais;
  public string Pais {
    get {return pais;}
    set {pais = value;
         OnPropertyChanged("Pais");
        }
  int edad
  public int Edad {
    get {return edad;}
    set {edad = value;
         OnPropertyChanged("Edad");
        }
  public event PropertyChangedEventhandler PropertyChanged;
  private void OnPropertyChanged(string propertyName){
    if (PropertyChanged != null) {
      PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.