Información general sobre declaraciones de enlaces (WPF .NET)

Normalmente, los desarrolladores declaran los enlaces directamente en el marcado XAML de los elementos de la interfaz de usuario a los que desean enlazar datos. Sin embargo, también puede declarar enlaces en el código. En este artículo se describe cómo declarar enlaces tanto en XAML como en código.

Requisitos previos

Antes de leer este tema, es importante que esté familiarizado con el concepto y el uso de las extensiones de marcado. Para más información sobre las extensiones de marcado, consulte Extensiones de marcado y XAML de WPF.

En este artículo no se tratan los conceptos de enlace de datos. Para obtener una explicación de los conceptos de enlace de datos, consulte Información general sobre el enlace de datos.

Declaración de un enlace en XAML

Binding es una extensión de marcado. Cuando se utiliza la extensión de enlace para declarar un enlace, la declaración consta de una serie de cláusulas después de la palabra clave Binding y separadas por comas (,). Las cláusulas de la declaración de enlace pueden estar en cualquier orden y hay muchas combinaciones posibles. Las cláusulas son pares de Nombre=Valor donde Nombre es el nombre de la propiedad Binding y Valor es el valor que se establece para la propiedad.

Al crear cadenas de declaración de enlace en el marcado, se adjuntará a la propiedad de dependencia concreta de un objeto de destino. En el ejemplo siguiente se muestra cómo enlazar la propiedad TextBox.Text mediante la extensión de enlace, especificando las propiedades Source y Path.

<TextBlock Text="{Binding Source={StaticResource myDataSource}, Path=Name}"/>

Puede especificar la mayoría de las propiedades de la clase Binding de esta manera. Para más información acerca de la extensión de enlace, así como una lista de propiedades Binding que no se pueden establecer mediante la extensión de enlace, consulte la introducción general a la Extensión de marcado de enlace (.NET Framework).

Sintaxis de elemento de objeto

La sintaxis de elemento de objeto es una alternativa a la creación de la declaración de enlace. En la mayoría de los casos no hay ninguna ventaja particular para usar la extensión de marcado o la sintaxis de elemento de objeto. Sin embargo, en aquellos casos en los que la extensión de marcado no admite el escenario, como cuando el valor de la propiedad es de un tipo que no es una cadena para el que no existe conversión de tipo, debe utilizar la sintaxis de elemento de objeto.

En la sección anterior se ha mostrado cómo enlazar con una extensión XAML. En el ejemplo siguiente se muestra cómo realizar el mismo enlace, pero se usa la sintaxis del elemento de objeto:

<TextBlock>
    <TextBlock.Text>
        <Binding Source="{StaticResource myDataSource}" Path="Name"/>
    </TextBlock.Text>
</TextBlock>

Para más información sobre los distintos términos, consulte Detalles de la sintaxis XAML (.NET Framework).

MultiBinding y PriorityBinding

MultiBinding y PriorityBinding no admiten la sintaxis de la extensión XAML. Por eso debe usar la sintaxis del elemento de objeto si declara un MultiBinding o un PriorityBinding en XAML.

Creación de un enlace en el código

Otra manera de especificar un enlace es establecer propiedades directamente en un objeto Binding en el código y, a continuación, asignar el enlace a una propiedad. En el siguiente ejemplo de código se muestra cómo crear un objeto Binding en el código.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // Make a new data source object
    var personDetails = new Person()
    {
        Name = "John",
        Birthdate = DateTime.Parse("2001-02-03")
    };

    // New binding object using the path of 'Name' for whatever source object is used
    var nameBindingObject = new Binding("Name");

    // Configure the binding
    nameBindingObject.Mode = BindingMode.OneWay;
    nameBindingObject.Source = personDetails;
    nameBindingObject.Converter = NameConverter.Instance;
    nameBindingObject.ConverterCulture = new CultureInfo("en-US");

    // Set the binding to a target object. The TextBlock.Name property on the NameBlock UI element
    BindingOperations.SetBinding(NameBlock, TextBlock.TextProperty, nameBindingObject);
}
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)

    ' Make a new data source object
    Dim personDetails As New Person() With {
        .Name = "John",
        .Birthdate = Date.Parse("2001-02-03")
    }

    ' New binding object using the path of 'Name' for whatever source object is used
    Dim nameBindingObject As New Binding("Name")

    ' Configure the binding
    nameBindingObject.Mode = BindingMode.OneWay
    nameBindingObject.Source = personDetails
    nameBindingObject.Converter = NameConverter.Instance
    nameBindingObject.ConverterCulture = New CultureInfo("en-US")

    ' Set the binding to a target object. The TextBlock.Name property on the NameBlock UI element
    BindingOperations.SetBinding(NameBlock, TextBlock.TextProperty, nameBindingObject)

