Controlli di elementi XAML, binding a una raccolta C++/WinRT

Una raccolta di cui è possibile eseguire in modo efficace il binding a un controllo di elementi XAML è nota come raccolta osservabile. Questo concetto è basato sul modello di progettazione del software noto come modello osservatore. Questo argomento illustra come implementare raccolte osservabili in C++/WinRT e come eseguire il binding a controlli di elementi XAML. Per informazioni generali, vedi Data binding.

Se si desidera proseguire con questo argomento, è consigliabile creare innanzitutto il progetto descritto in Controlli XAML; binding a una proprietà C++/WinRT. Questo argomento aggiunge altro codice al progetto e completa i concetti illustrati in quell'argomento.

Importante

Per i concetti essenziali e i termini che possono aiutarti a comprendere come usare e creare classi di runtime con C++/WinRT, vedi Usare API con C++/WinRT e Creare API con C++/WinRT.

Cosa vuol dire osservabile in riferimento a una raccolta?

Se una classe di runtime che rappresenta una raccolta prevede la generazione dell'evento IObservableVector<T>::VectorChanged ogni volta che viene eseguita l'aggiunta o la rimozione di un elemento, la classe di runtime è una raccolta osservabile. Si può eseguire il binding di un controllo di elementi XAML a tali eventi in modo che li gestisca recuperando la raccolta aggiornata e poi si aggiorni per mostrare gli elementi correnti.

Nota

Per informazioni sull'installazione e sull'uso dell'Estensione C++/WinRT per Visual Studio (VSIX) e del pacchetto NuGet, che insieme forniscono il modello di progetto e il supporto della compilazione, vedi Supporto di Visual Studio per C++/WinRT.

Aggiungere una raccolta BookSkus a BookstoreViewModel

Nella sezione Controlli XAML, binding a una proprietà C++/WinRT abbiamo aggiunto una proprietà di tipo BookSku al nostro modello di visualizzazione principale. In questo passaggio useremo la funzione factory winrt::single_threaded_observable_vector per implementare una raccolta osservabile di BookSku sullo stesso modello di visualizzazione.

Dichiara una nuova proprietà in BookstoreViewModel.idl.

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

Nota

Nel listato MIDL 3.0 precedente puoi notare che il tipo della proprietà BookSkus è IObservableVector di BookSku. Nella sezione successiva di questo argomento eseguiremo il binding dell'origine degli elementi di un ListBox a BookSkus. Una casella di riepilogo è un controllo di elementi e per impostare correttamente la proprietà ItemsControl.ItemsSource devi impostarla su un valore di tipo IObservableVector o IVector o di un tipo di interoperabilità, ad esempio IBindableObservableVector.

Avviso

Il codice illustrato in questo argomento si applica a C++/WinRT versione 2.0.190530.8 o successiva. Se usi una versione precedente, dovrai apportare alcune piccole modifiche al codice illustrato. Nel listato MIDL 3.0 precedente, modifica la proprietà BookSkus in IObservableVector di IInspectable. Usa quindi IInspectable (anziché BookSku) anche nella tua implementazione.

Salva ed esegui la compilazione. Copia gli stub di funzioni di accesso da BookstoreViewModel.h e BookstoreViewModel.cpp nella cartella \Bookstore\Bookstore\Generated Files\sources; per altri dettagli, vedi l'argomento precedente, Controlli XAML, binding a una proprietà C++/WinRT. Implementa tali stub di funzioni di accesso in questo modo.

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

Eseguire il binding di ListBox alla proprietà BookSkus

Apri MainPage.xaml, che contiene il markup XAML per la nostra pagina dell'interfaccia utente principale. Aggiungi il markup seguente nello stesso StackPanel di 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>

In MainPage.cpp aggiungi una riga di codice al gestore eventi Click per aggiungere un libro alla raccolta.

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

A questo punto compila ed esegui il progetto. Fai clic sul pulsante per eseguire il gestore eventi Click. Abbiamo visto che l'implementazione di Append genera un evento per segnalare all'interfaccia utente che la raccolta è stata modificata. ListBox esegue di nuovo una query sulla raccolta per aggiornare il proprio valore Items. Proprio come in precedenza, il titolo di uno dei libri cambia e tale modifica al titolo viene riflessa nel pulsante e nella casella di riepilogo.

API importanti