Enlace de datos en profundidadData binding in depth

API importantesImportant APIs

Nota

En este tema se describen detalladamente las características del enlace de datos.This topic describes data binding features in detail. Para obtener una introducción breve y práctica, consulta Introducción al enlace de datos.For a short, practical introduction, see Data binding overview.

En este tema se describe el enlace de datos en las aplicaciones para la Plataforma universal de Windows (UWP).This topic is about data binding in Universal Windows Platform (UWP) applications. Las API que se describen aquí residen en el espacio de nombres Windows.UI.Xaml.Data.The APIs discussed here reside in the Windows.UI.Xaml.Data namespace.

El enlace de datos es una forma para que la interfaz de usuario de la aplicación muestre los datos y, opcionalmente, se mantenga sincronizada con dichos datos.Data binding is a way for your app's UI to display data, and optionally to stay in sync with that data. El enlace de datos permite separar lo que concierne a los datos de lo que concierne a la interfaz de usuario, lo que da como resultado un modelo conceptual más sencillo y una mejor legibilidad, comprobación y mantenimiento de la aplicación.Data binding allows you to separate the concern of data from the concern of UI, and that results in a simpler conceptual model as well as better readability, testability, and maintainability of your app.

Puedes usar el enlace de datos para simplemente mostrar los valores de un origen de datos aparece en primer lugar la interfaz de usuario, pero no para responder a cambios en dichos valores.You can use data binding to simply display values from a data source when the UI is first shown, but not to respond to changes in those values. Este es un modo de enlace denominado único y funciona bien para un valor que no cambia en tiempo de ejecución.This is a mode of binding called one-time, and it works well for a value that doesn't change during run-time. También puedes elegir "observar" los valores y actualizar la interfaz de usuario cuando cambien.Alternatively, you can choose to "observe" the values and to update the UI when they change. Este modo se denomina enlace unidireccional y funciona bien para datos de solo lectura.This mode is called one-way, and it works well for read-only data. En última instancia, puedes elegir observar y actualizar para que los cambios que realiza el usuario a los valores de la interfaz de usuario se envíen automáticamente al origen de datos.Ultimately, you can choose to both observe and update, so that changes that the user makes to values in the UI are automatically pushed back into the data source. Este modo se denomina enlace bidireccional y funciona bien para datos de lectura y escritura.This mode is called two-way, and it works well for read-write data. A continuación se muestran algunos ejemplos.Here are some examples.

  • Puedes usar el modo único para enlazar un elemento Image con la foto del usuario actual.You could use the one-time mode to bind an Image to the current user's photo.
  • Puedes usar el modo unidireccional para enlazar un elemento ListView con una colección de artículos de noticias en tiempo real agrupados por sección de periódico.You could use the one-way mode to bind a ListView to a collection of real-time news articles grouped by newspaper section.
  • Puedes usar el modo bidireccional para enlazar un elemento TextBox con el nombre de un cliente en un formulario.You could use the two-way mode to bind a TextBox to a customer's name in a form.

Independientemente del modo, existen dos tipos de enlaces y, generalmente, ambos se declaran en el marcado de interfaz de usuario.Independent of mode, there are two kinds of binding, and they're both typically declared in UI markup. Puedes usar la extensión de marcado {x:Bind} o extensión de marcado {Binding}.You can choose to use either the {x:Bind} markup extension or the {Binding} markup extension. Incluso puedes usar una combinación de ambos en la misma aplicación, aun en el mismo elemento de la interfaz de usuario.And you can even use a mixture of the two in the same app—even on the same UI element. {x:Bind} es nuevo en Windows 10 y tiene un mejor rendimiento.{x:Bind} is new for Windows 10 and it has better performance. Todos los detalles que se describen en este tema se aplican a ambos tipos de enlace, a menos que especifiquemos explícitamente lo contrario.All the details described in this topic apply to both kinds of binding unless we explicitly say otherwise.

Aplicaciones de ejemplo que muestran {x:Bind}Sample apps that demonstrate {x:Bind}

Aplicaciones de ejemplo que muestran {Binding}Sample apps that demonstrate {Binding}

Cada enlace implica estas piezasEvery binding involves these pieces

  • Un origen de enlace.A binding source. Este es el origen de los datos para el enlace y puede ser una instancia de cualquier clase que tenga miembros cuyos valores que quieres mostrar en la interfaz de usuario.This is the source of the data for the binding, and it can be an instance of any class that has members whose values you want to display in your UI.
  • Un destino de enlace.A binding target. Se trata de una DependencyProperty del FrameworkElement en la interfaz de usuario que muestra los datos.This is a DependencyProperty of the FrameworkElement in your UI that displays the data.
  • Un objeto de enlace.A binding object. Este es el fragmento que transfiere los valores de datos del origen al destino y, opcionalmente, del destino nuevamente al origen.This is the piece that transfers data values from the source to the target, and optionally from the target back to the source. Se crea el objeto de enlace en tiempo de carga de XAML desde tu {x:Bind} o la extensión de marcado {Binding}.The binding object is created at XAML load time from your {x:Bind} or {Binding} markup extension.

En las siguientes secciones, se echaremos un vistazo al origen de enlace, el destino de enlace y el objeto de enlace.In the following sections, we'll take a closer look at the binding source, the binding target, and the binding object. Además, vincularemos las secciones junto con el ejemplo de enlace de contenido de un botón a una propiedad de cadena denominada NextButtonText, que pertenece a una clase denominada HostViewModel.And we'll link the sections together with the example of binding a button's content to a string property named NextButtonText, which belongs to a class named HostViewModel.

Origen de enlaceBinding source

Esta es una implementación muy rudimentaria de una clase que podríamos usar como origen de enlace.Here's a very rudimentary implementation of a class that we could use as a binding source.

Si usas C++/WinRT, agrega nuevos elementos de archivo MIDL (.idl) al proyecto, con el nombre que se muestra en la lista del ejemplo de código C++/WinRT siguiente.If you're using C++/WinRT, then add new Midl File (.idl) items to the project, named as shown in the C++/WinRT code example listing below. Reemplaza el contenido de los archivos nuevos con el código MIDL 3.0 que se muestra en la lista, compila el proyecto para generar HostViewModel.h y .cpp y, a continuación, agrega el código a los archivos generados para que coincidan con la lista.Replace the contents of those new files with the MIDL 3.0 code shown in the listing, build the project to generate HostViewModel.h and .cpp, and then add code to the generated files to match the listing. Para obtener más información sobre esos archivos generados y cómo copiarlos en el proyecto, consulta Controles de XAML; enlazar a una propiedad de C++/WinRT.For more info about those generated files and how to copy them into your project, see XAML controls; bind to a C++/WinRT property.

public class HostViewModel
{
    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText { get; set; }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Implement the constructor like this, and add this field:
...
HostViewModel() : m_nextButtonText{ L"Next" } {}
...
private:
    std::wstring m_nextButtonText;
...

// HostViewModel.cpp
// Implement like this:
...
hstring HostViewModel::NextButtonText()
{
    return hstring{ m_nextButtonText };
}

void HostViewModel::NextButtonText(hstring const& value)
{
    m_nextButtonText = value;
}
...

La implementación de HostViewModel y su propiedad NextButtonText solo es apropiada para el enlace único.That implementation of HostViewModel, and its property NextButtonText, are only appropriate for one-time binding. Sin embargo, los enlace unidireccionales y bidireccionales son muy comunes y, en dichos tipos de enlaces, la interfaz de usuario se actualiza automáticamente en respuesta a cambios en los valores de datos del origen del enlace.But one-way and two-way bindings are extremely common, and in those kinds of binding the UI automatically updates in response to changes in the data values of the binding source. Para que esos tipos de enlace funcionen correctamente, debes colocar al origen de enlace como "observable" en el objeto de enlace.In order for those kinds of binding to work correctly, you need to make your binding source "observable" to the binding object. Así, en nuestro ejemplo, si queremos un enlace unidireccional o bidireccional con la propiedad NextButtonText y, a continuación, cualquier cambio que se produzca en tiempo de ejecución en el valor de esa propiedad debe hacerse observable para el objeto de enlace.So in our example, if we want to one-way or two-way bind to the NextButtonText property, then any changes that happen at run-time to the value of that property need to be made observable to the binding object.

Una manera de hacerlo es derivar la clase que representa el origen de enlace de DependencyObject y exponer un valor de datos a través de una DependencyProperty.One way of doing that is to derive the class that represents your binding source from DependencyObject, and expose a data value through a DependencyProperty. De este modo, un FrameworkElement pasa a ser observable.That's how a FrameworkElement becomes observable. FrameworkElements son orígenes de enlace correctos sin necesidad de personalizarlos.FrameworkElements are good binding sources right out of the box.

Una manera más ligera de hacer que una clase sea observable, y necesaria para las clases que ya tienen una clase base, es implementar System.ComponentModel.INotifyPropertyChanged.A more lightweight way of making a class observable—and a necessary one for classes that already have a base class—is to implement System.ComponentModel.INotifyPropertyChanged. Esto simplemente implica la implementación de un solo evento denominado PropertyChanged.This really just involves implementing a single event named PropertyChanged. A continuación te mostramos un ejemplo usando HostViewModel.An example using HostViewModel is below.

...
using System.ComponentModel;
using System.Runtime.CompilerServices;
...
public class HostViewModel : INotifyPropertyChanged
{
    private string nextButtonText;

    public event PropertyChangedEventHandler PropertyChanged = delegate { };

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set
        {
            this.nextButtonText = value;
            this.OnPropertyChanged();
        }
    }

    public void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        // Raise the PropertyChanged event, passing the name of the property whose value has changed.
        this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}
// HostViewModel.idl
namespace DataBindingInDepth
{
    runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        HostViewModel();
        String NextButtonText;
    }
}

// HostViewModel.h
// Add this field:
...
    winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler);
    void PropertyChanged(winrt::event_token const& token) noexcept;

private:
    winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
...

