Compartilhar via


Controles de itens XAML; associar a uma coleção C++/WinRT

Uma coleção que pode ser efetivamente associada a um controle de itens XAML é chamada de uma coleção observável. Essa ideia baseia-se no padrão de design de software conhecido como o padrão de observador . Este tópico mostra como implementar coleções observáveis em C++/WinRTe como associar controles de itens XAML a elas (para obter informações em segundo plano, consulte Associação de Dados).

Se você quiser acompanhar este tópico, recomendamos que primeiro crie o projeto descrito em controles XAML e vincule a uma propriedade C++/WinRT. Este tópico adiciona mais código a esse projeto e adiciona aos conceitos explicados nesse tópico.

Importante

Para obter conceitos e termos essenciais que dão suporte à compreensão de como consumir e criar classes de tempo de execução com C++/WinRT, consulte Consumir APIs com C++/WinRT e Criar APIs com C++/WinRT.

O que significa observável para uma coleção?

Se uma classe de runtime que representa uma coleção optar por gerar o IObservableVector<T>::VectorChanged evento sempre que um elemento for adicionado a ele ou removido dele, a classe de runtime será uma coleção observável. Um controle de itens XAML pode associar e manipular esses eventos recuperando a coleção atualizada e atualizando-se para mostrar os elementos atuais.

Observação

Para obter informações sobre como instalar e usar a Extensão C++/WinRT para Visual Studio (VSIX) e o pacote NuGet (que juntos fornecem suporte ao modelo de projeto e ao build), consulte suporte do Visual Studio para C++/WinRT.

Adicionar uma coleção BookSkus a BookstoreViewModel

Em controles XAML; associar a uma propriedade C++/WinRT, adicionamos uma propriedade do tipo BookSku ao nosso modelo de exibição principal. Nesta etapa, usaremos o modelo de função de fábrica winrt::single_threaded_observable_vector para nos ajudar a implementar uma coleção observável de BookSku no mesmo modelo de exibição.

Declare uma nova propriedade em BookstoreViewModel.idl.

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

Importante

A associação a uma coleção com C++/WinRT é um pouco mais matizada do que com C#. Na listagem MIDL 3.0 acima, observe que o tipo da propriedade BookSkus é IObservableVector de BookSku. Na próxima seção deste tópico, associaremos a fonte de itens de um ListBox a BookSkus. Uma caixa de listagem é um controle de itens e, para definir corretamente a propriedade ItemsControl.ItemsSource, você precisa defini-la como um valor do tipo IObservableVector ou IVector ou de um tipo de interoperabilidade, como IBindableObservableVector. Caso contrário, {x:Bind} gerará E_INVALIDARG e {Binding} falhará silenciosamente.

Aviso

O código mostrado neste tópico se aplica ao C++/WinRT versão 2.0.190530.8 ou posterior. Se você estiver usando uma versão anterior, precisará fazer alguns pequenos ajustes no código mostrado. Na listagem MIDL 3.0 acima, altere a propriedade BookSkus para IObservableVector de IInspectable. Em sua implementação, use IInspectable (em vez de BookSku) também.

Salvar e compilar. Copie os stubs do acessador de BookstoreViewModel.h e BookstoreViewModel.cpp na pasta \Bookstore\Bookstore\Generated Files\sources (para obter mais detalhes, consulte o tópico anterior, controles XAML; associe a uma propriedade C++/WinRT). Implemente esses acessadores stub dessa forma.

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

Associar um ListBox à propriedade BookSkus

Abra MainPage.xaml, que contém as marcações XAML para nossa página principal de UI. Adicione a marcação a seguir dentro da mesma do StackPanel que o botão .

<ListBox ItemsSource="{x:Bind MainViewModel.BookSkus}">
    <ItemsControl.ItemTemplate>
        <DataTemplate x:DataType="local:BookSku">
            <TextBlock Text="{x:Bind Title, Mode=OneWay}"/>
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ListBox>

Em MainPage.cpp, adicione uma linha de código ao manipulador de eventos Clique para acrescentar um livro à coleção.

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

Agora, compile e execute o projeto. Clique no botão para executar o manipulador de eventos Clique. Vimos que a implementação de Append gera um evento para informar à interface do usuário que a coleção foi alterada; e o ListBox consulta novamente a coleção para atualizar seu próprio valor Items. Assim como antes, o título de um dos livros muda; e essa alteração de título é refletida no botão e na caixa de listagem.

APIs importantes