Элементы управления XAML; привязка к коллекции C++/WinRT

Коллекция, которая может быть эффективно привязана к элементам управления XAML, называется отслеживаемой. Эта идея основана на шаблоне проектирования программного обеспечения, известном как шаблон наблюдателя. В этом разделе показано, как реализовывать отслеживаемые коллекции в C++/WinRT и привязывать к ним элементы управления XAML (вводные сведения см. в разделе Привязка данных).

Если вы хотите следовать инструкциям в этом разделе, рекомендуется сначала создать проект, который описан в разделе Элементы управления XAML; привязка к свойству C++/WinRT. В этом разделе добавляется дополнительный код для этого проекта, а также дополняются основные понятия, приведенные в том разделе.

Важно!

Основные понятия и термины, которые помогают понять, как использовать и создавать классы среды выполнения с помощью C++/WinRT, описаны в разделах Использование интерфейсов API с помощью C++/WinRT и Создание интерфейсов API с помощью C++/WinRT.

Что означает понятие отслеживаемая для коллекции?

Если класс среды выполнения, представляющий коллекцию, вызывает событие 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 является IObservableVectorBookSku. В следующем подразделе этого раздела мы привяжем источник элементов ListBox к BookSkus. Список — это элемент управления элементами. Чтобы правильно задать свойство ItemsControl.ItemsSource, необходимо присвоить значение типа IObservableVector (или IVector) или типа взаимодействия, например IBindableObservableVector.

Предупреждение

Код, показанный в этом разделе, применяется к C++/WinRT версии 2.0.190530.8 или более поздней. Если вы используете более раннюю версию, нужно внести в приведенный код несколько незначительных изменений. В приведенном выше листинге MIDL 3.0 измените значение свойства BookSkus на IObservableVector интерфейса IInspectable. А затем также используйте в соей реализации 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, который содержит разметку XAML для главной страницы пользовательского интерфейса. Добавьте следующую разметку внутри того же элемента StackPanel, что и 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 для добавления книги в коллекцию.

// 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 вызывает событие, чтобы сообщить пользовательскому интерфейсу о том, что коллекция изменилась, а ListBox повторно запрашивает коллекцию, чтобы обновить свое собственное значение Items. Так же, как и раньше, меняется название одной из книг, и это изменение отражается как на кнопке, так и в списке.

Важные API