End Sub

El código anterior establece lo siguiente en el enlace:

  • Ruta de acceso de la propiedad en el objeto de origen de datos.
  • Modo del enlace.
  • Origen de datos, en este caso, una instancia de objeto simple que representa a una persona.
  • Convertidor opcional que procesa el valor procedente del objeto de origen de datos antes de asignarlo a la propiedad de destino.

Cuando el objeto que está enlazando es un FrameworkElement o un FrameworkContentElement, puede llamar al método SetBinding en el objeto directamente en lugar de usar BindingOperations.SetBinding. Para obtener un ejemplo, consulte Cómo: Crear un enlace mediante código.

En el ejemplo anterior se usa un tipo de objeto de datos simple de Person. A continuación se muestra el código de ese objeto:

class Person
{
    public string Name { get; set; }
    public DateTime Birthdate { get; set; }
}
Public Class Person

    Public Property Name As String
    Public Property Birthdate As DateTime
    
End Class

Sintaxis de la ruta de enlace

Use la propiedad Path para especificar el valor de origen al que desea enlazar:

  • En el caso más simple, el valor de la propiedad Path es el nombre de la propiedad del objeto de origen que se utilizará para el enlace, como Path=PropertyName.

  • Se pueden especificar subpropiedades de una propiedad mediante una sintaxis similar a la de C#. Por ejemplo, la cláusula Path=ShoppingCart.Order define el enlace a la subpropiedad Order del objeto o la propiedad ShoppingCart.

  • Para enlazar a una propiedad adjunta, coloque paréntesis alrededor de esta propiedad. Por ejemplo, para enlazar a la propiedad adjunta DockPanel.Dock, la sintaxis es Path=(DockPanel.Dock).

  • Los indizadores de una propiedad pueden especificarse entre corchetes después del nombre de la propiedad donde se aplica el indizador. Por ejemplo, la cláusula Path=ShoppingCart[0] establece el enlace al índice que se corresponde a cómo la indización interna de la propiedad administra la cadena literal "0". También se admiten indizadores anidados.

  • Los indizadores y las subpropiedades se pueden combinar en una cláusula Path; por ejemplo, Path=ShoppingCart.ShippingInfo[MailingAddress,Street]..

  • Dentro de los indexadores. Puede tener varios parámetros de indexador separados por comas (,). El tipo de cada parámetro se puede especificar entre paréntesis. Por ejemplo, puede tener Path="[(sys:Int32)42,(sys:Int32)24]", donde sys se asigna al espacio de nombres System.

  • Cuando el origen es una vista de colección, el elemento actual se puede especificar con una barra diagonal (/). Por ejemplo, la cláusula Path=/ establece el enlace al elemento actual de la vista. Cuando el origen es una colección, esta sintaxis especifica el elemento actual de la vista de colección predeterminada.

  • Los nombres de propiedad y las barras diagonales se pueden combinar para recorrer las propiedades que son colecciones. Por ejemplo, Path=/Offices/ManagerName especifica el elemento actual de la colección de origen, que contiene una propiedad Offices que también es una colección. Su elemento actual es un objeto que contiene una propiedad ManagerName.

  • Opcionalmente se puede usar una ruta de acceso de punto (.) para enlazar con el origen actual. Por ejemplo, Text="{Binding}" es equivalente a Text="{Binding Path=.}".

