共用方式為


XAML 項目控制項;綁定至 C++/WinRT 集合

可以有效地系結至 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 的屬性。 在此步驟中,我們將使用 winrt::single_threaded_observable_vector Factory 函式範本,協助我們在相同的檢視模型中實作可觀察的 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。 清單框是專案控件,若要正確設定 ItemsControl.ItemsSource 屬性,您必須將它設定為 IObservableVector類型 值,或 IVector,或是 IBindableObservableVector等互操作性類型的值。 否則, {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 值。 就像以前一樣,其中一本書的標題也發生了變化:且標題變更會同時反映在按鈕和清單框中。

重要 API