// HostViewModel.cpp
// Implement like this:
...
void HostViewModel::NextButtonText(hstring const& value)
{
    if (m_nextButtonText != value)
    {
        m_nextButtonText = value;
        m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"NextButtonText" });
    }
}

winrt::event_token HostViewModel::PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& handler)
{
    return m_propertyChanged.add(handler);
}

void HostViewModel::PropertyChanged(winrt::event_token const& token) noexcept
{
    m_propertyChanged.remove(token);
}
...

Ahora la propiedad NextButtonText es observable.Now the NextButtonText property is observable. Cuando creas una enlace unidireccional o bidireccional con esa propiedad (te mostraremos cómo más adelante), el objeto de enlace resultante se suscribe al evento PropertyChanged.When you author a one-way or a two-way binding to that property (we'll show how later), the resulting binding object subscribes to the PropertyChanged event. Cuando se genera el evento, controlador del objeto de enlace recibe un argumento que contiene el nombre de la propiedad que ha cambiado.When that event is raised, the binding object's handler receives an argument containing the name of the property that has changed. Así es cómo el objeto de enlace sabe a qué valor de propiedad dirigirse y volver a leer.That's how the binding object knows which property's value to go and read again.

Para que no tengas que implementar el patrón mostrado anteriormente varias veces, si usas C#, puedes derivar de la clase base BindableBase que encontrarás en el ejemplo de QuizGame (en la carpeta "Common").So that you don't have to implement the pattern shown above multiple times, if you're using C# then you can just derive from the BindableBase base class that you'll find in the QuizGame sample (in the "Common" folder). Este es un ejemplo de cómo queda.Here's an example of how that looks.

public class HostViewModel : BindableBase
{
    private string nextButtonText;

    public HostViewModel()
    {
        this.NextButtonText = "Next";
    }

    public string NextButtonText
    {
        get { return this.nextButtonText; }
        set { this.SetProperty(ref this.nextButtonText, value); }
    }
}
// Your BindableBase base class should itself derive from Windows::UI::Xaml::DependencyObject. Then, in HostViewModel.idl, derive from BindableBase instead of implementing INotifyPropertyChanged.

Nota

Para C++/WinRT, cualquier clase en tiempo de ejecución que declares en la aplicación que derive de una clase base se conoce como una clase que admite composición.For C++/WinRT, any runtime class that you declare in your application that derives from a base class is known as a composable class. Las clases que admiten composición tienen restricciones.And there are constraints around composable classes. Para que una aplicación pase las pruebas del kit de certificación de aplicaciones en Windows que Visual Studio y Microsoft Store utilizan para validar los envíos (y para que la aplicación se incorpore correctamente a Microsoft Store), una clase que admite composición debe derivar en última instancia de una clase base de Windows.For an application to pass the Windows App Certification Kit tests used by Visual Studio and by the Microsoft Store to validate submissions (and therefore for the application to be successfully ingested into the Microsoft Store), a composable class must ultimately derive from a Windows base class. Eso significa que, en la raíz misma de la jerarquía de herencia, la clase debe ser un tipo que se origina en un espacio de nombres Windows.*.Meaning that the class at the very root of the inheritance hierarchy must be a type originating in a Windows.* namespace. Si necesitas derivar una clase en tiempo de ejecución de una clase base, por ejemplo para implementar una clase BindableBase para todos los modelos de vista de los que puedes derivar, puedes derivar de Windows.UI.Xaml.DependencyObject.If you do need to derive a runtime class from a base class—for example, to implement a BindableBase class for all of your view models to derive from—then you can derive from Windows.UI.Xaml.DependencyObject.

Generar el evento PropertyChanged con un argumento de String.Empty o null indica que se deben volver a leer todas las propiedades no indexadoras del objeto.Raising the PropertyChanged event with an argument of String.Empty or null indicates that all non-indexer properties on the object should be re-read. Puedes generar el evento para indica que las propiedades de indizador del objeto han cambiado mediante un argumento de "Item[indexer]" para indexadores específicos (donde indexer es el valor de índice) o el valor de "Item[]" para todos los indexadores.You can raise the event to indicate that indexer properties on the object have changed by using an argument of "Item[indexer]" for specific indexers (where indexer is the index value), or a value of "Item[]" for all indexers.

Un objeto de enlace puede tratarse como un solo objeto cuyas propiedades contienen datos, o bien, como una colección de objetos.A binding source can be treated either as a single object whose properties contain data, or as a collection of objects. En el código de C# y Visual Basic, puedes enlazar por única vez a un objeto que implementa List(Of T) para mostrar una colección que no cambia en tiempo de ejecución.In C# and Visual Basic code, you can one-time bind to an object that implements List(Of T) to display a collection that doesn't change at run-time. Para una colección observable (observar cuando se agregan o quitan los elementos de la colección), se realiza un enlace unidireccional a ObservableCollection(Of T) en su lugar.For an observable collection (observing when items are added to and removed from the collection), one-way bind to ObservableCollection(Of T) instead. En el código de C++/CX, puedes enlazar con Vector<T> para las colecciones observables y no observables, y C++/WinRT tiene sus propios tipos.In C++/CX code, you can bind to Vector<T> for both observable and non-observable collections, and C++/WinRT has its own types. Para enlazar tus propias clases de colecciones, usa las directrices de la siguiente tabla.To bind to your own collection classes, use the guidance in the following table.

EscenarioScenario C# y VB (CLR)C# and VB (CLR) C++/WinRTC++/WinRT C++/CXC++/CX
Enlazar a un objeto.Bind to an object. Puede ser cualquier objeto.Can be any object. Puede ser cualquier objeto.Can be any object. El objeto debe tener el atributo BindableAttribute o implementa ICustomPropertyProvider.Object must have BindableAttribute or implement ICustomPropertyProvider.
Obtener notificaciones de cambio de propiedades de un objeto enlazado.Get property change notifications from a bound object. El objeto debe implementar INotifyPropertyChanged.Object must implement INotifyPropertyChanged. El objeto debe implementar INotifyPropertyChanged.Object must implement INotifyPropertyChanged. El objeto debe implementar INotifyPropertyChanged.Object must implement INotifyPropertyChanged.
Enlazar a una colección.Bind to a collection. List(Of T) List(Of T) IVector de IInspectable o IBindableObservableVector.IVector of IInspectable, or IBindableObservableVector. Consulta Controles de elementos de XAML; enlazar a una colección C++/WinRT y Colecciones con C++/WinRT.See XAML items controls; bind to a C++/WinRT collection and Collections with C++/WinRT. Vector<T> Vector<T>
Obtener notificaciones de cambios de colecciones de una colección enlazada.Get collection change notifications from a bound collection. ObservableCollection(Of T) ObservableCollection(Of T) IObservableVector de IInspectable.IObservableVector of IInspectable. Por ejemplo, winrt::single_threaded_observable_vector<T> .For example, winrt::single_threaded_observable_vector<T>. IObservableVector<T> .IObservableVector<T>. Vector<T> implementa esta interfaz.Vector<T> implements this interface.
Implementar una colección compatible con enlaces.Implement a collection that supports binding. Extiende List(Of T) o implementa IList, IList(Of Object), IEnumerable o IEnumerable(Of Object).Extend List(Of T) or implement IList, IList(Of Object), IEnumerable, or IEnumerable(Of Object). No se admite el enlace a IList(Of T) e IEnumerable(Of T) genéricos.Binding to generic IList(Of T) and IEnumerable(Of T) is not supported. Implementa IVector de IInspectable.Implement IVector of IInspectable. Consulta Controles de elementos de XAML; enlazar a una colección C++/WinRT y Colecciones con C++/WinRT.See XAML items controls; bind to a C++/WinRT collection and Collections with C++/WinRT. Implementa IBindableVector, IBindableIterable, IVector<Object^>, IIterable<Object^>, IVector<IInspectable*> o IIterable<IInspectable*>.Implement IBindableVector, IBindableIterable, IVector<Object^>, IIterable<Object^>, IVector<IInspectable*>, or IIterable<IInspectable*>. No se admite el enlace a IVector<T> e IIterable<T> genéricos.Binding to generic IVector<T> and IIterable<T> is not supported.
Implementar una colección que admita notificaciones de cambios de colecciones.Implement a collection that supports collection change notifications. Extiende ObservableCollection(Of T) o implementa IList e INotifyCollectionChanged (no genéricos).Extend ObservableCollection(Of T) or implement (non-generic) IList and INotifyCollectionChanged. Implementa IObservableVector de IInspectable o IBindableObservableVector.Implement IObservableVector of IInspectable, or IBindableObservableVector. Implementa IBindableVector e IBindableObservableVector.Implement IBindableVector and IBindableObservableVector.
Implementar una colección compatible con la carga incremental.Implement a collection that supports incremental loading. Extiende ObservableCollection(Of T) o implementa IList e INotifyCollectionChanged (no genéricos).Extend ObservableCollection(Of T) or implement (non-generic) IList and INotifyCollectionChanged. Además, implementa ISupportIncrementalLoading.Additionally, implement ISupportIncrementalLoading. Implementa IObservableVector de IInspectable o IBindableObservableVector.Implement IObservableVector of IInspectable, or IBindableObservableVector. Además, implementa ISupportIncrementalLoading.Additionally, implement ISupportIncrementalLoading Implementa IBindableVector, IBindableObservableVector e ISupportIncrementalLoading.Implement IBindableVector, IBindableObservableVector, and ISupportIncrementalLoading.

Con la carga incremental, puedes enlazar controles de lista a orígenes de datos que son arbitrariamente de gran tamaño y aun así lograr un alto rendimiento.You can bind list controls to arbitrarily large data sources, and still achieve high performance, by using incremental loading. Por ejemplo, puedes enlazar controles de lista a resultados de consulta de imágenes de Bing sin tener que cargarlos a todos de una vez.For example, you can bind list controls to Bing image query results without having to load all the results at once. Solo cargas algunos resultados inmediatamente y después cargas otros, según sea necesario.Instead, you load only some results immediately, and load additional results as needed. Para admitir la carga incremental, debes implementar ISupportIncrementalLoading en un origen de datos compatible con las notificaciones de cambios de colección.To support incremental loading, you must implement ISupportIncrementalLoading on a data source that supports collection change notifications. Cuando el motor de enlace de datos solicite más datos, tu origen de datos debe realizar las solicitudes apropiadas, integrar los resultados y después enviar las debidas notificaciones para actualizar la interfaz de usuario.When the data binding engine requests more data, your data source must make the appropriate requests, integrate the results, and then send the appropriate notifications in order to update the UI.

Destino de enlaceBinding target

En los dos ejemplos siguientes, la propiedad Button.Content es el destino de enlace y su valor se establece en una extensión de marcado que declara el objeto de enlace.In the two examples below, the Button.Content property is the binding target, and its value is set to a markup extension that declares the binding object. Se muestra el primer {x:Bind} y luego {Binding}.First {x:Bind} is shown, and then {Binding}. Declarar enlaces en el marcado es el caso común (es cómodo, legible y administrable).Declaring bindings in markup is the common case (it's convenient, readable, and toolable). Sin embargo, puedes evitar el marcado y de manera imperativa (mediante programación) crear una instancia de la clase Binding en su lugar, si necesitas.But you can avoid markup and imperatively (programmatically) create an instance of the Binding class instead if you need to.

<Button Content="{x:Bind ...}" ... />
<Button Content="{Binding ...}" ... />

Si usas extensiones de componentes de C++/WinRT o Visual C++ (C++/CX), deberás agregar el atributo BindableAttribute a cualquier clase en tiempo de ejecución con la que quieras usar la extensión de marcado {Binding}.If you're using C++/WinRT or Visual C++ component extensions (C++/CX), then you'll need to add the BindableAttribute attribute to any runtime class that you want to use the {Binding} markup extension with.

Importante

Si estás usando C++/WinRT, el atributo BindableAttribute está disponible si has instalado la versión de Windows SDK 10.0.17763.0 (Windows 10, versión 1809) o posterior.If you're using C++/WinRT, then the BindableAttribute attribute is available if you've installed the Windows SDK version 10.0.17763.0 (Windows 10, version 1809), or later. Sin ese atributo, tendrás que implementar las interfaces ICustomPropertyProvider y ICustomProperty para poder usar la extensión de marcado {Binding}.Without that attribute, you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces in order to be able to use the {Binding} markup extension.

Objeto de enlace que se declaran usando {x:Bind}Binding object declared using {x:Bind}

Hay un solo paso que necesitamos ejecutar antes de crear nuestro marcado {x:Bind}.There's one step we need to do before we author our {x:Bind} markup. Tenemos que exponer nuestra clase de origen de enlace desde la clase que representa nuestra página de marcado.We need to expose our binding source class from the class that represents our page of markup. Eso lo haremos agregando una propiedad (de tipo HostViewModel en este caso) a nuestra clase de página MainPage.We do that by adding a property (of type HostViewModel in this case) to our MainPage page class.

namespace DataBindingInDepth
{
    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();
            this.ViewModel = new HostViewModel();
        }
    
        public HostViewModel ViewModel { get; set; }
    }
}
// MainPage.idl
import "HostViewModel.idl";

