En Windows Presentation Foundation (WPF), los conceptos de DataContext y Binding son fundamentales para la gestión de datos en la interfaz de usuario. Un DataContext actúa como el origen de datos para un elemento de la interfaz de usuario y sus elementos hijos. El Binding, por otro lado, es el mecanismo que conecta una propiedad de un control de UI con una propiedad del DataContext.
Ejemplo Básico: Vinculando una Etiqueta al DataContext de la Ventana
Consideremos un escenario simple donde queremos mostrar un texto en una etiqueta (Label) utilizando un DataContext.
Primero, definimos la interfaz de usuario en XAML:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="300" Width="500">
<Grid>
<Label Content="{Binding etiquetaTexto}"/>
</Grid>
</Window>
En el código subyacente (C#), configuramos el DataContext:
using System.Windows;
namespace WpfApp1
{
public partial class MainWindow : Window
{
public string EtiquetaTexto { get; set; } = "Texto de ejemplo";
public MainWindow()
{
InitializeComponent();
// Establecemos el DataContext de la ventana a la propia instancia de la ventana.
// Esto significa que las vinculaciones en XAML buscarán propiedades directamente en esta clase.
DataContext = this;
}
}
}
Al ejecutar esta aplicación, la etiqueta mostrará "Texto de ejemplo". Aquí, DataContext = this; indica que la ventana misma es el origen de datos. La vinculación {Binding etiquetaTexto} busca una propiedad llamada etiquetaTexto en la instancia de MainWindow.
Usando una Clase Externa como DataContext
Es común y a menudo preferible extrenalizar la lógica de datos en clases separadas. Veamos cómo hacerlo.
Creamos una clase de modelo de datos:
namespace WpfApp1
{
public class ModeloDatos
{
public string EtiquetaTexto { get; set; } = "Texto desde ModeloDatos";
}
}
Luego, modificamos el constructor de la ventana para usar esta nueva clase como DataContext:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Ahora, el DataContext es una instancia de ModeloDatos.
DataContext = new ModeloDatos();
}
}
La interfaz de usuario (XAML) permanece igual. Al ejecutar, la etiqueta ahora mostrará "Texto desde ModeloDatos", demostrando que el DataContext puede ser cualquier objeto CLR.
Múltiples DataContexts dentro de la Misma Interfaz
Un elemento de UI puede tener su propio DataContext, que se propaga a sus elementos hijos. Esto permite tener múltiples orígenes de datos dentro de la misma ventana.
Modificamos el XAML para incluir dos Grids, cada uno con su propio DataContext y una etiqueta vinculada:
<Window x:Class="WpfApp1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp1"
Title="MainWindow" Height="300" Width="500">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Primer Grid con su propio DataContext -->
<Grid Grid.Row="0">
<Grid.DataContext>
<local:ModeloDatos/>
</Grid.DataContext>
<Label Content="{Binding EtiquetaTexto}"/>
</Grid>
<!-- Segundo Grid con su propio DataContext -->
<Grid Grid.Row="1">
<Grid.DataContext>
<local:ClaseB/>
</Grid.DataContext>
<Label Content="{Binding OtraEtiqueta}"/>
</Grid>
</Grid>
</Window>
Para que esto funcione, necesitaríamos definir la clase ClaseB y asegurarnos de que tenga una propiedad llamada OtraEtiqueta.
namespace WpfApp1
{
public class ClaseB
{
public string OtraEtiqueta { get; set; } = "Texto desde ClaseB";
}
}
Con esta configuración, la primera etiqueta mostrará "Texto desde ModeloDatos" y la segunda etiqueta mostrará "Texto desde ClaseB". Cada Grid define su propio DataContext, que es utilizado por los controles dentro de él.