Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Internamente, uma coleção do Windows Runtime tem muitos componentes complexos. Mas quando você deseja passar um objeto de coleção para uma função Windows Runtime ou implementar suas próprias propriedades de coleção e tipos de coleção, há funções e classes base em C++/WinRT para dar suporte a você. Esses recursos eliminam essa complexidade para você e poupam muito tempo e esforço.
IVector é a interface Windows Runtime implementada por qualquer coleção de elementos de acesso aleatório. Se você mesmo implementasse o IVector , também precisaria implementar IIterable, IVectorView e IIterator. Mesmo que você precise de um tipo de coleção personalizado, isso é muito trabalho. Mas se você tiver dados em um std::vector (ou um std::map ou um std::unordered_map) e tudo o que você deseja fazer é passar isso para uma API Windows Runtime, então você gostaria de evitar fazer esse nível de trabalho, se possível. E evitar isso é possível, pois o C++/WinRT ajuda você a criar coleções com eficiência e com pouco esforço.
Veja também controles de itens do XAML; vinculação a uma coleção do C++/WinRT.
Funções auxiliares para coleções
Coleção de uso geral, vazia
Esta seção aborda o cenário em que você deseja criar uma coleção inicialmente vazia; e, em seguida, preencha-o após a criação.
Para recuperar um novo objeto de um tipo que implementa uma coleção de uso geral, você pode chamar o modelo de função winrt::single_threaded_vector . O objeto é retornado como um IVector e essa é a interface por meio da qual você chama as funções e as propriedades do objeto retornado.
Se você quiser copiar e colar os exemplos de código a seguir diretamente no arquivo de código-fonte principal de um projeto do Windows Console Application (C++/WinRT), primeiro defina Não Usando Cabeçalhos Pré-compilados nas propriedades do projeto.
// main.cpp
#include <winrt/Windows.Foundation.Collections.h>
#include <iostream>
using namespace winrt;
int main()
{
winrt::init_apartment();
Windows::Foundation::Collections::IVector<int> coll{ winrt::single_threaded_vector<int>() };
coll.Append(1);
coll.Append(2);
coll.Append(3);
for (auto const& el : coll)
{
std::cout << el << std::endl;
}
Windows::Foundation::Collections::IVectorView<int> view{ coll.GetView() };
}
Como você pode ver no exemplo de código acima, depois de criar a coleção, você pode acrescentar elementos, iterar sobre eles e geralmente tratar o objeto como faria com qualquer objeto de coleção Windows Runtime que você possa ter recebido de uma API. Se você precisar de uma exibição imutável sobre a coleção, poderá chamar IVector::GetView, conforme mostrado. O padrão mostrado acima, de criar e consumir uma coleção, é apropriado para cenários simples em que você deseja transmitir dados ou obter dados de uma API. Você pode passar um IVector ou um IVectorView em qualquer lugar que um IIterable seja esperado.
No exemplo de código acima, a chamada para winrt::init_apartment inicializa o thread no Windows Runtime; por padrão, em um apartamento multithreaded. A chamada também inicializa COM.
Coleção de uso geral, preparada a partir de dados
Esta seção aborda o cenário em que você deseja criar uma coleção e preenchê-la ao mesmo tempo.
Você pode evitar a sobrecarga das chamadas para Acrescentar no exemplo de código anterior. Talvez você já tenha os dados de origem ou prefira preencher os dados de origem antes de criar o objeto de coleção Windows Runtime. Veja como fazer isso.
auto coll1{ winrt::single_threaded_vector<int>({ 1,2,3 }) };
std::vector<int> values{ 1,2,3 };
auto coll2{ winrt::single_threaded_vector<int>(std::move(values)) };
for (auto const& el : coll2)
{
std::cout << el << std::endl;
}
Você pode passar um objeto temporário que contém seus dados para winrt::single_threaded_vector, como com coll1, acima. Ou você pode mover um std::vector (supondo que você não irá acessá-lo novamente) para a função. Em ambos os casos, você está passando um rvalue para a função. Isso permite que o compilador seja eficiente e evite copiar os dados. Se você quiser saber mais sobre rvalues, consulte categorias de valor e referências a elas.
Se você quiser associar um controle de itens XAML à sua coleção, poderá. Mas lembre-se de que, para definir corretamente a propriedade ItemsControl.ItemsSource , você precisa defini-la como um valor do tipo IVector de IInspectable (ou de um tipo de interoperabilidade, como IBindableObservableVector).
Aqui está um exemplo de código que produz uma coleção de um tipo adequado para vinculação e adiciona um elemento a essa coleção. Você pode encontrar o contexto deste exemplo de código em controles de itens XAML; vinculados a uma coleção C++/WinRT.
auto bookSkus{ winrt::single_threaded_vector<Windows::Foundation::IInspectable>() };
bookSkus.Append(winrt::make<Bookstore::implementation::BookSku>(L"Moby Dick"));
Você pode criar uma coleção do Windows Runtime a partir de dados e obter uma exibição dela pronta para ser passada a uma API, tudo isso sem copiar nada.
std::vector<float> values{ 0.1f, 0.2f, 0.3f };
Windows::Foundation::Collections::IVectorView<float> view{ winrt::single_threaded_vector(std::move(values)).GetView() };
Nos exemplos acima, a coleção que criamos pode ser associada a um controle de itens XAML; mas a coleção não é observável.
Coleção observável
Para recuperar um novo objeto de um tipo que implementa uma coleção observável , chame o modelo de função winrt::single_threaded_observable_vector com qualquer tipo de elemento. Mas para tornar uma coleção observável adequada para associação a um controle de itens XAML, use IInspectable como o tipo de elemento.
O objeto é retornado como um IObservableVector e essa é a interface por meio da qual você (ou o controle ao qual está associado) chama as funções e as propriedades do objeto retornado.
auto bookSkus{ winrt::single_threaded_observable_vector<Windows::Foundation::IInspectable>() };
Para obter mais detalhes e exemplos de código, sobre como associar seus controles de interface do usuário a uma coleção observável, consulte controles de itens XAML; associar a uma coleção C++/WinRT.
Coleção associativa (mapa)
Há versões de coleção associativa das duas funções que examinamos.
- O modelo de função winrt::single_threaded_map retorna uma coleção associativa não observável como um IMap.
- O modelo de função winrt::single_threaded_observable_map retorna uma coleção associativa observável como um IObservableMap.
Opcionalmente, você pode aprimorar essas coleções com dados passando para a função um rvalue do tipo std::map ou std::unordered_map.
auto coll1{
winrt::single_threaded_map<winrt::hstring, int>(std::map<winrt::hstring, int>{
{ L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
})
};
std::map<winrt::hstring, int> values{
{ L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
};
auto coll2{ winrt::single_threaded_map<winrt::hstring, int>(std::move(values)) };
Thread único
O "thread único" nos nomes dessas funções indica que elas não fornecem nenhuma simultaneidade. Em outras palavras, elas não são thread-safe. A menção a threads não está relacionada a apartamentos, pois os objetos retornados por essas funções são todos ágeis (consulte Objetos ágeis em C++/WinRT). É que os objetos são de thread único. E isso é totalmente apropriado se você quiser apenas passar dados de uma forma ou de outra na ABI (interface binária do aplicativo).
Classes base para coleções
Se, para ter total flexibilidade, você deseja implementar sua própria coleção personalizada, então você vai querer evitar fazer isso da maneira mais difícil. Por exemplo, essa é a aparência de uma exibição de vetor personalizada sem a assistência das classes base do C++/WinRT.
...
using namespace winrt;
using namespace Windows::Foundation::Collections;
...
struct MyVectorView :
implements<MyVectorView, IVectorView<float>, IIterable<float>>
{
// IVectorView
float GetAt(uint32_t const) { ... };
uint32_t GetMany(uint32_t, winrt::array_view<float>) const { ... };
bool IndexOf(float, uint32_t&) { ... };
uint32_t Size() { ... };
// IIterable
IIterator<float> First() const { ... };
};
...
IVectorView<float> view{ winrt::make<MyVectorView>() };
Em vez disso, é muito mais fácil derivar sua exibição de vetor personalizado do modelo de struct winrt::vector_view_base e apenas implementar a função get_container para expor o contêiner que contém seus dados.
struct MyVectorView2 :
implements<MyVectorView2, IVectorView<float>, IIterable<float>>,
winrt::vector_view_base<MyVectorView2, float>
{
auto& get_container() const noexcept
{
return m_values;
}
private:
std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};
O contêiner retornado por get_container deve fornecer a interface de início e término que winrt::vector_view_base espera. Conforme mostrado no exemplo acima, std::vector fornece isso. Mas você pode retornar qualquer contêiner que cumpra o mesmo contrato, incluindo seu próprio contêiner personalizado.
struct MyVectorView3 :
implements<MyVectorView3, IVectorView<float>, IIterable<float>>,
winrt::vector_view_base<MyVectorView3, float>
{
auto get_container() const noexcept
{
struct container
{
float const* const first;
float const* const last;
auto begin() const noexcept
{
return first;
}
auto end() const noexcept
{
return last;
}
};
return container{ m_values.data(), m_values.data() + m_values.size() };
}
private:
std::array<float, 3> m_values{ 0.2f, 0.3f, 0.4f };
};
Essas são as classes base que o C++/WinRT fornece para ajudá-lo a implementar coleções personalizadas.
winrt::vector_view_base
Veja os exemplos de código acima.
winrt::vector_base
struct MyVector :
implements<MyVector, IVector<float>, IVectorView<float>, IIterable<float>>,
winrt::vector_base<MyVector, float>
{
auto& get_container() const noexcept
{
return m_values;
}
auto& get_container() noexcept
{
return m_values;
}
private:
std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};
winrt::observable_vector_base
struct MyObservableVector :
implements<MyObservableVector, IObservableVector<float>, IVector<float>, IVectorView<float>, IIterable<float>>,
winrt::observable_vector_base<MyObservableVector, float>
{
auto& get_container() const noexcept
{
return m_values;
}
auto& get_container() noexcept
{
return m_values;
}
private:
std::vector<float> m_values{ 0.1f, 0.2f, 0.3f };
};
winrt::map_view_base
struct MyMapView :
implements<MyMapView, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
winrt::map_view_base<MyMapView, winrt::hstring, int>
{
auto& get_container() const noexcept
{
return m_values;
}
private:
std::map<winrt::hstring, int> m_values{
{ L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
};
};
winrt::map_base
struct MyMap :
implements<MyMap, IMap<winrt::hstring, int>, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
winrt::map_base<MyMap, winrt::hstring, int>
{
auto& get_container() const noexcept
{
return m_values;
}
auto& get_container() noexcept
{
return m_values;
}
private:
std::map<winrt::hstring, int> m_values{
{ L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
};
};
winrt::observable_map_base
struct MyObservableMap :
implements<MyObservableMap, IObservableMap<winrt::hstring, int>, IMap<winrt::hstring, int>, IMapView<winrt::hstring, int>, IIterable<IKeyValuePair<winrt::hstring, int>>>,
winrt::observable_map_base<MyObservableMap, winrt::hstring, int>
{
auto& get_container() const noexcept
{
return m_values;
}
auto& get_container() noexcept
{
return m_values;
}
private:
std::map<winrt::hstring, int> m_values{
{ L"AliceBlue", 0xfff0f8ff }, { L"AntiqueWhite", 0xfffaebd7 }
};
};
APIs importantes
- Propriedade ItemsControl.ItemsSource
- Interface IObservableVector
- Interface IVector
- modelo de struct winrt::map_base
- modelo da struct winrt::map_view_base
- modelo de struct winrt::observable_map_base
- modelo da struct winrt::observable_vector_base
- Modelo de função winrt::single_threaded_observable_map
- Modelo de função winrt::single_threaded_map
- modelo de função winrt::single_threaded_observable_vector
- Modelo de função winrt::single_threaded_vector
- modelo de struct winrt::vector_base
- modelo de struct winrt::vector_view_base
Tópicos relacionados:
Windows developer