namespace DataBindingInDepth
{
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        HostViewModel ViewModel{ get; };
    }
}

// MainPage.h
// Include a header, and add this field:
...
#include "HostViewModel.h"
...
    DataBindingInDepth::HostViewModel ViewModel();

private:
    DataBindingInDepth::HostViewModel m_viewModel{ nullptr };
...

// MainPage.cpp
// Implement like this:
...
MainPage::MainPage()
{
    InitializeComponent();

}

DataBindingInDepth::HostViewModel MainPage::ViewModel()
{
    return m_viewModel;
}
...

Una vez que hayas hecho esto, puedes analizar más minuciosamente el marcado que declara el objeto de enlace.That done, we can now take a closer look at the markup that declares the binding object. El siguiente ejemplo usa el mismo destino de enlace Button.Content que usamos en la sección "Destino de enlace" anteriormente, y muestra que está enlazado a la propiedad HostViewModel.NextButtonText.The example below uses the same Button.Content binding target we used in the "Binding target" section earlier, and shows it being bound to the HostViewModel.NextButtonText property.

<!-- MainPage.xaml -->
<Page x:Class="DataBindingInDepth.Mainpage" ... >
    <Button Content="{x:Bind Path=ViewModel.NextButtonText, Mode=OneWay}" ... />
</Page>

Observa el valor que especificamos para Path.Notice the value that we specify for Path. Este valor se interpreta en el contexto de la página en sí y, en este caso, la ruta comienza haciendo referencia a la propiedad ViewModel que acabamos de agregar a la página MainPage.This value is interpreted in the context of the page itself, and in this case the path begins by referencing the ViewModel property that we just added to the MainPage page. Esa propiedad devuelve una instancia HostViewModel, así podemos usar el operador punto en ese objeto para acceder a la propiedad HostViewModel.NextButtonText.That property returns a HostViewModel instance, and so we can dot into that object to access the HostViewModel.NextButtonText property. Además, especificamos Mode para invalidar el {x:Bind} predeterminado de una sola vez.And we specify Mode, to override the {x:Bind} default of one-time.

La propiedad Path admite una variedad de opciones de sintaxis para enlazar a propiedades anidadas, propiedades adjuntas e indexadores de cadenas y de enteros.The Path property supports a variety of syntax options for binding to nested properties, attached properties, and integer and string indexers. Para más información, consulta Sintaxis de property-path.For more info, see Property-path syntax. El enlace a indexadores de cadenas te ofrece el mismo efecto que el enlace a propiedades dinámicas sin tener que implementar ICustomPropertyProvider.Binding to string indexers gives you the effect of binding to dynamic properties without having to implement ICustomPropertyProvider. Para otras opciones de configuración, consulta Extensión de marcado {x:Bind}.For other settings, see {x:Bind} markup extension.

Para ilustrar que la propiedad HostViewModel.NextButtonText es realmente observable, agrega un controlador de eventos Click al botón y actualiza el valor de HostViewModel.NextButtonText.To illustrate that the HostViewModel.NextButtonText property is indeed observable, add a Click event handler to the button, and update the value of HostViewModel.NextButtonText. Compila, ejecuta y haz clic en el botón para ver el valor de actualización de Content del botón.Build, run, and click the button to see the value of the button's Content update.

// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.ViewModel.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    ViewModel().NextButtonText(L"Updated Next button text");
}

Nota

Los cambios en TextBox.Text se envían a un origen de enlace bidireccional cuando TextBox pierde el foco y no después de cada presión de tecla del usuario.Changes to TextBox.Text are sent to a two-way bound source when the TextBox loses focus, and not after every user keystroke.

DataTemplate y x:DataTypeDataTemplate and x:DataType

Dentro de DataTemplate (independientemente de si se usa como plantilla de elemento, plantilla de contenido o plantilla de encabezado), el valor de Path no se interpreta en el contexto de la página, sino en el contexto del objeto de datos al que se aplica la plantilla.Inside a DataTemplate (whether used as an item template, a content template, or a header template), the value of Path is not interpreted in the context of the page, but in the context of the data object being templated. Cuando usas {x:Bind} en la plantilla de datos para que sus enlaces pueden validarse (y un código eficaz generado para ellos) en tiempo de compilación, la clase DataTemplate debe declarar el tipo de su objeto de datos mediante x:DataType.When using {x:Bind} in a data template, so that its bindings can be validated (and efficient code generated for them) at compile-time, the DataTemplate needs to declare the type of its data object using x:DataType. El ejemplo siguiente puede usarse como ItemTemplate de un control de elementos enlazados a una colección de objetos SampleDataGroup.The example given below could be used as the ItemTemplate of an items control bound to a collection of SampleDataGroup objects.

<DataTemplate x:Key="SimpleItemTemplate" x:DataType="data:SampleDataGroup">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{x:Bind Title}"/>
      <TextBlock Text="{x:Bind Description}"/>
    </StackPanel>
  </DataTemplate>

Objetos con establecimiento flexible de tipos en la ruta de accesoWeakly-typed objects in your Path

Consideremos, por ejemplo, que tienes un tipo denominado SampleDataGroup, que implementa una propiedad de cadena denominada Título.Consider for example that you have a type named SampleDataGroup, which implements a string property named Title. Y tienes una propiedad MainPage.SampleDataGroupAsObject, que es de tipo objeto, pero que devuelve realmente una instancia de SampleDataGroup.And you have a property MainPage.SampleDataGroupAsObject, which is of type object, but which actually returns an instance of SampleDataGroup. El enlace <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> generará un error de compilación porque la propiedad Título no se encuentra en el objeto de tipo.The binding <TextBlock Text="{x:Bind SampleDataGroupAsObject.Title}"/> will result in a compile error because the Title property is not found on the type object. La solución para esto es agregar una conversión a la sintaxis de la ruta de acceso, como esta: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>.The remedy for this is to add a cast to your Path syntax like this: <TextBlock Text="{x:Bind ((data:SampleDataGroup)SampleDataGroupAsObject).Title}"/>. Este es otro ejemplo donde se declara el elemento como objeto, pero que realmente es TextBlock: <TextBlock Text="{x:Bind Element.Text}"/>.Here's another example where Element is declared as object but is actually a TextBlock: <TextBlock Text="{x:Bind Element.Text}"/>. Y una conversión soluciona el problema: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.And a cast remedies the issue: <TextBlock Text="{x:Bind ((TextBlock)Element).Text}"/>.

Si los datos se cargan de forma asincrónicaIf your data loads asynchronously

