XAML-objektkontroller; binda till en C++/WinRT-samling

En samling som effektivt kan bindas till en XAML-objektkontroll kallas för en observerbar samling. Den här idén baseras på det programvarudesignmönster som kallas observatörsmönster. Det här avsnittet visar hur du implementerar observerbara samlingar i C++/WinRT och hur du binder XAML-objektkontroller till dem (för bakgrundsinformation, se Databindning).

Om du vill följa med i det här avsnittet rekommenderar vi att du först skapar projektet som beskrivs i XAML-kontroller. Bind till en C++/WinRT-egenskap. Det här avsnittet lägger till mer kod i projektet och lägger till begreppen som beskrivs i det ämnet.

Viktigt!

Viktiga begrepp och termer som stöder din förståelse av hur du använder och skapar körningsklasser med C++/WinRT finns i Använda API:er med C++/WinRT och Redigerings-API:er med C++/WinRT.

Vad betyder observerbar för en samling?

Om en körningsklass som representerar en samling väljer att höja IObservableVector<T>::VectorChanged-händelsen när ett element läggs till i den eller tas bort från den, är körningsklassen en observerbar samling. En XAML-objektkontroll kan binda till och hantera dessa händelser genom att hämta den uppdaterade samlingen och sedan uppdatera sig själv för att visa de aktuella elementen.

Note

Information om hur du installerar och använder VSIX (C++/WinRT Visual Studio Extension) och NuGet-paketet (som tillsammans tillhandahåller projektmall och byggstöd) finns i Visual Studio support för C++/WinRT.

Lägga till en BookSkus-samling i BookstoreViewModel

I XAML-kontroller, bind till en C++/WinRT-egenskap, lade vi till en egenskap av typen BookSku till vår huvudvymodell. I det här steget kommer vi att använda fabrikfunktionsmallen winrt::single_threaded_observable_vector för att hjälpa oss att implementera en observerbar samling av BookSku i samma vymodell.

Deklarera en ny egenskap i BookstoreViewModel.idl.

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

Viktigt!

Bindning till en samling med C++/WinRT är lite mer nyanserad än med C#. I MIDL 3.0-listan ovan bör du tänka på att typen av bookskus-egenskapen är IObservableVector för BookSku. I nästa avsnitt i det här avsnittet ska vi binda objektkällan för en ListBox till BookSkus. En listruta är en objektkontroll, och för att korrekt ställa in egenskapen ItemsControl.ItemsSource måste du ange den till ett värde av typen IObservableVector, IVector eller av en samverkanstyp som IBindableObservableVector. Annars {x:Bind} genererar E_INVALIDARG och {Binding} misslyckas tyst.

Varning

Koden som visas i det här avsnittet gäller för C++/WinRT version 2.0.190530.8 eller senare. Om du använder en tidigare version måste du göra några mindre justeringar av koden som visas. I MIDL 3.0-listan ovan ändrar du egenskapen BookSkus till IObservableVector för IInspectable. Och sedan använda IInspectable (i stället för BookSku) i din implementering också.

Spara och skapa. Kopiera åtkomststubbarna från BookstoreViewModel.h och BookstoreViewModel.cpp i mappen \Bookstore\Bookstore\Generated Files\sources (mer information finns i föregående avsnitt, XAML-kontroller; bind till en C++/WinRT-egenskap). Implementera dessa åtkomststubbar så här.

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

Binda en ListBox till egenskapen BookSkus

Öppna MainPage.xaml, som innehåller XAML-markering för vår huvudsida för användargränssnittet. Lägg till följande markering i samma StackPanel som knappen.

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

I MainPage.cpplägger du till en kodrad i händelsehanteraren Klicka för att lägga till en bok i samlingen.

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

Skapa och kör nu projektet. Klicka på knappen för att köra Click-händelsehanteraren. Vi såg att implementeringen av Append utlöser en händelse för att meddela användargränssnittet att samlingen har ändrats; och ListBox frågar samlingen på nytt för att uppdatera sitt eget Items-värde. Precis som tidigare ändras titeln på en av böckerna; och att rubrikändringen återspeglas både på knappen och i listrutan.

Viktiga API:er