Contrôles XAML ; liaison à une propriété C++/WinRTXAML controls; bind to a C++/WinRT property

Une propriété qui peut être efficacement liée à un contrôle XAML est appelée propriété observable.A property that can be effectively bound to a XAML control is known as an observable property. Ce concept est basé sur le modèle de conception logicielle appelé modèle observateur.This idea is based on the software design pattern known as the observer pattern. Cette rubrique montre comment implémenter des propriétés observables en C++/WinRT et y lier des contrôles XAML (pour des informations de référence, consultez Liaison de données.This topic shows how to implement observable properties in C++/WinRT, and how to bind XAML controls to them (for background info, see Data binding).

Important

Pour obtenir les principaux concepts et termes facilitant votre compréhension pour utiliser et créer des classes runtime avec C++/WinRT, voir Utiliser des API avec C++/WinRT et Créer des API avec C++/WinRT.For essential concepts and terms that support your understanding of how to consume and author runtime classes with C++/WinRT, see Consume APIs with C++/WinRT and Author APIs with C++/WinRT.

Que signifie observable pour une propriété ?What does observable mean for a property?

Supposons qu’une classe runtime nommée BookSku a une propriété nommée Title.Let's say that a runtime class named BookSku has a property named Title. Si BookSku déclenche l’événement INotifyPropertyChanged::PropertyChanged chaque fois que la valeur de Title change, cela signifie que Title est une propriété observable.If BookSku raises the INotifyPropertyChanged::PropertyChanged event whenever the value of Title changes, then that means that Title is an observable property. C’est le comportement de BookSku (déclenchement ou non de l’événement) qui détermine lesquelles de ses propriétés, le cas échéant, sont observables.It's the behavior of BookSku (raising or not raising the event) that determines which, if any, of its properties are observable.

Un élément de texte XAML, ou contrôle, peut établir une liaison à ces événements, et les gérer.A XAML text element, or control, can bind to, and handle, these events. Un tel élément ou contrôle gère l’événement en récupérant la ou les valeurs mises à jour, puis en se mettant lui-même à jour pour afficher la nouvelle valeur.Such an element or control handles the event by retrieving the updated value(s), and then updating itself to show the new value.

Notes

Pour plus d’informations sur l’installation et l’utilisation de l’extension VSIX (Visual Studio Extension) C++/WinRT et du package NuGet (qui fournissent ensemble la prise en charge des modèles et des builds de projet), consultez Prise en charge de Visual Studio pour C++/WinRT.For info about installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support), see Visual Studio support for C++/WinRT.

Créer une application vide (Bookstore)Create a Blank App (Bookstore)

Commencez par créer un nouveau projet dans Microsoft Visual Studio.Begin by creating a new project in Microsoft Visual Studio. Créez un projet Application vide (C++/WinRT) et nommez-le Bookstore.Create a Blank App (C++/WinRT) project, and name it Bookstore. Vérifiez que l’option Placer la solution et le projet dans le même répertoire n’est pas cochée.Make sure that Place solution and project in the same directory is unchecked. Ciblez la dernière version en disponibilité générale (autrement dit, pas la préversion) du SDK Windows.Target the latest generally-available (that is, not preview) version of the Windows SDK.

Nous allons créer une nouvelle classe pour représenter un livre qui a une propriété de titre observable.We're going to author a new class to represent a book that has an observable title property. La création et l’utilisation de la classe se feront au sein de la même unité de compilation.We're authoring and consuming the class within the same compilation unit. Mais nous voulons être en mesure d’établir une liaison à cette classe à partir de XAML, c’est pourquoi il s’agira d’une classe runtime.But we want to be able to bind to this class from XAML, and for that reason it's going to be a runtime class. Et nous allons utiliser C++/WinRT à la fois pour la créer et l’utiliser.And we're going to use C++/WinRT to both author and consume it.