El código para admitir {x:Bind} se genera en tiempo de compilación en las clases parciales para tus páginas.Code to support {x:Bind} is generated at compile-time in the partial classes for your pages. Estos archivos pueden encontrarse en la carpeta obj, con nombres como (para C#) <view name>.g.cs.These files can be found in your obj folder, with names like (for C#) <view name>.g.cs. El código generado incluye un controlador para el evento Loading de tu página y ese controlador llama al método Initialize en una clase generada que representa los enlaces de la página.The generated code includes a handler for your page's Loading event, and that handler calls the Initialize method on a generated class that represent's your page's bindings. Initialize llama a su vez a Update para empezar a mover datos entre el origen de enlace y el destino.Initialize in turn calls Update to begin moving data between the binding source and the target. Loading se genera justo antes del primer paso de medida de la página o del control de usuario.Loading is raised just before the first measure pass of the page or user control. Por lo que si los datos se cargan de forma asincrónica puede que no esté listo en el momento en que se llama a Initialize.So if your data is loaded asynchronously it may not be ready by the time Initialize is called. Por lo tanto, después de cargar los datos, puedes forzar la inicialización de enlaces de un solo uso llamando a this.Bindings.Update();.So, after you've loaded data, you can force one-time bindings to be initialized by calling this.Bindings.Update();. Si solo necesitas enlaces de un solo uso para los datos cargados de forma asincrónica es mucho más barato inicializarlos así que tener enlaces unidireccionales y escuchar los cambios.If you only need one-time bindings for asynchronously-loaded data then it's much cheaper to initialize them this way than it is to have one-way bindings and to listen for changes. Si los datos no sufren cambios específicos y es probable que se actualicen como parte de una acción específica, puedes hacer que tus enlaces sean de un solo uso y forzar una actualización manual en cualquier momento con una llamada a Update.If your data does not undergo fine-grained changes, and if it's likely to be updated as part of a specific action, then you can make your bindings one-time, and force a manual update at any time with a call to Update.

Nota

{x:Bind} no es adecuado para los escenarios enlazados en tiempo de ejecución, como la navegación por la estructura de diccionario de un objeto JSON, como tampoco lo es el estilo duck typing.{x:Bind} is not suited to late-bound scenarios, such as navigating the dictionary structure of a JSON object, nor duck typing. "Duck typing" es un formato de escritura no seguro basado en las correspondencias léxicas de los nombres de propiedad (p. ej., "si anda, nada y grazna como un pato, entonces es un pato")."Duck typing" is a weak form of typing based on lexical matches on property names (a in, "if it walks, swims, and quacks like a duck, then it's a duck"). Con duck typing, un enlace a la propiedad Age podría corresponder a un objeto Person o a un objeto Wine (asumiendo que ambos tipos tuvieran una propiedad de edad).With duck typing, a binding to the Age property would be equally satisfied with a Person or a Wine object (assuming that those types each had an Age property). Para estos escenarios, usa la extensión de marcado {Binding} .For these scenarios, use the {Binding} markup extension.

Objeto de enlace que se declara usando {Binding}Binding object declared using {Binding}

Si usas extensiones de componente de C++/WinRT o Visual C++ (C++/CX), para usar la extensión de marcado {Binding}, deberás agregar el atributo BindableAttribute a cualquier clase en tiempo de ejecución con la que quieras enlazar.If you're using C++/WinRT or Visual C++ component extensions (C++/CX) then, to use the {Binding} markup extension, you'll need to add the BindableAttribute attribute to any runtime class that you want to bind to. Para usar {x:Bind}, no necesitas ese atributo.To use {x:Bind}, you don't need that attribute.

// HostViewModel.idl
// Add this attribute:
[Windows.UI.Xaml.Data.Bindable]
runtimeclass HostViewModel : Windows.UI.Xaml.Data.INotifyPropertyChanged
...

Importante

Si estás usando C++/WinRT, el atributo BindableAttribute está disponible si has instalado la versión de Windows SDK 10.0.17763.0 (Windows 10, versión 1809) o posterior.If you're using C++/WinRT, then the BindableAttribute attribute is available if you've installed the Windows SDK version 10.0.17763.0 (Windows 10, version 1809), or later. Sin ese atributo, tendrás que implementar las interfaces ICustomPropertyProvider y ICustomProperty para poder usar la extensión de marcado {Binding}.Without that attribute, you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces in order to be able to use the {Binding} markup extension.

{Binding} supone que, de forma predeterminada, se está realizando un enlace a la propiedad DataContext de la página de marcado.{Binding} assumes, by default, that you're binding to the DataContext of your markup page. Por lo tanto, estableceremos el DataContext de nuestra página para que sea una instancia de la clase de origen de enlace (de tipo HostViewModel en este caso).So we'll set the DataContext of our page to be an instance of our binding source class (of type HostViewModel in this case). El siguiente ejemplo muestra el marcado que declara el objeto de enlace.The example below shows the markup that declares the binding object. Usamos el mismo destino de enlace Button.Content que usamos en la sección "Destino de enlace" anterior, y enlazamos a la propiedad HostViewModel.NextButtonText.We use the same Button.Content binding target we used in the "Binding target" section earlier, and we bind to the HostViewModel.NextButtonText property.

<Page xmlns:viewmodel="using:DataBindingInDepth" ... >
    <Page.DataContext>
        <viewmodel:HostViewModel x:Name="viewModelInDataContext"/>
    </Page.DataContext>
    ...
    <Button Content="{Binding Path=NextButtonText}" ... />
</Page>
// MainPage.xaml.cs
private void Button_Click(object sender, RoutedEventArgs e)
{
    this.viewModelInDataContext.NextButtonText = "Updated Next button text";
}
// MainPage.cpp
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    viewModelInDataContext().NextButtonText(L"Updated Next button text");
}

Observa el valor que especificamos para Path.Notice the value that we specify for Path. Este valor se interpreta en el contexto de DataContext de la página, que en este ejemplo se establece en una instancia de HostViewModel.This value is interpreted in the context of the page's DataContext, which in this example is set to an instance of HostViewModel. La ruta hace referencia a la propiedad HostViewModel.NextButtonText.The path references the HostViewModel.NextButtonText property. Podemos omitir Mode, porque la {Binding} predeterminada unidireccional funciona aquí.We can omit Mode, because the {Binding} default of one-way works here.

El valor predeterminado de DataContext para un elemento de la interfaz de usuario es el valor heredado de su elemento principal.The default value of DataContext for a UI element is the inherited value of its parent. Por supuesto, puedes anular ese valor predeterminado estableciendo DataContext explícitamente, que se hereda de forma predeterminada por los elementos secundarios.You can of course override that default by setting DataContext explicitly, which is in turn inherited by children by default. La configuración de DataContext explícitamente en un elemento es cuando quieres tener varios enlaces que usen el mismo origen.Setting DataContext explicitly on an element is useful when you want to have multiple bindings that use the same source.

Un objeto de enlace tiene una propiedad Source, que el valor predeterminado es el DataContext del elemento de interfaz de usuario en el que se declara el enlace.A binding object has a Source property, which defaults to the DataContext of the UI element on which the binding is declared. Puedes invalidar este valor predeterminado estableciendo Source, RelativeSource, o ElementName explícitamente en el enlace (consulte {Binding} para obtener más información).You can override this default by setting Source, RelativeSource, or ElementName explicitly on the binding (see {Binding} for details).

Dentro de DataTemplate, DataContext se establece automáticamente en el objeto de datos con plantilla.Inside a DataTemplate, the DataContext is automatically set to the data object being templated. El ejemplo siguiente puede usarse como la propiedad ItemTemplate de un control de elementos enlazado a una colección de cualquier tipo que tiene propiedades de cadena denominadas Title y Description.The example given below could be used as the ItemTemplate of an items control bound to a collection of any type that has string properties named Title and Description.

<DataTemplate x:Key="SimpleItemTemplate">
    <StackPanel Orientation="Vertical" Height="50">
      <TextBlock Text="{Binding Title}"/>
      <TextBlock Text="{Binding Description"/>
    </StackPanel>
  </DataTemplate>

Nota

De forma predeterminada, los cambios en TextBox.Text se envían a un origen de enlace bidireccional cuando la clase TextBox pierde el foco.By default, changes to TextBox.Text are sent to a two-way bound source when the TextBox loses focus. Para hacer que los cambios se envíen después de cada presión de tecla de usuario, establece UpdateSourceTrigger en PropertyChanged en el enlace en el marcado.To cause changes to be sent after every user keystroke, set UpdateSourceTrigger to PropertyChanged on the binding in markup. También puede tomar el control completo de cuándo se envían los datos al origen estableciendo UpdateSourceTrigger en Explicit.You can also completely take control of when changes are sent to the source by setting UpdateSourceTrigger to Explicit. Luego puedes controlar eventos en el cuadro de texto (normalmente TextBox.TextChanged), llamar a GetBindingExpression en el destino para obtener un BindingExpression y finalmente llamar a BindingExpression.UpdateSource para actualizar mediante programación el origen de datos.You then handle events on the text box (typically TextBox.TextChanged), call GetBindingExpression on the target to get a BindingExpression object, and finally call BindingExpression.UpdateSource to programmatically update the data source.

La propiedad Path admite una variedad de opciones de sintaxis para enlazar a propiedades anidadas, propiedades adjuntas e indexadores de cadenas y de enteros.The Path property supports a variety of syntax options for binding to nested properties, attached properties, and integer and string indexers. Para más información, consulta Sintaxis de property-path.For more info, see Property-path syntax. El enlace a indexadores de cadenas te ofrece el mismo efecto que el enlace a propiedades dinámicas sin tener que implementar ICustomPropertyProvider.Binding to string indexers gives you the effect of binding to dynamic properties without having to implement ICustomPropertyProvider. La propiedad ElementName es útil para el enlace de elemento a elemento.The ElementName property is useful for element-to-element binding. La propiedad RelativeSource tiene varios usos, uno de los cuales es como una alternativa más eficaz para el enlace de plantilla dentro de un ControlTemplate.The RelativeSource property has several uses, one of which is as a more powerful alternative to template binding inside a ControlTemplate. Para otras opciones de configuración, consulta extensión de marcado {Binding} y la clase Binding.For other settings, see {Binding} markup extension and the Binding class.

