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

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

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

Это важно

Основные понятия и термины, поддерживающие понимание использования и разработки классов среды выполнения с помощью C++/WinRT, см. в статье "Использование API с помощью C++/WinRT и разработки API с помощью C++/WinRT".

Что означает наблюдаемое значение для коллекции?

Если класс среды выполнения, представляющий коллекцию, выбирает вызов события IObservableVector<T>::VectorChanged всякий раз, когда элемент добавляется к нему или удаляется из него, то класс среды выполнения является наблюдаемой коллекцией. Элемент управления элементами в XAML может быть привязан к этим событиям и обрабатывать их, получая обновленную коллекцию, а затем обновляя себя, чтобы отобразить текущие элементы.

Note

Сведения об установке и использовании расширения C++/WinRT Visual Studio (VSIX) и пакета NuGet (которые вместе предоставляют поддержку шаблона проекта и сборки), см. Visual Studio поддержку C++/WinRT.

Добавление коллекции 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; };
}
...

Это важно

Привязка к коллекции с помощью C++/WinRT несколько сложнее, чем в C#. В приведенном выше списке MIDL 3.0 обратите внимание, что тип свойства BookSkusIObservableVectorBookSku. В следующем разделе этой статьи мы привязаем источник элементов 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, который содержит разметку 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 . Мы видели, что реализация Добавления вызывает событие, чтобы сообщить пользовательскому интерфейсу, что коллекция изменилась; и ListBox повторно запрашивает коллекцию для обновления собственного значения Items . Как и раньше, название одной из книг изменяется; и это изменение заголовка отражается как на кнопке, так и в поле списка.

Важные API