La première étape de création d’une nouvelle classe runtime consiste à ajouter un nouvel élément Fichier Midl (.idl) au projet.The first step in authoring a new runtime class is to add a new Midl File (.idl) item to the project. Nommez le nouvel élément BookSku.idl.Name the new item BookSku.idl. Supprimez le contenu par défaut de BookSku.idl et collez-le dans cette déclaration de classe runtime.Delete the default contents of BookSku.idl, and paste in this runtime class declaration.

// BookSku.idl
namespace Bookstore
{
    runtimeclass BookSku : Windows.UI.Xaml.Data.INotifyPropertyChanged
    {
        BookSku(String title);
        String Title;
    }
}

Notes

Vos classes de modèle de vue —en fait, toute classe runtime que vous déclarez dans votre application— ne doit pas dériver d'une classe de base.Your view model classes—in fact, any runtime class that you declare in your application—need not derive from a base class. La classe BookSku déclarée ci-dessus en est un exemple.The BookSku class declared above is an example of that. Elle implémente une interface, mais n’est pas dérivée d’une classe de base.It implements an interface, but it doesn't derive from any base class.

Toute classe runtime que vous déclarez dans l’application et qui dérive d’une classe de base est appelée classe composable.Any runtime class that you declare in the application that does derive from a base class is known as a composable class. Et ces classes composables sont soumises à certaines contraintes.And there are constraints around composable classes. Pour qu’une application puisse réussir les tests du Kit de certification des applications Windows utilisés par Visual Studio et par le Microsoft Store afin de valider les soumissions (et par conséquent, pour que l’application puisse être ingérée avec succès dans le Microsoft Store), une classe composable doit finalement dériver d’une classe de base 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. Ce qui signifie que le type de la classe à la racine de la hiérarchie d’héritage doit provenir d’un espace de noms Windows.*.Meaning that the class at the very root of the inheritance hierarchy must be a type originating in a Windows.* namespace. Si vous devez dériver une classe runtime d’une classe de base—par exemple, pour implémenter une classe BindableBase afin que l’ensemble de vos modèles de vue dérivent de—, vous pouvez la dériver 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.

Un modèle de vue est une abstraction d’une vue, et par conséquent, il est directement lié à la vue (le balisage XAML).A view model is an abstraction of a view, and so it's bound directly to the view (the XAML markup). Un modèle de données est une abstraction de données, et il est consommé uniquement à partir de vos modèles de vue et non directement lié à XAML.A data model is an abstraction of data, and it's consumed only from your view models, and not bound directly to XAML. Vous pouvez donc déclarer vos modèles de données non pas comme des classes runtime, mais comme des structs ou des classes C++.So you can declare your data models not as runtime classes, but as C++ structs or classes. Elles ne doivent être déclarées dans MIDL, et vous êtes libre d’utiliser la hiérarchie d’héritage de votre choix.They don't need to be declared in MIDL, and you're free to use whatever inheritance hierarchy you like.

Enregistrez le fichier, puis générez le projet.Save the file, and build the project. La génération ne va pas encore totalement réussir, mais elle va fait des choses nécessaires pour nous.The build won't entirely succeed yet, but it will do some necessary things for us. Plus particulièrement, pendant le processus de génération, l’outil midl.exe est exécuté pour créer un fichier de métadonnées Windows Runtime (\Bookstore\Debug\Bookstore\Unmerged\BookSku.winmd) décrivant la classe runtime.Specifically, during the build process the midl.exe tool is run to create a Windows Runtime metadata file (\Bookstore\Debug\Bookstore\Unmerged\BookSku.winmd) describing the runtime class. Puis, l’outil cppwinrt.exe est exécuté pour générer les fichiers de code source et vous aider à créer et utiliser votre classe runtime.Then, the cppwinrt.exe tool is run to generate source code files to support you in authoring and consuming your runtime class. Ces fichiers incluent des stubs pour vous aider à implémenter la classe runtime BookSku que vous avez déclarée dans votre fichier IDL.These files include stubs to get you started implementing the BookSku runtime class that you declared in your IDL. Ces stubs sont \Bookstore\Bookstore\Generated Files\sources\BookSku.h et BookSku.cpp.Those stubs are \Bookstore\Bookstore\Generated Files\sources\BookSku.h and BookSku.cpp.