¿Qué ocurre si el origen y el destino no son del mismo tipo?What if the source and the target are not the same type?

Si desea controlar la visibilidad de un elemento de interfaz de usuario en función del valor de una propiedad booleana o si quieres representar un elemento de interfaz de usuario con un color que es una función de un intervalo o tendencia de un valor numérico o si deseas mostrar un valor de fecha y/u hora en una propiedad del elemento de interfaz de usuario que espera una cadena , necesitarás convertir los valores de un tipo a otro.If you want to control the visibility of a UI element based on the value of a boolean property, or if you want to render a UI element with a color that's a function of a numeric value's range or trend, or if you want to display a date and/or time value in a UI element property that expects a string, then you'll need to convert values from one type to another. Habrá casos en los que la solución correcta es exponer otra propiedad del tipo correcto desde la clase de origen de enlace y mantener la lógica de conversión encapsulada y comprobable allí.There will be cases where the right solution is to expose another property of the right type from your binding source class, and keep the conversion logic encapsulated and testable there. Sin embargo, no es escalable ni flexible cuando tienes muchos números o combinaciones grandes de propiedades de origen y destino.But that isn't flexible nor scalable when you have large numbers, or large combinations, of source and target properties. En ese caso, tienes un par de opciones:In that case you have a couple of options:

  • Si usas {x: Bind}, entonces puedes enlazar directamente a una función para hacer esa conversión.If using {x:Bind} then you can bind directly to a function to do that conversion
  • O bien, puedes especificar un convertidor de valores, que es un objeto que se ha diseñado para realizar la conversión.Or you can specify a value converter which is an object designed to perform the conversion

Convertidores de valoresValue Converters

Este es un convertidor de valores adecuado para un enlace único o unidireccional, que convierte un valor DateTime en un valor de cadena que contiene el mes.Here's a value converter, suitable for a one-time or a one-way binding, that converts a DateTime value to a string value containing the month. La clase implementa IValueConverter.The class implements IValueConverter.

public class DateToStringConverter : IValueConverter
{
    // Define the Convert method to convert a DateTime value to 
    // a month string.
    public object Convert(object value, Type targetType, 
        object parameter, string language)
    {
        // value is the data from the source object.
        DateTime thisdate = (DateTime)value;
        int monthnum = thisdate.Month;
        string month;
        switch (monthnum)
        {
            case 1:
                month = "January";
                break;
            case 2:
                month = "February";
                break;
            default:
                month = "Month not found";
                break;
        }
        // Return the value to pass to the target.
        return month;
    }

    // ConvertBack is not implemented for a OneWay binding.
    public object ConvertBack(object value, Type targetType, 
        object parameter, string language)
    {
        throw new NotImplementedException();
    }
}
// See the "Formatting or converting data values for display" section in the "Data binding overview" topic.

Y esta es la forma de consumir ese convertidor de valores en el marcado del objeto de enlace.And here's how you consume that value converter in your binding object markup.

<UserControl.Resources>
  <local:DateToStringConverter x:Key="Converter1"/>
</UserControl.Resources>
...
<TextBlock Grid.Column="0" 
  Text="{x:Bind ViewModel.Month, Converter={StaticResource Converter1}}"/>
<TextBlock Grid.Column="0" 
  Text="{Binding Month, Converter={StaticResource Converter1}}"/>

El motor de enlace llama a los métodos Convert y ConvertBack si se ha definido el parámetro Converter para el enlace.The binding engine calls the Convert and ConvertBack methods if the Converter parameter is defined for the binding. Cuando se pasan los datos del origen, el motor de enlace llama a Convert y pasa los datos devueltos al destino.When data is passed from the source, the binding engine calls Convert and passes the returned data to the target. Cuando se pasan los datos del destino (para un enlace bidireccional), el motor de enlace llama a ConvertBack y pasa los datos devueltos al origen.When data is passed from the target (for a two-way binding), the binding engine calls ConvertBack and passes the returned data to the source.

El convertidor también tiene parámetros opcionales: ConverterLanguage, que permite especificar el lenguaje que se usará en la conversión, y ConverterParameter, que permite pasar un parámetro para la lógica de conversión.The converter also has optional parameters: ConverterLanguage, which allows specifying the language to be used in the conversion, and ConverterParameter, which allows passing a parameter for the conversion logic. Para obtener un ejemplo en el que se use un parámetro de convertidor, consulta IValueConverter.For an example that uses a converter parameter, see IValueConverter.

Nota

Si hay un error en la conversión, no inicies una excepción.If there is an error in the conversion, do not throw an exception. En lugar de eso, devuelve DependencyProperty.UnsetValue, que detendrá la transferencia de datos.Instead, return DependencyProperty.UnsetValue, which will stop the data transfer.

Para mostrar un valor predeterminado para usar cuando no se pueda resolver el origen del enlace, establece la propiedad FallbackValue en el objeto de enlace en el marcado.To display a default value to use whenever the binding source cannot be resolved, set the FallbackValue property on the binding object in markup. Esto sirve para controlar los errores de formato y de conversión.This is useful to handle conversion and formatting errors. También resulta útil para crear un enlace con propiedades de origen que quizás no existen en todos los objetos de una colección enlazada de tipos heterogéneos.It is also useful to bind to source properties that might not exist on all objects in a bound collection of heterogeneous types.

Si enlazas un control de texto con un valor que no es una cadena, el motor de enlace de datos lo convertirá en una.If you bind a text control to a value that is not a string, the data binding engine will convert the value to a string. Si el valor es un tipo de referencia, dicho motor recuperará el valor de cadena llamando a ICustomPropertyProvider.GetStringRepresentation o a IStringable.ToString, si están disponibles, o bien llamando a Object.ToString, si no lo están.If the value is a reference type, the data binding engine will retrieve the string value by calling ICustomPropertyProvider.GetStringRepresentation or IStringable.ToString if available, and will otherwise call Object.ToString. Pero ten en cuenta que el motor de enlace de datos pasará por alto las implementaciones de ToString que oculten la implementación de la clase base.Note, however, that the binding engine will ignore any ToString implementation that hides the base-class implementation. Las implementaciones de la subclase deben invalidar, en cambio, el método ToString de la clase base.Subclass implementations should override the base class ToString method instead. De forma similar, en los lenguajes nativos, todos los objetos administrados parecen implementar ICustomPropertyProvider e IStringable.Similarly, in native languages, all managed objects appear to implement ICustomPropertyProvider and IStringable. Pero todas las llamadas a GetStringRepresentation y a IStringable.ToString se enrutan a Object.ToString o a una invalidación de ese método y nunca a una implementación de ToString que oculta la implementación de la clase base.However, all calls to GetStringRepresentation and IStringable.ToString are routed to Object.ToString or an override of that method, and never to a new ToString implementation that hides the base-class implementation.

Nota

A partir de Windows 10, versión 1607, el marco XAML proporciona un valor booleano integrado para el convertidor de visibilidad.Starting in Windows 10, version 1607, the XAML framework provides a built in boolean to Visibility converter. El convertidor asigna true al valor de la enumeración Visible y false a Collapsed, para que puedas enlazar una propiedad Visibility a un valor booleano sin necesidad de crear un convertidor.The converter maps true to the Visible enumeration value and false to Collapsed so you can bind a Visibility property to a boolean without creating a converter. Para usar el convertidor integrado, la versión mínima del SDK de destino de la aplicación debe ser 14393 o posterior.To use the built in converter, your app's minimum target SDK version must be 14393 or later. No puedes usarlo si la aplicación está destinada a versiones anteriores de Windows 10.You can't use it when your app targets earlier versions of Windows 10. Para obtener más información sobre las versiones de destino, consulta Version adaptive code (Código adaptativo para versiones).For more info about target versions, see Version adaptive code.

Enlace de función en {x: Bind}Function binding in {x:Bind}

{x: Bind} permite que el paso final de una ruta de acceso de enlace sea una función.{x:Bind} enables the final step in a binding path to be a function. Esto puede usarse para realizar conversiones y para realizar enlaces que dependen de más de una propiedad.This can be used to perform conversions, and to perform bindings that depend on more than one property. Consulta Funciones de x:BindSee Functions in x:Bind

Enlace de elemento a elementoElement-to-element binding

Se puede enlazar la propiedad de un elemento XAML a la propiedad de otro elemento XAML.You can bind the property of one XAML element to the property of another XAML element. En este ejemplo se muestra cómo queda en marcado.Here's an example of how that looks in markup.

<TextBox x:Name="myTextBox" />
<TextBlock Text="{x:Bind myTextBox.Text, Mode=OneWay}" />

Importante

Para obtener el flujo de trabajo necesario para el enlace de elemento a elemento mediante C++/WinRT, consulta Enlace de elemento a elemento.For the necessary workflow for element-to-element binding using C++/WinRT, see Element-to-element binding.

Diccionarios de recursos con {x:Bind}Resource dictionaries with {x:Bind}

La extensión de marcado {x:Bind} depende de la generación de códigos; por lo tanto, necesita un archivo de código subyacente que contenga un constructor que llame a InitializeComponent (para inicializar el código generado).The {x:Bind} markup extension depends on code generation, so it needs a code-behind file containing a constructor that calls InitializeComponent (to initialize the generated code). Vuelves a usar el diccionario de recursos creando una instancia de su tipo (por lo que se llama a InitializeComponent) en lugar de hacer referencia a su nombre de archivo.You re-use the resource dictionary by instantiating its type (so that InitializeComponent is called) instead of referencing its filename. Aquí un ejemplo de qué hacer si dispones de un diccionario de recursos existente y quieres usar {xBind} en este.Here's an example of what to do if you have an existing resource dictionary and you want to use {x:Bind} in it.

TemplatesResourceDictionary.xamlTemplatesResourceDictionary.xaml

<ResourceDictionary
    x:Class="ExampleNamespace.TemplatesResourceDictionary"
    .....
    xmlns:examplenamespace="using:ExampleNamespace">
    
    <DataTemplate x:Key="EmployeeTemplate" x:DataType="examplenamespace:IEmployee">
        <Grid>
            <TextBlock Text="{x:Bind Name}"/>
        </Grid>
    </DataTemplate>
