controlos de itens XAML; ligar a uma coleção C++/WinRT

Uma coleção que pode ser efetivamente ligada a um controlo de itens XAML é conhecida como coleção observável . Esta ideia baseia-se no padrão de design de software conhecido como padrão do observador. Este tópico mostra como implementar coleções observáveis em C++/WinRT e como associar controlos de itens XAML a elas (para informações de fundo, ver Data binding).

Se quiser acompanhar este tema, então recomendamos que crie primeiro o projeto descrito nos controlos XAML; associe a uma propriedade C++/WinRT. Este tópico acrescenta mais código ao projeto e acrescenta aos conceitos explicados nesse tópico.

Important

Para conceitos e termos essenciais que apoiam a sua compreensão de como consumir e criar classes de runtime com C++/WinRT, veja Consume APIs with C++/WinRT e Author APIs with C++/WinRT.

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

Se uma classe de runtime que representa uma coleção escolher criar o evento IObservableVector<T>::VectorChanged sempre que um elemento lhe é adicionado ou removido, então a classe de runtime é uma coleção observável. Um controlo de itens XAML pode associar-se e tratar destes eventos ao recuperar a coleção atualizada e depois atualizar-se para mostrar os elementos atuais.

Note

Para informações sobre a instalação e utilização da Extensão Visual Studio C++/WinRT (VSIX) e do pacote NuGet (que juntos fornecem suporte para templates de projeto e compilação), consulte o suporte Visual Studio para C++/WinRT.

Adicionar uma coleção BookSkus à BookstoreViewModel

Nos controlos XAML; vincular a uma propriedade C++/WinRT, adicionámos uma propriedade do tipo BookSku ao nosso modelo de vista principal. Neste passo, vamos usar 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 vista.

Declare uma nova propriedade em BookstoreViewModel.idl.

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

Important

Associar-se a uma coleção com C++/WinRT é um pouco mais complexo do que em C#. Na listagem MIDL 3.0 acima, note que o tipo da propriedade BookSkus é IObservableVector do BookSku. Na próxima secção deste tópico, iremos vincular a fonte dos itens de uma ListBox ao BookSkus. Uma caixa de lista é um controlo de itens e, para definir corretamente a propriedade ItemsControl.ItemsSource , é necessário defini-la para 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.

Warning

O código apresentado neste tópico aplica-se a C++/WinRT versão 2.0.190530.8 ou posterior. Se estiveres a usar uma versão anterior, terás de fazer alguns pequenos ajustes ao código mostrado. Na listagem MIDL 3.0 acima, altere a propriedade BookSkus para IObservableVector de IInspectable. E depois usa IInspectable (em vez de BookSku) também na tua implementação.

Guardar e compilar. Copie os stubs de acesso de BookstoreViewModel.h e BookstoreViewModel.cpp, na pasta \Bookstore\Bookstore\Generated Files\sources (para mais detalhes, consulte o tópico anterior, controlos XAML; associar a uma propriedade C++/WinRT). Implementar esses stubs de acessores da seguinte 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;
}
...

Vincule uma ListBox à propriedade BookSkus

Abra o MainPage.xaml, que contém a marcação XAML para a nossa página principal da interface de utilizador. Adicione a seguinte marcação dentro do mesmo StackPanel que o 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>

Em MainPage.cpp, adicione uma linha de código ao handler de eventos Click para adicionar 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, construa e execute o projeto. Clique no botão para executar o manipulador do evento Click. Vimos que a implementação do Append gera um evento para informar a interface de que a coleção mudou; e a ListBox volta a consultar a coleção para atualizar o seu próprio valor de Items . Tal como antes, o título de um dos livros muda; e essa alteração no título é refletida tanto no botão como na caixa da lista.

APIs importantes