Partager via


Contrôles d’éléments XAML ; lier à une collection C++/WinRT

Une collection pouvant être liée efficacement à un contrôle d’éléments XAML est appelée collection observable. Cette idée est basée sur le modèle de conception logicielle appelé modèle d’observateur . Cette rubrique montre comment implémenter des collections observables dans C++/WinRTet comment lier des contrôles d’éléments XAML à eux (pour obtenir des informations d’arrière-plan, consultez liaison de données).

Si vous souhaitez suivre cette rubrique, nous vous recommandons de créer d’abord le projet décrit dans les contrôles XAML ; liez-vous à une propriété C++/WinRT. Cette rubrique ajoute davantage de code à ce projet et ajoute aux concepts expliqués dans cette rubrique.

Important

Pour connaître les concepts et termes essentiels qui prennent en charge votre compréhension de l’utilisation et de la création de classes runtime avec C++/WinRT, consultez Consommer des API avec C++/WinRT et Créer des API avec C++/WinRT.

Que signifie 'observable ' pour une collection ?

Si une classe runtime qui représente une collection choisit de déclencher l’événement IObservableVector<T> ::VectorChanged chaque fois qu’un élément est ajouté ou supprimé de celui-ci, la classe runtime est une collection observable. Un contrôle d’éléments XAML peut se lier à ces événements et les gérer en récupérant la collection mise à jour, puis en se mettant à jour afin d'afficher les éléments actuels.

Remarque

Pour plus d’informations sur l’installation et l’utilisation de l’extension Visual Studio C++/WinRT (VSIX) et du package NuGet (qui fournissent ensemble la prise en charge du modèle de projet et de la génération), consultez prise en charge de Visual Studio pour C++/WinRT.

Ajouter une collection BookSkus à BookstoreViewModel

Dans contrôles XAML : nous avons lié une propriété C++/WinRTet ajouté une propriété de type BookSku à notre modèle d’affichage principal. Dans cette étape, nous allons utiliser le modèle de fonction d’usine winrt ::single_threaded_observable_vector pour nous aider à implémenter une collection observable de BookSku sur le même modèle d’affichage.

Déclarez une nouvelle propriété dans BookstoreViewModel.idl.

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

Important

La liaison à une collection avec C++/WinRT est un peu plus subtile qu’avec C#. Dans la liste MIDL 3.0 ci-dessus, notez que le type de la propriété BookSkus est IObservableVector de BookSku. Dans la section suivante de cette rubrique, nous allons lier la source d’éléments d’un ListBox à BookSkus. Une zone de liste est un contrôle d’éléments et pour définir correctement la propriété ItemsControl.ItemsSource , vous devez la définir sur une valeur de type IObservableVector, ou IVector, ou d’un type d’interopérabilité tel que IBindableObservableVector. Sinon, {x:Bind} génère E_INVALIDARG et {Binding} échoue en mode silencieux.

Avertissement

Le code présenté dans cette rubrique s’applique à C++/WinRT version 2.0.190530.8 ou ultérieure. Si vous utilisez une version antérieure, vous devez apporter des modifications mineures au code affiché. Dans la liste MIDL 3.0 ci-dessus, remplacez la propriété BookSkus par IObservableVector de IInspectable. Ensuite, utilisez également IInspectable (au lieu de BookSku) dans votre implémentation.

Enregistrez et générez. Copiez les squelettes d'accesseur à partir de BookstoreViewModel.h et BookstoreViewModel.cpp dans le dossier \Bookstore\Bookstore\Generated Files\sources (pour plus de détails, consultez le sujet précédent, contrôles XAML ; liez à une propriété C++/WinRT). Implémentez ces stubs d’accesseur comme ceci.

// 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;
}
...

Associer une ListBox à la propriété BookSkus

Ouvrez MainPage.xaml, qui contient le balisage XAML de notre page d’interface utilisateur principale. Ajoutez le balisage suivant à l’intérieur du même StackPanel que le bouton .

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

Dans MainPage.cpp, ajoutez une ligne de code au gestionnaire d’événements Click pour ajouter un livre à la collection.

// 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"));
}
...

Maintenant, générez et exécutez le projet. Cliquez sur le bouton pour exécuter le gestionnaire d'événements Click. Nous avons vu que l’implémentation d’Append déclenche un événement pour informer l’interface utilisateur que la collection a changé ; et ListBox interroge à nouveau la collection pour mettre à jour sa propre valeur Items . Tout comme avant, le titre de l’un des livres change ; et cette modification de titre est reflétée à la fois sur le bouton et dans la zone de liste.

API importantes