</ResourceDictionary>

TemplatesResourceDictionary.xaml.csTemplatesResourceDictionary.xaml.cs

using Windows.UI.Xaml.Data;
 
namespace ExampleNamespace
{
    public partial class TemplatesResourceDictionary
    {
        public TemplatesResourceDictionary()
        {
            InitializeComponent();
        }
    }
}

MainPage.xamlMainPage.xaml

<Page x:Class="ExampleNamespace.MainPage"
    ....
    xmlns:examplenamespace="using:ExampleNamespace">

    <Page.Resources>
        <ResourceDictionary>
            .... 
            <ResourceDictionary.MergedDictionaries>
                <examplenamespace:TemplatesResourceDictionary/>
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Page.Resources>
</Page>

Enlace de eventos e ICommandEvent binding and ICommand

{x:Bind} admite una característica llamada enlace de eventos.{x:Bind} supports a feature called event binding. Con esta característica, puede especificar el controlador para un evento con un enlace, que es una opción adicional sobre el control de eventos con un método en el archivo de código subyacente.With this feature, you can specify the handler for an event using a binding, which is an additional option on top of handling events with a method on the code-behind file. Supongamos que tienes una propiedad RootFrame en tu clase MainPage.Let's say you have a RootFrame property on your MainPage class.

public sealed partial class MainPage : Page
{
    ...
    public Frame RootFrame { get { return Window.Current.Content as Frame; } }
}

Se puede enlazar el evento Click de un botón a un método en el objeto Frame devuelto por la propiedad RootFrame como esta.You can then bind a button's Click event to a method on the Frame object returned by the RootFrame property like this. Ten en cuenta que también enlazamos la propiedad IsEnabled del botón a otro miembro del mismo Frame.Note that we also bind the button's IsEnabled property to another member of the same Frame.

<AppBarButton Icon="Forward" IsCompact="True"
IsEnabled="{x:Bind RootFrame.CanGoForward, Mode=OneWay}"
Click="{x:Bind RootFrame.GoForward}"/>

Los métodos sobrecargados no puede usarse para controlar un evento con esta técnica.Overloaded methods cannot be used to handle an event with this technique. Además, si el método que controla el evento tiene parámetros, todos deben ser asignables a partir de los tipos de todos los parámetros del evento, respectivamente.Also, if the method that handles the event has parameters then they must all be assignable from the types of all of the event's parameters, respectively. En este caso, Frame.GoForward no esté sobrecargado y no tiene parámetros (pero podría ser válido incluso si usó dos parámetros object).In this case, Frame.GoForward is not overloaded and it has no parameters (but it would still be valid even if it took two object parameters). Frame.GoBack está sobrecargado; por lo tanto, no podemos usar ese método con esta técnica.Frame.GoBack is overloaded, though, so we can't use that method with this technique.

La técnica de enlace de eventos es similar a implementar y consumir comandos (un comando es una propiedad que devuelve un objeto que implementa la interfaz ICommand).The event binding technique is similar to implementing and consuming commands (a command is a property that returns an object that implements the ICommand interface). Ambos {x: enlace} y {Binding} funcionan con comandos.Both {x:Bind} and {Binding} work with commands. Debido a que no tienes que implementar el patrón de comando varias veces, puedes usar la clase DelegateCommand auxiliar que encontrarás en la muestra QuizGame (en la carpeta "Común").So that you don't have to implement the command pattern multiple times, you can use the DelegateCommand helper class that you'll find in the QuizGame sample (in the "Common" folder).

Enlace a una colección de carpetas o archivosBinding to a collection of folders or files

Para recuperar datos de archivos y carpetas, puedes usar las API en el espacio de nombres Windows.Storage.You can use the APIs in the Windows.Storage namespace to retrieve folder and file data. No obstante, los distintos métodos GetFilesAsync, GetFoldersAsync y GetItemsAsync no devuelven valores adecuados para enlaces a controles de lista.However, the various GetFilesAsync, GetFoldersAsync, and GetItemsAsync methods do not return values that are suitable for binding to list controls. En cambio, debes enlazar a los valores devueltos de los métodos GetVirtualizedFilesVector, GetVirtualizedFoldersVector y GetVirtualizedItemsVector de la clase FileInformationFactory.Instead, you must bind to the return values of the GetVirtualizedFilesVector, GetVirtualizedFoldersVector, and GetVirtualizedItemsVector methods of the FileInformationFactory class. En el siguiente ejemplo de código de la muestra de StorageDataSource y GetVirtualizedFilesVector encontrarás el patrón de uso más común.The following code example from the StorageDataSource and GetVirtualizedFilesVector sample shows the typical usage pattern. No olvides que declarar el manifiesto picturesLibrary del paquete de funcionalidad de la aplicación y confirmar que hay imágenes en la carpeta de la biblioteca de imágenes.Remember to declare the picturesLibrary capability in your app package manifest, and confirm that there are pictures in your Pictures library folder.

protected override void OnNavigatedTo(NavigationEventArgs e)
{
    var library = Windows.Storage.KnownFolders.PicturesLibrary;
    var queryOptions = new Windows.Storage.Search.QueryOptions();
    queryOptions.FolderDepth = Windows.Storage.Search.FolderDepth.Deep;
    queryOptions.IndexerOption = Windows.Storage.Search.IndexerOption.UseIndexerWhenAvailable;

    var fileQuery = library.CreateFileQueryWithOptions(queryOptions);

    var fif = new Windows.Storage.BulkAccess.FileInformationFactory(
        fileQuery,
        Windows.Storage.FileProperties.ThumbnailMode.PicturesView,
        190,
        Windows.Storage.FileProperties.ThumbnailOptions.UseCurrentScale,
        false
        );

    var dataSource = fif.GetVirtualizedFilesVector();
    this.PicturesListView.ItemsSource = dataSource;
}

Normalmente usarás este enfoque para crear una vista de solo lectura de la información de archivo y carpeta.You will typically use this approach to create a read-only view of file and folder info. Puedes crear enlaces bidireccionales a las propiedades de archivo y carpeta; por ejemplo, para permitir que los usuarios califiquen una canción en una vista de música.You can create two-way bindings to the file and folder properties, for example to let users rate a song in a music view. No obstante, ningún cambio persiste hasta que no llames al método SavePropertiesAsync apropiado (por ejemplo, MusicProperties.SavePropertiesAsync).However, any changes are not persisted until you call the appropriate SavePropertiesAsync method (for example, MusicProperties.SavePropertiesAsync). Debes confirmar cambios cuando el elemento pierde el foco, porque esto desencadena el restablecimiento de la selección.You should commit changes when the item loses focus because this triggers a selection reset.

Ten en cuenta que el enlace bidireccional con esta técnica solo funciona con ubicaciones indizadas, como Música.Note that two-way binding using this technique works only with indexed locations, such as Music. Puedes determinar si una ubicación es indizada llamando al método FolderInformation.GetIndexedStateAsync.You can determine whether a location is indexed by calling the FolderInformation.GetIndexedStateAsync method.

Ten en cuenta también que un vector virtualizado puede devolver null para algunos elementos antes de que rellene su valor.Note also that a virtualized vector can return null for some items before it populates their value. Por ejemplo, debes comprobar null antes de usar el valor SelectedItem de un control de lista enlazado a un vector virtualizado o, en su lugar, usar SelectedIndex.For example, you should check for null before you use the SelectedItem value of a list control bound to a virtualized vector, or use SelectedIndex instead.

Enlace de datos agrupados por una claveBinding to data grouped by a key

Si tomas una colección plana de elementos (libros, por ejemplo, representados por una clase BookSku) y agrupas los elementos mediante una propiedad común, como una clave (la propiedad BookSku.AuthorName, por ejemplo), el resultado son datos agrupados.If you take a flat collection of items (books, for example, represented by a BookSku class) and you group the items by using a common property as a key (the BookSku.AuthorName property, for example) then the result is called grouped data. Al agrupar los datos, ya no es una colección plana.When you group data, it is no longer a flat collection. Los datos agrupados son una colección de objetos de grupo, donde cada objeto de grupo tieneGrouped data is a collection of group objects, where each group object has

  • una clave ya key, and
  • una colección de elementos cuya propiedad coincide con esa clave.a collection of items whose property matches that key.

Si retomamos el ejemplo de los libros, la agrupación de los libros por nombre de autor da como resultado una colección de grupos de nombres de autor donde cada grupo tieneTo take the books example again, the result of grouping the books by author name results in a collection of author name groups where each group has

  • una clave, que es un nombre de autor, ya key, which is an author name, and
  • una colección de BookSkus cuya propiedad AuthorName coincide con la clave del grupo.a collection of the BookSkus whose AuthorName property matches the group's key.

En general, para mostrar una colección, enlazas el ItemsSource de un control de elementos (como ListView o GridView) directamente a una propiedad que devuelve una colección.In general, to display a collection, you bind the ItemsSource of an items control (such as ListView or GridView) directly to a property that returns a collection. Si es una colección de elementos plana no necesitas hacer nada especial.If that's a flat collection of items then you don't need to do anything special. Pero si es una colección de objetos de grupo (como al enlazar a datos agrupados), a continuación, necesitas los servicios de un objeto intermediario llamado CollectionViewSource, que se encuentra entre el control de elementos y el origen del enlace.But if it's a collection of group objects (as it is when binding to grouped data) then you need the services of an intermediary object called a CollectionViewSource which sits between the items control and the binding source. Enlaza el CollectionViewSource a la propiedad que devuelve datos agrupados y enlaza el control de elementos a CollectionViewSource.You bind the CollectionViewSource to the property that returns grouped data, and you bind the items control to the CollectionViewSource. Un valor agregado adicional de un CollectionViewSource es que realiza el seguimiento del elemento actual, para poder mantener más de un control de elementos sincronizados al enlazarlos todos al mismo CollectionViewSource.An extra value-add of a CollectionViewSource is that it keeps track of the current item, so you can keep more than one items control in sync by binding them all to the same CollectionViewSource. Puedes acceder también al elemento actual mediante programación a través de la propiedad ICollectionView.CurrentItem del objeto devuelto por la propiedad CollectionViewSource.View.You can also access the current item programmatically through the ICollectionView.CurrentItem property of the object returned by the CollectionViewSource.View property.

