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 での作成者 API」を参照してください。For 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 Extension (VSIX) と NuGet パッケージ (両者が連携してプロジェクト テンプレートとビルドをサポート) のインストールと使用については、Visual Studio での C++/WinRT のサポートに関する記事を参照してください。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 コレクションを BookstoreViewModel に追加するAdd 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 プロパティの型が BookSkuIObservableVector であることに注意してください。In the MIDL 3.0 listing above, note that the type of the BookSkus property is IObservableVector of BookSku. このトピックの次のセクションでは、ListBox の項目ソースを BookSkus にバインドします。In the next section of this topic, we'll be binding the items source of a ListBox to BookSkus. リスト ボックスは項目コントロールです。ItemsControl.ItemsSource プロパティを正しく設定するには、それを IObservableVector 型の値、IVector 型の値、または IBindableObservableVector などの相互運用性型の値に設定する必要があります。A 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 プロパティを IInspectableIObservableVector に変更します。In the MIDL 3.0 listing above, change the BookSkus property to IObservableVector of IInspectable. その後、実装でも (BookSku の代わりに) IInspectable を使います。And then use IInspectable (instead of BookSku) in your implementation, too.

保存してビルドします。Save and build. \Bookstore\Bookstore\Generated Files\sources フォルダー内の BookstoreViewModel.h および BookstoreViewModel.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;
}
...

BookSkus プロパティに ListBox をバインドします。Bind a ListBox to the BookSkus property

メイン UI ページの XAML マークアップが含まれている MainPage.xaml を開きます。Open MainPage.xaml, which contains the XAML markup for our main UI page. Button と同じ 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 で、クリック イベント ハンドラーにコードの行を追加してブックをコレクションに追加します。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