Cliquez avec le bouton droit de la souris sur le nœud du projet, puis cliquez sur Ouvrir le dossier dans l'Explorateur de fichiers.Right-click the project node and click Open Folder in File Explorer. Le dossier du projet s’ouvre dans l'Explorateur de fichiers.This opens the project folder in File Explorer. Copiez les fichiers stub BookSku.h et BookSku.cpp du dossier \Bookstore\Bookstore\Generated Files\sources\ vers le dossier du projet, à savoir \Bookstore\Bookstore\.There, copy the stub files BookSku.h and BookSku.cpp from the \Bookstore\Bookstore\Generated Files\sources\ folder and into the project folder, which is \Bookstore\Bookstore\. Dans l’Explorateur de solutions, avec le nœud de projet sélectionné, assurez-vous que l’option Afficher tous les fichiers est activée.In Solution Explorer, with the project node selected, make sure Show All Files is toggled on. Cliquez avec le bouton droit sur les fichiers stub que vous avez copiés, puis cliquez sur Inclure dans le projet.Right-click the stub files that you copied, and click Include In Project.

Implémenter BookSkuImplement BookSku

Maintenant, ouvrons \Bookstore\Bookstore\BookSku.h et BookSku.cpp et implémentons la classe runtime.Now let's open \Bookstore\Bookstore\BookSku.h and BookSku.cpp and implement our runtime class. Tout d’abord, vous allez voir un static_assert en haut de BookSku.h et de BookSku.cpp, que vous devrez supprimer.First, you'll see a static_assert at the top of BookSku.h and BookSku.cpp, which you'll need to remove.

Dans BookSku.h, apportez les changements suivants.Next, in BookSku.h, make these changes.

  • Sur le constructeur par défaut, remplacez = default par = delete.On the default constructor, change = default to = delete. En effet, nous ne voulons pas de constructeur par défaut.That's because we don't want a default constructor.
  • Ajoutez un membre privé pour stocker la chaîne de titre.Add a private member to store the title string. Notez que nous avons un constructeur qui prend la valeur winrt::hstring.Note that we have a constructor that takes a winrt::hstring value. Cette valeur est la chaîne de titre (« title »).That value is the title string.
  • Ajoutez un autre membre privé pour l’événement que nous déclencherons quand le titre changera.Add another private member for the event that we'll raise when the title changes.

Après avoir apporté ces modifications, votre BookSku.h se présentera comme suit.After making these changes, your BookSku.h will look like this.

// BookSku.h
#pragma once
#include "BookSku.g.h"

namespace winrt::Bookstore::implementation
{
    struct BookSku : BookSkuT<BookSku>
    {
        BookSku() = delete;
        BookSku(winrt::hstring const& title);

        winrt::hstring Title();
        void Title(winrt::hstring const& value);
        winrt::event_token PropertyChanged(Windows::UI::Xaml::Data::PropertyChangedEventHandler const& value);
        void PropertyChanged(winrt::event_token const& token);
    
    private:
        winrt::hstring m_title;
        winrt::event<Windows::UI::Xaml::Data::PropertyChangedEventHandler> m_propertyChanged;
    };
}
namespace winrt::Bookstore::factory_implementation
{
    struct BookSku : BookSkuT<BookSku, implementation::BookSku>
    {
    };
}

Dans BookSku.cpp, implémentez les fonctions comme suit.In BookSku.cpp, implement the functions like this.

// BookSku.cpp
#include "pch.h"
#include "BookSku.h"
#include "BookSku.g.cpp"

namespace winrt::Bookstore::implementation
{
    BookSku::BookSku(winrt::hstring const& title) : m_title{ title }
    {
    }

    winrt::hstring BookSku::Title()
    {
        return m_title;
    }