Para activar la función de agrupación de un CollectionViewSource, establece IsSourceGrouped en true.To activate the grouping facility of a CollectionViewSource, set IsSourceGrouped to true. Si también debes establecer la propiedad ItemsPath depende de cómo crees exactamente los objetos de grupo.Whether you also need to set the ItemsPath property depends on exactly how you author your group objects. Existen dos formas para crear un objeto de grupo: el patrón de "es un grupo" y el "tiene un grupo".There are two ways to author a group object: the "is-a-group" pattern, and the "has-a-group" pattern. En el modelo "es un grupo", el objeto de grupo se deriva de un tipo de colección (por ejemplo, List<T> ), de modo que el objeto de grupo en realidad es el grupo de elementos.In the "is-a-group" pattern, the group object derives from a collection type (for example, List<T>), so the group object actually is itself the group of items. Con este modelo, es necesario establecer ItemsPath.With this pattern you do not need to set ItemsPath. En el modelo "tiene un grupo", el objeto de grupo tiene una o más propiedades de un tipo de colección (como List<T> ), por lo que el grupo "tiene un" grupo de elementos en forma de una propiedad (o varios grupos de elementos en forma de varias propiedades).In the "has-a-group" pattern, the group object has one or more properties of a collection type (such as List<T>), so the group "has a" group of items in the form of a property (or several groups of items in the form of several properties). Con este modelo, debes establecer ItemsPath en el nombre de la propiedad que contiene el grupo de elementos.With this pattern you need to set ItemsPath to the name of the property that contains the group of items.

El siguiente ejemplo muestra el modelo de "tiene un grupo".The example below illustrates the "has-a-group" pattern. La clase de página tiene una propiedad denominada ViewModel, que devuelve una instancia de nuestro modelo de vista.The page class has a property named ViewModel, which returns an instance of our view model. El CollectionViewSource enlaza a la propiedad Authors del modelo de vista (Authors es la colección de objetos de grupo) y también especifica que es la propiedad Author.BookSkus que contiene los elementos agrupados.The CollectionViewSource binds to the Authors property of the view model (Authors is the collection of group objects) and also specifies that it's the Author.BookSkus property that contains the grouped items. Por último, la GridView está enlazada al CollectionViewSource, y su estilo de grupo se define para que pueda representar los elementos en grupos.Finally, the GridView is bound to the CollectionViewSource, and has its group style defined so that it can render the items in groups.

<Page.Resources>
    <CollectionViewSource
    x:Name="AuthorHasACollectionOfBookSku"
    Source="{x:Bind ViewModel.Authors}"
    IsSourceGrouped="true"
    ItemsPath="BookSkus"/>
</Page.Resources>
...
<GridView
ItemsSource="{x:Bind AuthorHasACollectionOfBookSku}" ...>
    <GridView.GroupStyle>
        <GroupStyle
            HeaderTemplate="{StaticResource AuthorGroupHeaderTemplateWide}" ... />
    </GridView.GroupStyle>
</GridView>

Para implementar el patrón de "es un grupo" en uno de dos maneras.You can implement the "is-a-group" pattern in one of two ways. Es una forma crear tu propia clase de grupo.One way is to author your own group class. Deriva la clase de List<T> (donde T es el tipo de los elementos).Derive the class from List<T> (where T is the type of the items). Por ejemplo, public class Author : List<BookSku>.For example, public class Author : List<BookSku>. La segunda manera es usar una expresión LINK para crear dinámicamente objetos de grupo (y una clase de grupo) desde valores de propiedad similares de los elementos BookSku.The second way is to use a LINQ expression to dynamically create group objects (and a group class) from like property values of the BookSku items. Este enfoque, mantener solo una lista de elementos y agrupar sobre la marcha, es típico de una aplicación que accede a los datos de un servicio de nube.This approach—maintaining only a flat list of items and grouping them together on the fly—is typical of an app that accesses data from a cloud service. Obtienes la flexibilidad de agrupar libros según el autor o el género (por ejemplo), sin necesidad de disponer de clases de grupo especiales, como Author y Genre.You get the flexibility to group books by author or by genre (for example) without needing special group classes such as Author and Genre.

El siguiente ejemplo muestra el uso del patrón "es un grupo" LINQ.The example below illustrates the "is-a-group" pattern using LINQ. Esta vez agrupamos libros por género, mostrados con el nombre de género en los encabezados de grupo.This time we group books by genre, displayed with the genre name in the group headers. Esto se indica en la ruta de acceso de la propiedad "Key" en referencia al valor Key del grupo.This is indicated by the "Key" property path in reference to the group Key value.

using System.Linq;
...
private IOrderedEnumerable<IGrouping<string, BookSku>> genres;

public IOrderedEnumerable<IGrouping<string, BookSku>> Genres
{
    get
    {
        if (this.genres == null)
        {
            this.genres = from book in this.bookSkus
                          group book by book.genre into grp
                          orderby grp.Key
                          select grp;
        }
        return this.genres;
    }
}

Recuerda que, al usar {x:Bind} con plantillas de datos que necesitamos para indicar el tipo enlazado a estableciendo un valor x:DataType.Remember that when using {x:Bind} with data templates we need to indicate the type being bound to by setting an x:DataType value. Si el tipo es genérico y no podemos declaramos que en el marcado que necesitamos usar {Binding} en su lugar en la plantilla de encabezado de estilo de grupo.If the type is generic then we can't express that in markup so we need to use {Binding} instead in the group style header template.

    <Grid.Resources>
        <CollectionViewSource x:Name="GenreIsACollectionOfBookSku"
        Source="{x:Bind Genres}"
        IsSourceGrouped="true"/>
    </Grid.Resources>
    <GridView ItemsSource="{x:Bind GenreIsACollectionOfBookSku}">
        <GridView.ItemTemplate x:DataType="local:BookTemplate">
            <DataTemplate>
                <TextBlock Text="{x:Bind Title}"/>
            </DataTemplate>
        </GridView.ItemTemplate>
        <GridView.GroupStyle>
            <GroupStyle>
                <GroupStyle.HeaderTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding Key}"/>
                    </DataTemplate>
                </GroupStyle.HeaderTemplate>
            </GroupStyle>
        </GridView.GroupStyle>
    </GridView>

Un control SemanticZoom es una manera ideal para que los usuarios vean y naveguen por los datos agrupados.A SemanticZoom control is a great way for your users to view and navigate grouped data. La aplicación de muestra Bookstore2 ilustra cómo usar SemanticZoom.The Bookstore2 sample app illustrates how to use the SemanticZoom. En esa aplicación, puedes ver una lista de libros agrupados por autor (la vista ampliada) o alejar para ver una lista de accesos directos de autores (la vista alejada).In that app, you can view a list of books grouped by author (the zoomed-in view) or you can zoom out to see a jump list of authors (the zoomed-out view). La lista de accesos directos ofrece una navegación mucho más rápida que un desplazamiento por la lista de libros.The jump list affords much quicker navigation than scrolling through the list of books. Las vistas acercada y alejada en realidad son controles ListView o GridView enlazados a la misma clase CollectionViewSource.The zoomed-in and zoomed-out views are actually ListView or GridView controls bound to the same CollectionViewSource.

Ilustración de SemanticZoom

Cuando se enlaza a datos jerárquicos (como subcategorías dentro de las categorías), puedes mostrar los niveles jerárquicos en la interfaz de usuario con una serie de controles de elementos.When you bind to hierarchical data—such as subcategories within categories—you can choose to display the hierarchical levels in your UI with a series of items controls. Una selección en un control de elementos determina el contenido de los controles de elementos posteriores.A selection in one items control determines the contents of subsequent items controls. Puedes mantener las listas sincronizadas, al enlazar cada una de ellas a su propio CollectionViewSource y al enlazar las instancias de CollectionViewSource juntas en una cadena.You can keep the lists synchronized by binding each list to its own CollectionViewSource and binding the CollectionViewSource instances together in a chain. Esto se denomina una vista maestro/detalles (o la lista y detalles).This is called a master/details (or list/details) view. Para más información, consulta el tema Cómo enlazar a datos jerárquicos y crear una vista maestro y detalles.For more info, see How to bind to hierarchical data and create a master/details view.

Diagnóstico y depuración de problemas de enlace de datosDiagnosing and debugging data binding problems

