可以有效地系結至 XAML 專案控件的集合稱為可觀察 集合。 這個概念是以稱為「Observer pattern」的軟體設計模式為基礎。 本主題說明如何在 C++/WinRT中實作可觀察的集合,以及如何將 XAML 專案控件系結至它們(如需背景資訊,請參閱 數據系結)。
如果您想要遵循本主題,建議您先建立 XAML 控件中所述的專案;繫結至 C++/WinRT 屬性。 本主題會將更多程式代碼新增至該專案,並新增至該主題中說明的概念。
這很重要
如需基本概念和術語,以幫助您理解如何使用 C++/WinRT 取用和撰寫執行階段類別,請參閱 使用 C++/WinRT 取用 API,以及 使用 C++/WinRT 撰寫 API。
可觀察的 對集合意味著什麼?
如果代表集合的執行階段類別選擇引發 IObservableVector<T>::VectorChanged 事件,每當元素被加入或移除時,那麼這個執行階段類別就是可觀察的集合。 XAML 專案控制項可以藉由擷取更新的集合,然後更新本身以顯示目前的元素,來系結及處理這些事件。
備註
如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 和 NuGet 套件的資訊(一起提供專案範本和建置支援),請參閱 Visual Studio 支援 C++/WinRT。
將 BookSkus 集合新增至 BookstoreViewModel
在 XAML 控制件中;系結至 C++/WinRT 屬性,我們在主要檢視模型中新增了類型為 BookSku 的屬性。 在此步驟中,我們將使用
在 BookstoreViewModel.idl中宣告新的屬性。
// BookstoreViewModel.idl
...
runtimeclass BookstoreViewModel
{
BookSku BookSku{ get; };
Windows.Foundation.Collections.IObservableVector<BookSku> BookSkus{ get; };
}
...
這很重要
使用 C++/WinRT 綁定到集合的方法比使用 C# 的方式更細緻一些。 在上述 MIDL 3.0 清單中,請注意,BookSkus 屬性的類型是 IObservableVector,包含 BookSku。 在本主題的下一節中,我們將將 ListBox 的專案來源系結至 BookSkus。 清單框是專案控件,若要正確設定 {x:Bind} 會產生 E_INVALIDARG,且 {Binding} 會以無訊息方式失敗。
警告
本主題中顯示的程式代碼適用於 C++/WinRT 2.0.190530.8 版或更新版本。 如果您使用舊版,則必須對所顯示的程式代碼進行一些次要調整。 在上述 MIDL 3.0 清單中,將 BookSkus 屬性變更為 IObservableVectorIInspectable。 然後在實作中使用 IInspectable (而非 BookSku)。
儲存並建置。 從 BookstoreViewModel.h 資料夾中的 BookstoreViewModel.cpp 和 \Bookstore\Bookstore\Generated Files\sources 複製存取器樣本(更多內容,請參閱前一主題,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 標記。 在與 Button相同的 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"));
}
...
現在建置並執行專案。 點擊按鈕來執行 點擊 事件處理程式。 我們看到 Append 的實作會引發事件,讓 UI 知道集合已變更,ListBox 重新查詢集合,以便更新其 Items 值。 就像以前一樣,其中一本書的標題也發生了變化:且標題變更會同時反映在按鈕和清單框中。