    void BookSku::Title(winrt::hstring const& value)
    {
        if (m_title != value)
        {
            m_title = value;
            m_propertyChanged(*this, Windows::UI::Xaml::Data::PropertyChangedEventArgs{ L"Title" });
        }
    }

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

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

Dans la fonction mutateur Titre, nous vérifions si une valeur définie est différente de la valeur actuelle.In the Title mutator function, we check whether a value is being set that's different from the current value. Et, si tel est le cas, nous mettons à jour le titre et déclenchons aussi l’événement INotifyPropertyChanged::PropertyChanged avec un argument égal au nom de la propriété qui a changé.And, if so, then we update the title and also raise the INotifyPropertyChanged::PropertyChanged event with an argument equal to the name of the property that has changed. De cette façon, l’interface utilisateur saura quelle valeur de propriété elle doit réinterroger.This is so that the user-interface (UI) will know which property's value to re-query.

Si vous voulez le vérifier, le projet est alors à nouveau généré.The project will build again now, if you want to check that.

Déclarer et implémenter BookstoreViewModelDeclare and implement BookstoreViewModel

Notre page XAML principale va établir une liaison à un modèle d’affichage principal.Our main XAML page is going to bind to a main view model. Et ce modèle d’affichage va avoir plusieurs propriétés, y compris une de type BookSku.And that view model is going to have several properties, including one of type BookSku. Dans cette étape, nous allons déclarer et implémenter la classe runtime de notre modèle d’affichage principal.In this step, we'll declare and implement our main view model runtime class.

Ajoutez un nouvel élément Fichier Midl (.idl) nommé BookstoreViewModel.idl.Add a new Midl File (.idl) item named BookstoreViewModel.idl. Consultez également Factorisation des classes runtime dans des fichiers Midl (.idl).But also see Factoring runtime classes into Midl files (.idl).

// BookstoreViewModel.idl
import "BookSku.idl";

namespace Bookstore
{
    runtimeclass BookstoreViewModel
    {
        BookstoreViewModel();
        BookSku BookSku{ get; };
    }
}

Enregistrez et générez le projet. (La génération ne va pas encore totalement réussir, mais le but de cette génération est de générer à nouveau les fichiers stub.)Save and build (the build won't entirely succeed yet, but the reason we're building is to generate stub files again).

Copiez BookstoreViewModel.h et BookstoreViewModel.cpp à partir du dossier Generated Files\sources dans le dossier de projet, et incluez-les dans le projet.Copy BookstoreViewModel.h and BookstoreViewModel.cpp from the Generated Files\sources folder into the project folder, and include them in the project. Ouvrez ces fichiers (en supprimant à nouveau static_assert), puis implémentez la classe runtime comme indiqué ci-dessous.Open those files (removing the static_assert again), and implement the runtime class as shown below. Notez comment, dans BookstoreViewModel.h, nous incluons BookSku.h, qui déclare le type d’implémentation pour BookSku (c'est-à-dire winrt::Bookstore::implementation::BookSku).Note how, in BookstoreViewModel.h, we're including BookSku.h, which declares the implementation type for BookSku (which is winrt::Bookstore::implementation::BookSku). Et nous supprimons = default du constructeur par défaut.And we're removing = default from the default constructor.

Notes

Dans les listes ci-dessous pour BookstoreViewModel.h et BookstoreViewModel.cpp, le code illustre la façon par défaut de construire le membre de données m_bookSku.In the listings below for BookstoreViewModel.h and BookstoreViewModel.cpp, the code illustrates the default way of constructing the m_bookSku data member. C’est la méthode qui date de la première version de C++ /WinRT, et il est conseillé d’être au moins familiarisé avec le modèle.That's the method that dates back to the first release of C++/WinRT, and it's a good idea to be at least familiar with the pattern. Avec C++ /WinRT version 2.0 et les versions ultérieures, vous disposez d’une forme optimisée de construction, connue sous le nom de construction uniforme (consultez Nouveautés et changements dans C++/WinRT 2.0.).With C++/WinRT version 2.0 and later, there's an optimized form of construction available to you known as uniform construction (see News, and changes, in C++/WinRT 2.0). Plus loin dans cette rubrique, nous présenterons un exemple de construction uniforme.Later in this topic, we'll show an example of uniform construction.

// BookstoreViewModel.h
#pragma once
#include "BookstoreViewModel.g.h"
#include "BookSku.h"

namespace winrt::Bookstore::implementation
{
    struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel>
    {
        BookstoreViewModel();

        Bookstore::BookSku BookSku();

    private:
        Bookstore::BookSku m_bookSku{ nullptr };
    };
}
namespace winrt::Bookstore::factory_implementation
{
    struct BookstoreViewModel : BookstoreViewModelT<BookstoreViewModel, implementation::BookstoreViewModel>
    {
    };
}
// BookstoreViewModel.cpp
#include "pch.h"
#include "BookstoreViewModel.h"
#include "BookstoreViewModel.g.cpp"

namespace winrt::Bookstore::implementation
{
    BookstoreViewModel::BookstoreViewModel()
    {
        m_bookSku = winrt::make<Bookstore::implementation::BookSku>(L"Atticus");
    }

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

Notes

Le type de m_bookSku est le type projeté (winrt::Bookstore::BookSku), et le paramètre de modèle que vous utilisez avec winrt::make est le type d’implémentation (winrt::Bookstore::implementation::BookSku).The type of m_bookSku is the projected type (winrt::Bookstore::BookSku), and the template parameter that you use with winrt::make is the implementation type (winrt::Bookstore::implementation::BookSku). Même dans ce cas, make renvoie une instance du type projeté.Even so, make returns an instance of the projected type.

Le projet est à présent à nouveau généré.The project will build again now.

Ajouter une propriété de type BookstoreViewModel à MainPageAdd a property of type BookstoreViewModel to MainPage

Ouvrez MainPage.idl, qui déclare la classe runtime représentant notre page d’interface utilisateur principale.Open MainPage.idl, which declares the runtime class that represents our main UI page.

  • Ajoutez une directive import pour importer BookstoreViewModel.idl.Add an import directive to import BookstoreViewModel.idl.
  • Ajoutez une propriété en lecture seule nommée MainViewModel, de type BookstoreViewModel.Add a read-only property named MainViewModel, of type BookstoreViewModel.
  • Supprimez la propriété MyProperty.Remove the MyProperty property.
// MainPage.idl
import "BookstoreViewModel.idl";

namespace Bookstore
{
    runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
    {
        MainPage();
        BookstoreViewModel MainViewModel{ get; };
    }
}

Enregistrez le fichier.Save the file. La génération ne va pas encore totalement réussir, mais cette étape est utile car elle regénère les fichiers de code source dans lesquels la classe runtime MainPage est implémentée (\Bookstore\Bookstore\Generated Files\sources\MainPage.h et MainPage.cpp).The project won't entirely succeed in building yet, but building now is a useful thing to do because it regenerates the source code files in which the MainPage runtime class is implemented (\Bookstore\Bookstore\Generated Files\sources\MainPage.h and MainPage.cpp). Continuons et générons le projet maintenant.So go ahead and build now. L’erreur de build à laquelle vous pouvez vous attendre à ce stade est 'MainViewModel': n’est pas membre de 'winrt::Bookstore::implementation::MainPage' .The build error you can expect to see at this stage is 'MainViewModel': is not a member of 'winrt::Bookstore::implementation::MainPage'.

Si vous omettez l’inclure BookstoreViewModel.idl (voir le listingMainPage.idl ci-dessus), vous verrez l’erreur attendu < près de « MainViewModel » .If you omit the include of BookstoreViewModel.idl (see the listing of MainPage.idl above), then you'll see the error expecting < near "MainViewModel". Une autre astuce consiste à vérifier que vous conservez tous les types dans le même espace de noms : l’espace de noms indiqué dans les listings de code.Another tip is to make sure that you leave all types in the same namespace—the namespace that's shown in the code listings.

Pour résoudre l’erreur que nous devrions voir, vous devez maintenant copier les stubs accesseur de la propriété MainViewModel à partir des fichiers générés (\Bookstore\Bookstore\Generated Files\sources\MainPage.h et MainPage.cpp) et dans \Bookstore\Bookstore\MainPage.h et MainPage.cpp.To resolve the error that we expect to see, you'll now need to copy the accessor stubs for the MainViewModel property out of the generated files (\Bookstore\Bookstore\Generated Files\sources\MainPage.h and MainPage.cpp) and into \Bookstore\Bookstore\MainPage.h and MainPage.cpp. Les étapes à suivre sont décrites ci-après.The steps to do that are described next.

Dans \Bookstore\Bookstore\MainPage.h, effectuez les étapes suivantes.In \Bookstore\Bookstore\MainPage.h, perform these steps.

  • Incluez BookstoreViewModel.h, qui déclare le type d’implémentation pour BookstoreViewModel (c’est-à-dire winrt::Bookstore::implementation::BookstoreViewModel).Include BookstoreViewModel.h, which declares the implementation type for BookstoreViewModel (which is winrt::Bookstore::implementation::BookstoreViewModel).
  • Ajoutez un membre privé pour stocker le modèle d’affichage.Add a private member to store the view model. Notez que la fonction d’accesseur de propriété (et le membre m_mainViewModel) sont implémentés en termes de type projeté pour BookstoreViewModel (c’est-à-dire Bookstore::BookstoreViewModel).Note that the property accessor function (and the member m_mainViewModel) is implemented in terms of the projected type for BookstoreViewModel (which is Bookstore::BookstoreViewModel).
  • Le type d’implémentation se trouvant dans le même projet (unité de compilation) que l’application, nous construisons m_mainViewModel par le biais de la surcharge du constructeur qui accepte std::nullptr_t.The implementation type is in the same project (compilation unit) as the application, so we construct m_mainViewModel via the constructor overload that takes std::nullptr_t.
  • Supprimez la propriété MyProperty.Remove the MyProperty property.

Notes

Dans les deux listings ci-dessous pour MainPage.h et MainPage.cpp, le code illustre la façon par défaut de construire le membre de données m_mainViewModel.In the pair of listings below for MainPage.h and MainPage.cpp, the code illustrates the default way of constructing the m_mainViewModel data member. Dans la section qui suit, nous allons montrer une version qui utilise la construction uniforme à la place.In the section that follows, we'll show a version that uses uniform construction instead.

// MainPage.h
...
#include "BookstoreViewModel.h"
...
namespace winrt::Bookstore::implementation
{
    struct MainPage : MainPageT<MainPage>
    {
        MainPage();

        Bookstore::BookstoreViewModel MainViewModel();

        void ClickHandler(Windows::Foundation::IInspectable const&, Windows::UI::Xaml::RoutedEventArgs const&);

    private:
        Bookstore::BookstoreViewModel m_mainViewModel{ nullptr };
    };
}
...

Apportez les modifications suivantes à \Bookstore\Bookstore\MainPage.cpp en vous reportant au listing plus bas.In \Bookstore\Bookstore\MainPage.cpp, as shown in the listing below, make the following changes.

  • Appelez winrt::make (avec le type d’implémentation BookstoreViewModel) pour attribuer une nouvelle instance du type projeté BookstoreViewModel à m_mainViewModel.Call winrt::make (with the BookstoreViewModel implementation type) to assign a new instance of the projected BookstoreViewModel type to m_mainViewModel. Comme nous l’avons vu plus haut, le constructeur BookstoreViewModel crée un objet BookSku comme membre de données privé en lui attribuant initialement le titre L"Atticus".As we saw above, the BookstoreViewModel constructor creates a new BookSku object as a private data member, setting its title initially to L"Atticus".
  • Dans le gestionnaire d’événements du bouton (ClickHandler), mettez à jour le titre du livre en spécifiant le titre publié.In the button's event handler (ClickHandler), update the book's title to its published title.
  • Implémentez l’accesseur pour la propriété MainViewModel.Implement the accessor for the MainViewModel property.
  • Supprimez la propriété MyProperty.Remove the MyProperty property.
// MainPage.cpp
#include "pch.h"
#include "MainPage.h"
#include "MainPage.g.cpp"

using namespace winrt;
using namespace Windows::UI::Xaml;

namespace winrt::Bookstore::implementation
{
    MainPage::MainPage()
    {
        m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();
        InitializeComponent();
    }

    void MainPage::ClickHandler(Windows::Foundation::IInspectable const& /* sender */, Windows::UI::Xaml::RoutedEventArgs const& /* args */)
    {
        MainViewModel().BookSku().Title(L"To Kill a Mockingbird");
    }

    Bookstore::BookstoreViewModel MainPage::MainViewModel()
    {
        return m_mainViewModel;
    }
}

Construction uniformeUniform construction

Pour utiliser la construction uniforme au lieu de winrt::make, dans MainPage.h, déclarez et initialisez m_mainViewModel en une seule étape, comme indiqué ci-dessous.To use uniform construction instead of winrt::make, in MainPage.h declare and initialize m_mainViewModel in just one step, as shown below.

// MainPage.h
...
#include "BookstoreViewModel.h"
...
struct MainPage : MainPageT<MainPage>
{
    ...
private:
    Bookstore::BookstoreViewModel m_mainViewModel;
};
...

Ensuite, dans le constructeur MainPage utilisé dans MainPage.cpp, le code m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>(); n’est pas nécessaire.And then, in the MainPage constructor in MainPage.cpp, there's no need for the code m_mainViewModel = winrt::make<Bookstore::implementation::BookstoreViewModel>();.

Pour obtenir plus d’informations sur la construction uniforme et des exemples de code, consultez Accepter la construction uniforme et l’accès direct à l’implémentation.For more info about uniform construction, and code examples, see Opt in to uniform construction, and direct implementation access.

Lier le bouton à la propriété TitleBind the button to the Title property

Ouvrez MainPage.xaml, qui contient le balisage XAML pour notre page d’interface utilisateur principale.Open MainPage.xaml, which contains the XAML markup for our main UI page. Comme indiqué dans le listing ci-dessous, supprimez le nom du bouton et modifiez la valeur de sa propriété Content d’une chaîne littérale à une expression de liaison.As shown in the listing below, remove the name from the button, and change its Content property value from a literal to a binding expression. Notez la propriété Mode=OneWay sur l’expression de liaison (à sens unique, du modèle d’affichage vers l’interface utilisateur).Note the Mode=OneWay property on the binding expression (one-way from the view model to the UI). Sans cette propriété, l’interface utilisateur ne répondra pas aux événements de modification de propriété.Without that property, the UI will not respond to property changed events.

<Button Click="ClickHandler" Content="{x:Bind MainViewModel.BookSku.Title, Mode=OneWay}"/>

Lancez à présent le processus de génération et exécutez le projet.Now build and run the project. Cliquez sur le bouton pour exécuter le gestionnaire d’événements Click.Click the button to execute the Click event handler. Ce gestionnaire appelle la fonction mutateur du titre du livre ; ce mutateur déclenche un événement pour informer l’interface utilisateur que la propriété Title a été modifiée ; et le bouton réinterroge la valeur de cette propriété pour mettre à jour sa propre valeur Content.That handler calls the book's title mutator function; that mutator raises an event to let the UI know that the Title property has changed; and the button re-queries that property's value to update its own Content value.

Utilisation de l’extension de balisage {Binding} avec C++/WinRTUsing the {Binding} markup extension with C++/WinRT

Pour la version actuellement publiée de C++/WinRT, pour pouvoir utiliser l’extension de balisage {Binding}, vous devrez implémenter les interfaces ICustomPropertyProvider et ICustomProperty.For the currently released version of C++/WinRT, in order to be able to use the {Binding} markup extension you'll need to implement the ICustomPropertyProvider and ICustomProperty interfaces.

Liaison d’élément à élémentElement-to-element binding

Vous pouvez lier la propriété d’un élément XAML à celle d’un autre élément XAML.You can bind the property of one XAML element to the property of another XAML element. Voici un exemple qui illustre cette opération dans le balisage.Here's an example of how that looks in markup.

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

Vous devez déclarer l’entité XAML nommée myTextBox comme propriété en lecture seule dans votre fichier Midl (.idl).You'll need to declare the named XAML entity myTextBox as a read-only property in your Midl file (.idl).

// MainPage.idl
runtimeclass MainPage : Windows.UI.Xaml.Controls.Page
{
    MainPage();
    Windows.UI.Xaml.Controls.TextBox myTextBox{ get; };
}

La raison est la suivante :Here's the reason for this necessity. tous les types que le compilateur XAML doit valider (notamment ceux utilisés dans {x:Bind}) sont lus à partir de métadonnées Windows (WinMD).All types that the XAML compiler needs to validate (including those used in {x:Bind}) are read from Windows Metadata (WinMD). Il vous suffit donc d’ajouter la propriété en lecture seule à votre fichier Midl.All you need to do is to add the read-only property to your Midl file. Ne l’implémentez pas, car le code-behind XAML généré automatiquement fournit l’implémentation pour vous.Don't implement it, because the autogenerated XAML code-behind provides the implementation for you.

Utilisation d’objets à partir du balisage XAMLConsuming objects from XAML markup

Toutes les entités utilisées via l’extension de balisage {x:Bind} XAML doivent être exposées publiquement dans IDL.All entities consumed by using the XAML {x:Bind} markup extension must be exposed publicly in IDL. De plus, si le balisage XAML contient une référence à un autre élément qui se trouve également dans un balisage, la méthode getter de ce balisage doit être présente dans IDL.Furthermore, if XAML markup contains a reference to another element that's also in markup, then the getter for that markup must be present in IDL.

<Page x:Name="MyPage">
    <StackPanel>
        <CheckBox x:Name="UseCustomColorCheckBox" Content="Use custom color"
             Click="UseCustomColorCheckBox_Click" />
        <Button x:Name="ChangeColorButton" Content="Change color"
            Click="{x:Bind ChangeColorButton_OnClick}"
            IsEnabled="{x:Bind UseCustomColorCheckBox.IsChecked.Value, Mode=OneWay}"/>
    </StackPanel>
</Page>

L’élément ChangeColorButton fait référence à l’élément UseCustomColorCheckBox via une liaison.The ChangeColorButton element refers to the UseCustomColorCheckBox element via binding. L’IDL de cette page doit donc déclarer une propriété en lecture seule intitulée UseCustomColorCheckBox pour qu’elle soit accessible à la liaison.So the IDL for this page must declare a read-only property named UseCustomColorCheckBox in order for it to be accessible to binding.

Le délégué du gestionnaire d’événements Click pour UseCustomColorCheckBox utilise la syntaxe de délégué XAML classique afin de ne pas avoir besoin d’une entrée dans l’IDL. Il doit simplement être public dans votre classe d’implémentation.The click event handler delegate for UseCustomColorCheckBox uses classic XAML delegate syntax, so that doesn't need an entry in the IDL; it just needs to be public in your implementation class. En revanche, ChangeColorButton possède également un gestionnaire d’événements Click {x:Bind} qui doit également être placé dans l’IDL.On the other hand, ChangeColorButton also has an {x:Bind} click event handler, which must also go into the IDL.

runtimeclass MyPage : Windows.UI.Xaml.Controls.Page
{
    MyPage();

    // These members are consumed by binding.
    void ChangeColorButton_OnClick();
    Windows.UI.Xaml.Controls.CheckBox UseCustomColorCheckBox{ get; };
}

Vous n’avez pas besoin de fournir une implémentation pour la propriété UseCustomColorCheckBox.You don't need to provide an implementation for the UseCustomColorCheckBox property. Le générateur de code XAML le fait pour vous.The XAML code generator does that for you.

Liaison à un booléenBinding to Boolean

Vous pouvez effectuer cette opération en mode Diagnostic.You might do this in a diagnostic mode.

true ou false s’affiche dans C++/CX, tandis que Windows.Foundation.IReference`1 s’affiche dans C++/WinRT.This shows true or false in C++/CX, but shows Windows.Foundation.IReference`1 in C++/WinRT.

Utilisez x:Bind lors de la liaison à un booléen.Use x:Bind when binding to a Boolean.

<TextBlock Text="{x:Bind CanPair}"/>

API importantesImportant APIs