DataBinding en WPF 2/2

En el anterior post vimos que teníamos que hacer para realizar sincronización de los datos con la interfaz de usuario sin Databinding, en este vamos a ver el DataBinding

Consiste en registrar un par de propiedades, una de ellas en un objeto (Person.Name), la otra en la interfaz grafica (Textbox.Text), con el motor de Data Binding
Este motor es el que se encarga de mantener ambas sincronizadas, convirtiendo los tipos de datos según sea necesario

 

image

Para registrar ambas propiedades (tanto del elemento, que seria la clase persona como del objeto que seria el Textbox), utilizamos el objeto Binding

Todas las siguientes son equivalentes…

 

<TextBox ...>
   <TextBox.Text>
      <Binding Path="Age" />
   </TextBox.Text>
</TextBox>
<TextBox Text="{Binding Path=Age}" />
<TextBox Text="{Binding Age}" />

es equivalente a…

image

En general, podemos pensar que Path es la ruta para acceder a una propiedad dentro del objeto fuente de la información. En el caso anterior, el binding se da entre el
TextBox (propiedad Text) y la propiedad Age de un objeto que será determinado luego.

En el caso anterior, el textbox actúa como binding target , consumiendo los cambios binding source. El binding target puede ser cualquier elemento WPF, pero solo podemos hacer binding contra las dependency properties. El binding source puede ser cualquier propiedad de cualquier elemento WPF.En este caso, el binding source puede especificarse en runtime
Sin embargo, en general, el binding provendrá de un Data Context.

Un DataContext es el lugar en el que los bindings buscan por su data source si no se les ha dado ninguna instrucción especial. En WPF todo FrameworkElement y todo FrameworkContentElement tienen una propiedad DataContext, y recordamos el grafico del post donde veíamos que todos los controles derivan de FrameWorkElement

El DataContext es de tipo Object, por lo que podemos colocar cualquier cosa que deseemos.

Cuando se busca un objeto para utilizar como data source de un binding, se recorre el árbol de componentes en forma inversa, partiendo del componente en cuestión
Esto es bastante útil cuando queremos que dos componentes compartan el mismo data source

image

Esto funciona así…

  • El binding busca un DataContext en el propio TextBox
  • El binding busca un DataContext en la Grid
  • El binding busca un DataContext en el Window

 

Hacer que ambos textbox compartan el mismo objeto Person, es cuestión de colocarlo en el DataContext del Grid

// Window1.xaml.cs
using System;
using System.Windows;
using System.Windows.Controls;
namespace WithBinding {
   public partial class Window1 : Window {
      Person person = new Person("Tom", 11);
      public Window1( ) {
         InitializeComponent( );
         grid.DataContext = person;
         this.birthdayButton.Click += birthdayButton_Click;
      }
      void birthdayButton_Click(object sender, 
                                RoutedEventArgs e) {
         ++person.Age;
         MessageBox.Show(string.Format(
                  "Happy Birthday, {0}, age {1}!",
                   person.Name,
                   person.Age),
                   "Birthday");
      }
   }
}

Entonces, si bien la funcionalidad es la misma, el código de sincronización se ha reducido enormemente y sobre todo es mas escalable sin mucho impacto en el código

El DataBinding tiene diferentes direcciones de enlace

Dirección del Databind

  • OneWay: de origen a destino y cuando el origen cambie
  • TwoWat: en ambos sentidos y con notificaciones de cambio
  • OneWayToSource: es igual que OneWay pero al reves, de destino a origen
  • OneTime: enlace a datos igual que OneWay pero únicamente una vez.

Debemos de tener en cuenta que todas las clases que hagamos Binding deben de ser a DependencyProperties o Propiedad, si son a estas ultimas las clases deben de implementar el interfaz INotifyPropertyChanged para notificar los cambios de la clase al Interfaz de Usuario, sino cambiaríamos el valor  y no se reflejaría en el control enlazado.

Recordar que en el DataBinding no solo lo podemos hacer de clases de negocio a objetos de interfaz de usuario, sino también entre los propios objetos de interfaz de usuario, esto da un gran poder en los diseños de interfaz de usuario.

Por ejemplo:

<Slider Name="Slider1" />
<TextBox Name="TextBox1" Text="{Binding ElementName=Slider1, Path=Value}" />

En este código cada vez que movamos el slider, se mostrar el valor en el TextBox

Cuando se hace el Databinding existe atributos opcionales para añadir a las expresiones de Binding

 

  • Source – usado en lugar  ElementName para referirse al objeto
  • RelativeSource –usado en lugar ElementName para referirse al elemento actual. con los valores Self, FindAncestor, y PreviousData.
  • Mode – OneTime|OneWay|TwoWay|OneWayToSource – para indicar la dirección y frecuencia del binding
  • Converter – para especificar una particular conversión de los datos a la interfaz de usuario
  • ConverterParameter – para pasar un parámetro adicional al converter
  • UpdateSourceTrigger – LostFocus|PropertyChanged|Explicit – para indicar cuando modificar la propiedad destino
  • FallbackValue – para indicar un valor por defecto cuando el binding falla

Un comentario sobre “DataBinding en WPF 2/2”

Deja un comentario

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