XAML-Itemssteuerelemente; Bindung an eine C++/WinRT-Sammlung

Eine Sammlung, die sich problemlos an ein XAML-ItemsControl binden lässt, wird als observable-Auflistung bezeichnet. Diese Idee basiert auf dem Softwaredesignmuster, das als Beobachtermuster bezeichnet wird. In diesem Thema wird gezeigt, wie Observable-Auflistungen in C++/WinRT implementiert werden und wie XAML-Elementsteuerelemente an sie gebunden werden (informationen zu Hintergrundinformationen finden Sie unter "Datenbindung").

Wenn Sie diesem Thema Schritt für Schritt folgen möchten, empfehlen wir, zunächst das in XAML-Steuerelemente; Bindung an eine C++/WinRT-Eigenschaft beschriebene Projekt zu erstellen. Dieses Thema fügt diesem Projekt zusätzlichen Code hinzu und baut auf den in jenem Thema erläuterten Konzepten auf.

Important

Wichtige Konzepte und Begriffe, die Ihr Verständnis für die Nutzung und Erstellung von Laufzeitklassen mit C++/WinRT unterstützen, finden Sie unter Verwenden von APIs mit C++/WinRT und Erstellen von APIs mit C++/WinRT.

Was bedeutet observable für eine Sammlung?

Wenn eine Laufzeitklasse, die eine Auflistung darstellt, das IObservableVector<T>::VectorChanged-Ereignis auslöst, wenn ein Element hinzugefügt oder daraus entfernt wird, ist die Laufzeitklasse eine observable Auflistung. Ein XAML-ItemsControl kann an diese Ereignisse gebunden werden und sie verarbeiten, indem es die aktualisierte Sammlung abruft und sich dann selbst aktualisiert, um die aktuellen Elemente anzuzeigen.

Hinweis

Informationen zum Installieren und Verwenden der C++/WinRT Visual Studio Extension (VSIX) und des NuGet-Pakets (die zusammen Projektvorlage und Buildunterstützung bereitstellen), finden Sie unter Visual Studio Unterstützung für C++/WinRT.

Hinzufügen einer BookSkus-Auflistung zu BookstoreViewModel

In XAML-Steuerelementen; Binden an eine C++/WinRT-Eigenschaft haben wir dem Hauptansichtsmodell eine Eigenschaft vom Typ BookSku hinzugefügt. In diesem Schritt verwenden wir die Factoryfunktionsvorlage winrt::single_threaded_observable_vector, um im selben Ansichtsmodell eine beobachtbare Sammlung von BookSku zu implementieren.

Deklarieren Sie eine neue Eigenschaft in BookstoreViewModel.idl.

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

Important

Die Bindung an eine Sammlung mit C++/WinRT ist etwas differenzierter als bei C#. Beachten Sie in der oben aufgeführten MIDL 3.0-Auflistung, dass der Typ der BookSkus-EigenschaftIObservableVector von BookSku ist. Im nächsten Abschnitt dieses Themas werden wir die ItemsSource-Eigenschaft eines ListBox an BookSkus binden. Ein Listenfeld ist ein Elementsteuerelement und zum ordnungsgemäßen Festlegen der ItemsControl.ItemsSource-Eigenschaft müssen Sie es auf einen Wert vom Typ "IObservableVector" oder "IVector" oder einen Interoperabilitätstyp wie "IBindableObservableVector" festlegen. Andernfalls gibt {x:Bind}E_INVALIDARG zurück, und {Binding} schlägt stillschweigend fehl.

Warnung

Der in diesem Thema gezeigte Code gilt für C++/WinRT, Version 2.0.190530.8 oder höher. Wenn Sie eine frühere Version verwenden, müssen Sie einige kleinere Optimierungen an dem angezeigten Code vornehmen. Ändern Sie in der oben aufgeführten MIDL 3.0-Auflistung die BookSkus-Eigenschaft in IObservableVector von IInspectable. Verwenden Sie dann auch IInspectable (anstelle von BookSku) in Ihrer Implementierung.

Speichern und Erstellen. Kopieren Sie die Accessorstubs aus BookstoreViewModel.h und BookstoreViewModel.cpp in den Ordner \Bookstore\Bookstore\Generated Files\sources (weitere Details finden Sie im vorherigen Thema XAML-Steuerelemente; an eine C++/WinRT-Eigenschaft binden). Implementieren Sie diese Accessor-Stubs folgendermaßen.

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

Binden eines ListBox-Objekts an die BookSkus-Eigenschaft

Öffne MainPage.xaml. Darin befindet sich das XAML-Markup für unsere UI-Hauptseite. Fügen Sie das folgende Markup innerhalb desselben StackPanel-Elements wie die Schaltfläche hinzu.

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

MainPage.cppFügen Sie dem Click-Ereignishandler eine Codezeile hinzu, um ein Buch an die Auflistung anzufügen.

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

Erstellen Sie nun das Projekt und führen Sie es aus. Klicken Sie auf die Schaltfläche, um den Click-Event-Handler auszuführen. Wir haben gesehen, dass die Implementierung von Append ein Ereignis auslöst, um die Benutzeroberfläche darüber zu informieren, dass sich die Sammlung geändert hat; und das ListBox fragt die Auflistung erneut ab, um ihren eigenen Items-Wert zu aktualisieren. Genau wie zuvor ändert sich der Titel eines der Bücher; und diese Titeländerung wird sowohl auf der Schaltfläche als auch im Listenfeld widergespiegelt.

Wichtige APIs