Controles de elementos de XAML; enlazar a una colección C++/WinRT

Una colección que se puede enlazar de forma eficaz a un control de elementos de XAML se conoce como una colección observable. Esta idea se basa en el patrón de diseño de software conocido como patrón observador. En este tema se muestra cómo implementar colecciones observables en C++/WinRT y cómo enlazar controles de elementos XAML a dichas propiedades (para obtener información general, consulta Enlace de datos).

Si deseas seguir este tema, es mejor que primero crees el proyecto que se describe en Controles XAML; enlazar a una propiedad C++/WinRT. En este tema se agrega más código a ese proyecto, y se agrega a los conceptos explicados en ese tema.

Importante

Para conocer los conceptos y términos esenciales que te ayuden a entender cómo consumir y crear clases en tiempo de ejecución con C++/WinRT, consulta Consumir API con C++/WinRT y Crear API con C++/WinRT .

¿Qué significa observable con respecto a una colección?

Si una clase en tiempo de ejecución que representa una colección elige generar el evento IObservableVector<T>::VectorChanged cada vez que un elemento se agregue a ella o se quite de ella, la clase en tiempo de ejecución es una colección observable. El control de elementos XAML puede enlazarse a estos eventos, y controlarlos, mediante la recuperación de la colección actualizada y luego actualizarse automáticamente para mostrar los elementos actuales.

Nota

Para más información sobre cómo instalar y usar la Extensión de Visual Studio (VSIX) para C++/WinRT y el paquete de NuGet (que juntos proporcionan la plantilla de proyecto y compatibilidad de la compilación), consulta Compatibilidad de Visual Studio para C++/WinRT.

Adición de una colección BookSkus a BookstoreViewModel

En Controles XAML; enlazar a una propiedad C++/WinRT, hemos agregado una propiedad de tipo BookSku a nuestro modelo de vista principal. En este paso, usaremos la plantilla de función de fábrica winrt::single_threaded_observable_vector para que nos ayude a implementar una colección observable de BookSku en el mismo modelo de vista.

Declara una nueva propiedad en BookstoreViewModel.idl.

// BookstoreViewModel.idl
...
runtimeclass BookstoreViewModel
{
    BookSku BookSku{ get; };
    Windows.Foundation.Collections.IObservableVector<BookSku> BookSkus{ get; };
}
...

Nota

En la lista anterior de MIDL 3.0, observa que el tipo de la propiedad BookSkus es IObservableVector de BookSku. En la siguiente sección de este tema, vamos a enlazar el origen de elementos de ListBox a BookSkus. Un cuadro de lista es un control de elementos, y para establecer correctamente la propiedad ItemsControl.ItemsSource, debes hacerlo con un valor de tipo IObservableVector (o IVector), o de un tipo de interoperabilidad como IBindableObservableVector.

Advertencia

El código que se muestra en este tema se aplica a C++/WinRT versión 2.0.190530.8 y versiones posteriores. Si usas una versión anterior, tendrás que realizar algunos ajustes menores en el código mostrado. En el listado de MIDL 3.0 anterior, cambia la propiedad BookSkus a IObservableVector de IInspectable. Y, luego, también usa IInspectable (en lugar de BookSku) en la implementación.

Guarda y compila. Copia los códigos auxiliares del descriptor de acceso de BookstoreViewModel.h y BookstoreViewModel.cpp en la carpeta \Bookstore\Bookstore\Generated Files\sources (para más información, consulta el tema anterior, Controles XAML; enlazar a una propiedad C++/WinRT). Implementa esos códigos auxiliares de descriptor de acceso de esta manera.

// BookstoreViewModel.h
...
struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
{
    BookstoreViewModel();

    Bookstore::BookSku BookSku();

    Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> BookSkus();

private:
    Bookstore::BookSku m_bookSku{ nullptr };
    Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> m_bookSkus;
};
...
// BookstoreViewModel.cpp
...
BookstoreViewModel::BookstoreViewModel()
{
    m_bookSku = winrt::make<Bookstore::implementation::BookSku>(L"Atticus");
    m_bookSkus = winrt::single_threaded_observable_vector<Bookstore::BookSku>();
    m_bookSkus.Append(m_bookSku);
}

Bookstore::BookSku BookstoreViewModel::BookSku()
{
    return m_bookSku;
}

Windows::Foundation::Collections::IObservableVector<Bookstore::BookSku> BookstoreViewModel::BookSkus()
{
    return m_bookSkus;
}
...

Enlaza un elemento ListBox a la propiedad BookSkus.

Abre MainPage.xaml, que contiene el marcado XAML de nuestra página principal de la interfaz de usuario. Agrega el siguiente marcado dentro del mismo elemento StackPanel que Button.

<ListBox ItemsSource="{x:Bind MainViewModel.BookSkus}">
    <ItemsControl.ItemTemplate>
        <DataTemplate x:DataType="local:BookSku">
            <TextBlock Text="{x:Bind Title, Mode=OneWay}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ListBox>

En MainPage.cpp, agrega una línea de código al controlador de eventos Clic para anexar un libro a la colección.

// MainPage.cpp
...
void MainPage::ClickHandler(IInspectable const&, RoutedEventArgs const&)
{
    MainViewModel().BookSku().Title(L"To Kill a Mockingbird");
    MainViewModel().BookSkus().Append(winrt::make<Bookstore::implementation::BookSku>(L"Moby Dick"));
}
...

Ahora compila y ejecuta el proyecto. Haz clic en el botón para ejecutar el controlador de eventos Clic. Observamos que la implementación de Append genera un evento para informar a la interfaz de usuario de que ha cambiado la colección; y el elemento ListBox vuelve a consultar la colección para actualizar su propio valor de Items. Igual que antes, el título de uno de los libros cambia. Dicho cambio de título se refleja en el botón y en el cuadro de lista.

API importantes