XAML-Elementsteuerelemente: Binden an eine C++/WinRT-Sammlung

Eine Sammlung, die effektiv an ein XAML-Elementsteuerelement gebunden werden kann, wird als Observable-Sammlung bezeichnet. Dieses Konzept basiert auf dem Softwareentwurfsmuster, das als Beobachter-Muster bekannt ist. In diesem Thema erfährst du, wie du beobachtbare Sammlungen in C++/WinRT implementierst und Steuerelemente für XAML-Elemente an sie bindest (Hintergrundinformationen findest Du unter Datenbindung).

Zur besseren Nachvollziehbarkeit dieses Themas empfiehlt es sich, zuerst das unter XAML-Steuerelemente: Binden an eine C++/WinRT-Eigenschaft beschriebene Projekt zu erstellen. In diesem Thema wird dem Projekt weiterer Code hinzugefügt, und es werden weitere Konzepte erläutert.

Wichtig

Wichtige Konzepte und Begriffe im Zusammenhang mit der Nutzung und Erstellung von Laufzeitklassen mit C++/WinRT findest du unter Verwenden von APIs mit C++/WinRT sowie unter Erstellen von APIs mit C++/WinRT.

Was bedeutet beobachtbar für eine Sammlung?

Wenn eine Laufzeitklasse, die eine Sammlung darstellt, das Ereignis IObservableVector<T>::VectorChanged auslöst, sobald ihr ein Element hinzugefügt oder ein Element daraus entfernt wird, ist die Laufzeitklasse eine beobachtbare Sammlung. Ein XAML-Elementsteuerelement kann an diese Ereignisse gebunden werden und sie behandeln, indem es die aktualisierte Sammlung abruft und sich anschließend selbst aktualisiert, um die aktuellen Elemente anzuzeigen.

Hinweis

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

Hinzufügen einer Sammlung vom Typ BookSkus zu BookstoreViewModel

In XAML-Steuerelemente: Binden an eine C++/WinRT-Eigenschaft haben wir unserem Hauptansichtsmodell eine Eigenschaft vom Typ BookSku hinzugefügt. In diesem Schritt verwenden wir die Factoryfunktionsvorlage winrt::single_threaded_observable_vector, um auf der Grundlage des gleichen Ansichtsmodells eine beobachtbare Sammlung von BookSku zu implementieren.

Deklariere eine neue Eigenschaft in BookstoreViewModel.idl.

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

Hinweis

Wie in der obigen MIDL 3.0-Auflistung zu sehen, handelt es sich beim Typ der Eigenschaft BookSkus um IObservableVector von BookSku. Im nächsten Abschnitt dieses Themas binden wir die Elementquelle eines Listenfelds (ListBox an BookSkus. Ein Listenfeld ist ein Elementsteuerelement. Die Eigenschaft ItemsControl.ItemsSource muss daher auf einen Wert vom Typ IObservableVector oder IVector festgelegt werden – oder auf einen Interoperabilitätstyp wie IBindableObservableVector.

Warnung

Der in diesem Thema gezeigt Code gilt für C++/WinRT, Version 2.0.190530.8 oder höher. Wenn Sie eine frühere Version verwenden, müssen einige geringe Anpassungen am dargestellten Code vornehmen. Ändern Sie in der obigen MIDL 3.0-Auflistung die Eigenschaft BookSkus in IObservableVector von IInspectable. Verwenden Sie dann IInspectable (anstelle von BookSku) auch in Ihrer Implementierung.

Speichere, und führe den Buildvorgang aus. Kopiere die Accessor-Stubs aus BookstoreViewModel.h und BookstoreViewModel.cpp in den Ordner \Bookstore\Bookstore\Generated Files\sources. (Ausführlichere Informationen findest du im vorherigen Thema XAML-Steuerelemente: Binden an eine C++/WinRT-Eigenschaft.) Implementiere diese Accessor-Stubs wie folgt:

// 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 Listenfelds an die Eigenschaft BookSkus

Öffne MainPage.xaml. Darin befindet sich das XAML-Markup für unsere UI-Hauptseite. Füge das folgende Markup innerhalb des gleichen StackPanel-Elements hinzu wie die Schaltfläche (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>

Füge in MainPage.cpp dem Ereignishandler für Click eine Codezeile hinzu, um am Ende der Sammlung ein Buch hinzuzufü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"));
}
...

Erstelle nun das Projekt, und führe es aus. Klicke auf die Schaltfläche, um den Ereignishandler für Click auszuführen. Wir haben gesehen, dass die Implementierung von Append ein Ereignis auslöst, um die Benutzeroberfläche darauf hinzuweisen, dass sich die Sammlung geändert hat, und dass das Listenfeld (ListBox) die Sammlung erneut abfragt, um ihren eigenen Wert vom Typ Items 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 angezeigt.

Wichtige APIs