Mecanismo de escape

  • Dentro de los indizadores ([ ]), el carácter de intercalación (^) realiza el escape del carácter siguiente.

  • Si establece Path en XAML, también necesita realizar el escape (mediante entidades XML) de ciertos caracteres que son especiales para la definición del lenguaje XML:

    • Use &amp; para realizar el escape del carácter &.

    • Use &gt; para realizar el escape de la etiqueta final >.

  • Además, si describe el enlace completo en un atributo mediante la sintaxis de extensión de marcado, deberá realizar el escape (con la barra diagonal inversa \) de los caracteres que son especiales para el analizador de extensión de marcado de WPF:

    • La barra diagonal inversa (\) es el mismo carácter de escape.

    • El signo igual (=) separa el nombre de propiedad del valor de propiedad.

    • La coma (,) separa las propiedades.

    • La llave de cierre (}) es el final de una extensión de marcado.

Dirección de los enlaces

Use la propiedad Binding.Mode para especificar la dirección del enlace. Los modos siguientes son las opciones disponibles para enlazar actualizaciones:

Modo de enlace Descripción
BindingMode.TwoWay Actualiza la propiedad de destino o la propiedad cuando cambia la propiedad de destino o la propiedad de origen.
BindingMode.OneWay Actualiza la propiedad de destino solo cuando cambia la propiedad de origen.
BindingMode.OneTime Actualiza la propiedad de destino solo cuando se inicia la aplicación o cuando el DataContext se somete a un cambio.
BindingMode.OneWayToSource Actualiza la propiedad de origen cuando cambia la propiedad de destino.
BindingMode.Default Hace que se use el valor predeterminado Mode de la propiedad de destino.

Para obtener más información, vea la enumeración BindingMode.

En el ejemplo siguiente se muestra cómo establecer la propiedad Mode:

<TextBlock Name="IncomeText" Text="{Binding Path=TotalIncome, Mode=OneTime}" />

Para detectar cambios en el origen (aplicables a los enlaces OneWay y TwoWay), el origen debe implementar un mecanismo de notificación de cambio de propiedad adecuado, como INotifyPropertyChanged. Para obtener más información, consulte Proporcionar notificaciones de cambio.

Para los enlaces TwoWay o OneWayToSource, puede controlar el tiempo de las actualizaciones de origen estableciendo la propiedad UpdateSourceTrigger. Para obtener más información, vea UpdateSourceTrigger.

Comportamientos predeterminados

El comportamiento predeterminado es el siguiente si no se especifica en la declaración:

  • Se crea un convertidor predeterminado que intenta realizar una conversión de tipos entre el valor de origen de enlace y el valor de destino del enlace. Si no se puede realizar una conversión, el convertidor predeterminado devuelve null.

  • Si no establece ConverterCulture, el motor de enlace usa la propiedad Language del objeto de destino de enlace. En XAML tiene como valor predeterminado en-US o hereda el valor de elemento raíz (o cualquier elemento) de la página, si se ha establecido explícitamente.

  • Siempre que el enlace ya tenga un contexto de datos (por ejemplo, el contexto de datos heredado procedente de un elemento primario) y con independencia de que el elemento o la colección que se devuelva en ese contexto sea apropiado para el enlace sin necesitar una modificación adicional de la ruta, una declaración de enlace no puede tener ninguna cláusula: {Binding}. Esta suele ser la forma en que se especifica un enlace para el estilo de datos, donde el enlace actúa sobre una colección. Para obtener más información, consulte Usar objetos completos como origen de enlace.

  • El valor predeterminado Mode varía entre unidireccional y bidireccional, según la propiedad de dependencia que se va a enlazar. Siempre puede declarar explícitamente el modo de enlace para asegurarse de que el enlace tiene el comportamiento deseado. En general, las propiedades de control que puede modificar el usuario, como TextBox.Text y RangeBase.Value, tienen como valor predeterminado de enlaces bidireccionales, pero la mayoría de las demás propiedades tienen como valor predeterminado enlaces unidireccionales.

  • El valor predeterminado UpdateSourceTrigger también varía entre PropertyChanged y LostFocus en función de la propiedad de dependencia enlazada. El valor predeterminado de la mayoría de las propiedades de dependencia es PropertyChanged, mientras que la propiedad TextBox.Text tiene un valor predeterminado de LostFocus.

Vea también