XAML 項目控制項;繫結至一個 C++/WinRT 集合

可有效地繫結至 XAML 項目控制項的集合稱為「可觀察的」集合。 這個主意是以軟體設計模式為基礎稱為觀察者模式。 本主題顯示在 C++/WinRT 中實作可觀察集合,以及將 XAML 項目繫結至這些集合的方法 (如需背景資訊,請參閱資料繫結)。

如果您想要按照本主題的步驟進行,建議先建立 XAML 控制項;繫結一個 C++/WinRT 屬性一文所述的專案。 本主題會將更多程式碼加入至該專案,且能進一步輔助本主題所介紹的概念。

重要

如需支援您了解如何使用 C++/WinRT 使用及撰寫執行階段類別的基本概念和詞彙,請參閱使用 C++/WinRT 使用 API使用 C++/WinRT 撰寫 API

對一個集合來說,「可觀察」有何意義?

如果代表集合的執行階段類別,每當將元素新增至該類別或從中移除時,會選擇引發 IObservableVector<T>::VectorChanged 事件,則該執行階段類別便是可觀察的集合。 XAML 項目控制項藉由擷取更新的集合並且更新其本身以顯示目前的元素,可繫結至以及處理這些事件。

注意

如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 與 NuGet 套件 (一起提供專案範本和建置支援) 的資訊,請參閱 C++/WinRT 的 Visual Studio 支援

BookSkus 集合新增至 BookstoreViewModel

XAML 控制項;繫結至 C++/WinRT 屬性 中,我們已將類型 BookSku 的屬性新增至我們主要的檢視模型。 在此步驟,我們會使用 winrt::single_threaded_observable_vector 原廠函式範本,協助我們在相同的檢視模型上實作 BookSku 的可觀察集合。

BookstoreViewModel.idl 中宣告一個新的屬性。

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

注意

在上述的 MIDL 3.0 清單中,請注意,BookSkus 屬性的類別是 BookSkuIObservableVector。 在本主題的下一節中,我們會將 ListBox 的項目來源繫結至 BookSkus。 清單方塊是項目控制項,若要正確設定 ItemsControl.ItemsSource 屬性,您需要將它設定為 IObservableVectorIVector 類型的值,或互通性類型值,例如 IBindableObservableVector

警告

本主題中所顯示的程式碼適用於 C++/WinRT 版本 2.0.190530.8 和更新版本。 如果您使用較早版本,則需要對顯示的程式碼進行一些微幅調整。 在上述的 MIDL 3.0 清單中,將 BookSkus 屬性變更為 IInspectableIObservableVector。 然後在您的實作中也使用 IInspectable (而非 BookSku)。

儲存並建置。 複製 \Bookstore\Bookstore\Generated Files\sources 資料夾之中 BookstoreViewModel.hBookstoreViewModel.cpp 的存取子虛設常式 (如需詳細資訊,請參閱先前的主題 XAML 控制項,繫結至 C++/WinRT 屬性)。 實作像這樣的這些存取子虛設常式。

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

將一個 ListBox 繫結至 BookSkus 屬性

開啟 MainPage.xaml,其中包含我們主要 UI 頁面的 XAML 標記。 在相同的 StackPanel 中新增下列標記做為按鈕

<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.cpp 中,將一行程式碼新增至 Click 事件處理常式,將一本書附加至集合。

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

現在請建置並執行專案。 按一下按鈕執行 Click 事件處理常式。 我們所見 Append 的實作引發一個事件,讓 UI 知道集合已變更;且 ListBox 重新查詢集合,更新其自己的 Items 值。 就像以前一樣,變更書籍其中之一的標題;且同時在按鈕與清單方塊上反映該標題的變更。

重要 API