XAML 項目控制項;繫結至一個 C++/WinRT 集合XAML items controls; bind to a C++/WinRT collection

可有效地繫結至 XAML 項目控制項的集合稱為「可觀察的」 集合。A collection that can be effectively bound to a XAML items control is known as an observable collection. 這個主意是以軟體設計模式為基礎稱為觀察者模式This idea is based on the software design pattern known as the observer pattern. 本主題顯示在 C++/WinRT 中實作可觀察集合,以及將 XAML 項目繫結至這些集合的方法 (如需背景資訊,請參閱資料繫結)。This topic shows how to implement observable collections in C++/WinRT, and how to bind XAML items controls to them (for background info, see Data binding).

如果您想要按照本主題的步驟進行,建議先建立 XAML 控制項;繫結一個 C++/WinRT 屬性一文所述的專案。If you want to follow along with this topic, then we recommend that you first create the project that's described in XAML controls; bind to a C++/WinRT property. 本主題會將更多程式碼加入至該專案,且能進一步輔助本主題所介紹的概念。This topic adds more code to that project, and it adds to the concepts explained in that topic.

重要

如需支援您了解如何使用 C++/WinRT 使用及撰寫執行階段類別的基本概念和詞彙,請參閱使用 C++/WinRT 使用 API使用 C++/WinRT 撰寫 APIFor essential concepts and terms that support your understanding of how to consume and author runtime classes with C++/WinRT, see Consume APIs with C++/WinRT and Author APIs with C++/WinRT.

對一個集合來說,「可觀察」 有何意義?What does observable mean for a collection?

如果代表集合的執行階段類別,每當將元素新增至該類別或從中移除時,會選擇引發 IObservableVector<T>::VectorChanged 事件,則該執行階段類別便是可觀察的集合。If a runtime class that represents a collection chooses to raise the IObservableVector<T>::VectorChanged event whenever an element is added to it or removed from it, then the runtime class is an observable collection. XAML 項目控制項藉由擷取更新的集合並且更新其本身以顯示目前的元素,可繫結至以及處理這些事件。A XAML items control can bind to, and handle, these events by retrieving the updated collection and then updating itself to show the current elements.

注意

如需安裝和使用 C++/WinRT Visual Studio 延伸模組 (VSIX) 與 NuGet 套件 (一起提供專案範本和建置支援) 的資訊,請參閱 C++/WinRT 的 Visual Studio 支援For info about installing and using the C++/WinRT Visual Studio Extension (VSIX) and the NuGet package (which together provide project template and build support), see Visual Studio support for C++/WinRT.

BookSkus 集合新增至 BookstoreViewModelAdd a BookSkus collection to BookstoreViewModel

XAML 控制項;繫結至 C++/WinRT 屬性 中,我們已將類型 BookSku 的屬性新增至我們主要的檢視模型。In XAML controls; bind to a C++/WinRT property, we added a property of type BookSku to our main view model. 在此步驟,我們會使用 winrt::single_threaded_observable_vector 原廠函式範本,協助我們在相同的檢視模型上實作 BookSku 的可觀察集合。In this step, we'll use the winrt::single_threaded_observable_vector factory function template to help us implement an observable collection of BookSku on the same view model.

BookstoreViewModel.idl 中宣告一個新的屬性。Declare a new property in BookstoreViewModel.idl.

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

注意

在上述的 MIDL 3.0 清單中,請注意,BookSkus 屬性的類別是 BookSkuIObservableVectorIn the MIDL 3.0 listing above, note that the type of the BookSkus property is IObservableVector of BookSku. 在本主題的下一節中,我們會將 ListBox 的項目來源繫結至 BookSkusIn the next section of this topic, we'll be binding the items source of a ListBox to BookSkus. 清單方塊是項目控制項,若要正確設定 ItemsControl.ItemsSource 屬性,您需要將它設定為 IObservableVectorIVector 類型的值,或互通性類型值,例如 IBindableObservableVectorA list box is an items control, and to correctly set the ItemsControl.ItemsSource property, you need to set it to a value of type IObservableVector, or IVector, or of an interoperability type such as IBindableObservableVector.

警告

本主題中所顯示的程式碼適用於 C++/WinRT 版本2.0.190530.8 和更新版本。The code shown in this topic applies to C++/WinRT version 2.0.190530.8 and higher. 如果您使用較早版本,則需要對顯示的程式碼進行一些微幅調整。If you're using an earlier version, then you'll need to make some minor tweaks to the code shown. 在上述的 MIDL 3.0 清單中,將 BookSkus 屬性變更為 IInspectableIObservableVectorIn the MIDL 3.0 listing above, change the BookSkus property to IObservableVector of IInspectable. 然後在您的實作中也使用 IInspectable (而非 BookSku)。And then use IInspectable (instead of BookSku) in your implementation, too.

儲存並建置。Save and build. 複製 \Bookstore\Bookstore\Generated Files\sources 資料夾之中 BookstoreViewModel.hBookstoreViewModel.cpp 的存取子虛設常式 (如需詳細資訊,請參閱先前的主題 XAML 控制項,繫結至 C++/WinRT 屬性)。Copy the accessor stubs from BookstoreViewModel.h and BookstoreViewModel.cpp in the \Bookstore\Bookstore\Generated Files\sources folder (for more details, see the previous topic, XAML controls; bind to a C++/WinRT property). 實作像這樣的這些存取子虛設常式。Implement those accessor stubs like this.

// 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 屬性Bind a ListBox to the BookSkus property

開啟 MainPage.xaml,其中包含我們主要 UI 頁面的 XAML 標記。Open MainPage.xaml, which contains the XAML markup for our main UI page. 在相同的 StackPanel 中新增下列標記做為按鈕Add the following markup inside the same StackPanel as the 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>

MainPage.cpp 中,將一行程式碼新增至 Click 事件處理常式,將一本書附加至集合。In MainPage.cpp, add a line of code to the Click event handler to append a book to the collection.

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

現在請建置並執行專案。Now build and run the project. 按一下按鈕執行 [按一下] 事件處理常式。Click the button to execute the Click event handler. 我們所見 Append 的實作引發一個事件,讓 UI 知道集合已變更;且 ListBox 重新查詢集合,更新其自己的 Items 值。We saw that the implementation of Append raises an event to let the UI know that the collection has changed; and the ListBox re-queries the collection to update its own Items value. 就像以前一樣,變更書籍其中之一的標題;且同時在按鈕與清單方塊上反映該標題的變更。Just as before, the title of one of the books changes; and that title change is reflected both on the button and in the list box.

重要 APIImportant APIs