El marcado de enlace contiene los nombres de propiedades (y para C#, a veces campos y métodos).Your binding markup contains the names of properties (and, for C#, sometimes fields and methods). Por lo tanto, cuando cambias el nombre de una propiedad, también tendrás que cambiar cualquier enlace que haga referencia a él.So when you rename a property, you'll also need to change any binding that references it. Olvidar hacer que conduce a un ejemplo típico de un error de enlace de datos y la aplicación no compile o no ejecutarse correctamente.Forgetting to do that leads to a typical example of a data binding bug, and your app either won't compile or won't run correctly.

Los objetos de enlace creados por {x: enlace} y {Binding} son prácticamente funcionalmente equivalentes.The binding objects created by {x:Bind} and {Binding} are largely functionally equivalent. Pero {x:Bind} tiene información de tipo de origen de enlace, y genera código fuente en tiempo de compilación.But {x:Bind} has type information for the binding source, and it generates source code at compile-time. Con {x: enlace} obtener el mismo tipo de detección de problemas que se obtiene con el resto del código.With {x:Bind} you get the same kind of problem detection that you get with the rest of your code. Que incluye la validación de tiempo de compilación de las expresiones de enlace y depuración estableciendo puntos de interrupción en el código fuente que se generan como la clase parcial de la página.That includes compile-time validation of your binding expressions, and debugging by setting breakpoints in the source code generated as the partial class for your page. Estas clases pueden encontrarse en los archivos en tu obj carpetas con nombres como (para C#) <view name>.g.cs).These classes can be found in the files in your obj folder, with names like (for C#) <view name>.g.cs). Si tiene un problema con un enlace y activar interrumpir en las excepciones no controladas en el depurador de Microsoft Visual Studio.If you have a problem with a binding then turn on Break On Unhandled Exceptions in the Microsoft Visual Studio debugger. El depurador interrumpirá la ejecución en ese punto y, a continuación, se pueden depurar lo que ha funcionado.The debugger will break execution at that point, and you can then debug what has gone wrong. El código generado por {x:Bind} sigue el mismo patrón para cada parte del gráfico de nodos de origen de enlace, y puedes usar la información de la ventana Pila de llamadas para ayudar a determinar la secuencia de llamadas que condujeron al problema.The code generated by {x:Bind} follows the same pattern for each part of the graph of binding source nodes, and you can use the info in the Call Stack window to help determine the sequence of calls that led up to the problem.

{Binding} no tiene información de tipo de origen de enlace.{Binding} does not have type information for the binding source. Cuando ejecutas la aplicación con el depurador adjunto, los errores de enlace aparecen en la ventana Resultado en Visual Studio.But when you run your app with the debugger attached, any binding errors appear in the Output window in Visual Studio.

Crear enlaces en el códigoCreating bindings in code

Nota  Esta sección solo se aplica a {Binding}, porque no puedes crear enlaces {x:Bind} en el código.Note  This section only applies to {Binding}, because you can't create {x:Bind} bindings in code. Sin embargo, algunas de las ventajas de {x:Bind} pueden conseguirse con DependencyObject.RegisterPropertyChangedCallback, que te permite registrar notificaciones de cambio en cualquier propiedad de dependencia.However, some of the same benefits of {x:Bind} can be achieved with DependencyObject.RegisterPropertyChangedCallback, which enables you to register for change notifications on any dependency property.

También puedes conectar elementos de la interfaz de usuario a datos usando código de procedimientos en lugar de XAML.You can also connect UI elements to data using procedural code instead of XAML. Para ello, crea un nuevo objeto Binding, establece las propiedades correspondientes y luego llama a FrameworkElement.SetBinding o BindingOperations.SetBinding.To do this, create a new Binding object, set the appropriate properties, then call FrameworkElement.SetBinding or BindingOperations.SetBinding. Crear enlaces mediante programación te resultará útil si quieres elegir los valores de propiedad de los enlaces en tiempo de ejecución o compartir un único enlace entre varios controles.Creating bindings programmatically is useful when you want to choose the binding property values at run-time or share a single binding among multiple controls. Pero ten en cuenta que no puedes cambiar los valores de propiedad de los enlaces después de llamar a SetBinding.Note, however, that you cannot change the binding property values after you call SetBinding.

En el siguiente ejemplo se muestra cómo implementar un enlace en el código.The following example shows how to implement a binding in code.

<TextBox x:Name="MyTextBox" Text="Text"/>
// Create an instance of the MyColors class 
// that implements INotifyPropertyChanged.
MyColors textcolor = new MyColors();

// Brush1 is set to be a SolidColorBrush with the value Red.
textcolor.Brush1 = new SolidColorBrush(Colors.Red);

// Set the DataContext of the TextBox MyTextBox.
MyTextBox.DataContext = textcolor;

// Create the binding and associate it with the text box.
Binding binding = new Binding() { Path = new PropertyPath("Brush1") };
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding);
' Create an instance of the MyColors class 
' that implements INotifyPropertyChanged. 
Dim textcolor As New MyColors()

' Brush1 is set to be a SolidColorBrush with the value Red. 
textcolor.Brush1 = New SolidColorBrush(Colors.Red)

' Set the DataContext of the TextBox MyTextBox. 
MyTextBox.DataContext = textcolor

' Create the binding and associate it with the text box.
Dim binding As New Binding() With {.Path = New PropertyPath("Brush1")}
MyTextBox.SetBinding(TextBox.ForegroundProperty, binding)

{x: enlace} y {Binding} comparación de características{x:Bind} and {Binding} feature comparison

CaracterísticaFeature {x:Bind}{x:Bind} {Binding}{Binding} NotasNotes
La ruta de acceso es la propiedad predeterminadaPath is the default property {x:Bind a.b.c} {Binding a.b.c}
Propiedades de accesoPath property {x:Bind Path=a.b.c} {Binding Path=a.b.c} En Bind: x, ruta de acceso raíz está en la página de forma predeterminada, no DataContext.In x:Bind, Path is rooted at the Page by default, not the DataContext.
indizadorIndexer {x:Bind Groups[2].Title} {Binding Groups[2].Title} Enlaza con el elemento especificado en la colección.Binds to the specified item in the collection. Se admiten solamente en números enteros índices.Only integer-based indexes are supported.
Propiedades adjuntasAttached properties {x:Bind Button22.(Grid.Row)} {Binding Button22.(Grid.Row)} Las propiedades adjuntas se especifican mediante paréntesis.Attached properties are specified using parentheses. Si la propiedad no está declarada en un espacio de nombres XAML, agrega un prefijo con un espacio de nombres XML, que debe estar asignado a un espacio de nombres de código al principio del documento.If the property is not declared in a XAML namespace, then prefix it with an xml namespace, which should be mapped to a code namespace at the head of the document.
ConversiónCasting {x:Bind groups[0].(data:SampleDataGroup.Title)} No necesaria.Not needed. Las conversiones de tipos se especifican mediante paréntesis.Casts are specified using parentheses. Si la propiedad no está declarada en un espacio de nombres XAML, agrega un prefijo con un espacio de nombres XML, que debe estar asignado a un espacio de nombres de código al principio del documento.If the property is not declared in a XAML namespace, then prefix it with an xml namespace, which should be mapped to a code namespace at the head of the document.
ConverterConverter {x:Bind IsShown, Converter={StaticResource BoolToVisibility}} {Binding IsShown, Converter={StaticResource BoolToVisibility}} Convertidores deben declararse en la raíz del página o ResourceDictionary o en App.xaml.Converters must be declared at the root of the Page/ResourceDictionary, or in App.xaml.
ConvertidorParameter, ConvertidorLanguageConverterParameter, ConverterLanguage {x:Bind IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr} {Binding IsShown, Converter={StaticResource BoolToVisibility}, ConverterParameter=One, ConverterLanguage=fr-fr} Convertidores deben declararse en la raíz del página o ResourceDictionary o en App.xaml.Converters must be declared at the root of the Page/ResourceDictionary, or in App.xaml.
TargetNullValueTargetNullValue {x:Bind Name, TargetNullValue=0} {Binding Name, TargetNullValue=0} Se usa cuando la hoja de la expresión de enlace es null.Used when the leaf of the binding expression is null. Usar comillas simples para un valor de cadena.Use single quotes for a string value.
FallbackValueFallbackValue {x:Bind Name, FallbackValue='empty'} {Binding Name, FallbackValue='empty'} Se usa cuando cualquier parte de la ruta de acceso para el enlace (excepto la hoja) es null.Used when any part of the path for the binding (except for the leaf) is null.
ElementNameElementName {x:Bind slider1.Value} {Binding Value, ElementName=slider1} Con {x: enlace} que enlace a un campo; Ruta de acceso raíz está en la página de forma predeterminada, por lo que cualquier elemento con nombre se puede acceder mediante su campo.With {x:Bind} you're binding to a field; Path is rooted at the Page by default, so any named element can be accessed via its field.
RelativeSource: Self (Automático)RelativeSource: Self <Rectangle x:Name="rect1" Width="200" Height="{x:Bind rect1.Width}" ... /> <Rectangle Width="200" Height="{Binding Width, RelativeSource={RelativeSource Self}}" ... /> Con {x: Bind}, nombre del elemento y usar su nombre en la ruta de acceso.With {x:Bind}, name the element and use its name in Path.
RelativeSource: TemplatedParentRelativeSource: TemplatedParent No necesariaNot needed {Binding <path>, RelativeSource={RelativeSource TemplatedParent}} Con {x:Bind}, TargetType en ControlTemplate indica un enlace con el elemento primario de la plantilla.With {x:Bind} TargetType on ControlTemplate indicates binding to template parent. Para {Binding}, se puede usar el enlace de plantilla normal para plantillas de control en mayoría de casos.For {Binding} Regular template binding can be used in control templates for most uses. Pero usa TemplatedParent donde necesites usar un convertidor o un enlace bidireccional.<But use TemplatedParent where you need to use a converter, or a two-way binding.<
OrigenSource No necesariaNot needed <ListView ItemsSource="{Binding Orders, Source={StaticResource MyData}}"/> Para {x:Bind}, puedes usar directamente el elemento con nombre y una propiedad o ruta de acceso estática.For {x:Bind} you can directly use the named element, use a property or a static path.
ModoMode {x:Bind Name, Mode=OneWay} {Binding Name, Mode=TwoWay} El modo puede ser OneTime, OneWay o TwoWay.Mode can be OneTime, OneWay, or TwoWay. {x: enlace} el valor predeterminado es OneTime; {Binding} predeterminado OneWay.{x:Bind} defaults to OneTime; {Binding} defaults to OneWay.
UpdateSourceTriggerUpdateSourceTrigger {x:Bind Name, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged} {Binding UpdateSourceTrigger=PropertyChanged} UpdateSourceTrigger puede ser Default, LostFocus o PropertyChanged.UpdateSourceTrigger can be Default, LostFocus, or PropertyChanged. {x:Bind} no admite UpdateSourceTrigger=Explicit.{x:Bind} does not support UpdateSourceTrigger=Explicit. {x:Bind} usa el comportamiento PropertyChanged para todos los casos, excepto TextBox.Text, donde utiliza el comportamiento LostFocus.{x:Bind} uses PropertyChanged behavior for all cases except TextBox.Text, where it uses LostFocus behavior.