Next we will introduce several view controls used to display multiple items. They are commonly used to render batches of data, presenting a vertical list, grid or table layout.
| Control | Description |
|---|---|
| ListView | Vertical virtualized list |
| ListViewItem | Single item inside ListView |
| GridView | Grid card view (grid / thumbnail tile layout) |
| GridViewItem | Grid tile item for GridView |
| ItemsRepeater | Custom high-performance repeating item container |
| ItemsStackPanel | Virtualized vertical layout panel |
| ItemsWrapGrid | Virtualized auto-wrapping grid panel |
| LinedFlowLayout | Wrapped text-image flow layout |
Add Controls in XAML
First modify your XAML markup. If your page is not a Window type, refer to the example below.
<?xml version="1.0" encoding="utf-8"?>
<Window
x:Class="AppWinui.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:AppWinui"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="AppWinui">
<ScrollViewer VerticalScrollMode="Auto" Padding="16" Background="#F7F8FA">
<StackPanel Spacing="36">
<!-- 1. ListView + ListViewItem + ItemsStackPanel -->
<StackPanel>
<TextBlock Text="1. ListView (ItemsStackPanel)" FontSize="17" FontWeight="SemiBold"/>
<ListView Height="180" Margin="0 8 0 0">
<ListView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsStackPanel/>
</ItemsPanelTemplate>
</ListView.ItemsPanel>
<ListViewItem Background="White" Padding="10">
<StackPanel Orientation="Horizontal" Spacing="10">
<Ellipse Width="36" Height="36" Fill="#4285F4"/>
<TextBlock Text="Item One" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem Background="White" Padding="10">
<StackPanel Orientation="Horizontal" Spacing="10">
<Ellipse Width="36" Height="36" Fill="#EA4335"/>
<TextBlock Text="Item Two" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
<ListViewItem Background="White" Padding="10">
<StackPanel Orientation="Horizontal" Spacing="10">
<Ellipse Width="36" Height="36" Fill="#FBBC05"/>
<TextBlock Text="Item Three" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
</ListViewItem>
</ListView>
</StackPanel>
<!-- 2. GridView + GridViewItem + ItemsWrapGrid -->
<StackPanel>
<TextBlock Text="2. GridView (ItemsWrapGrid)" FontSize="17" FontWeight="SemiBold"/>
<GridView Height="220" Margin="0 8 0 0">
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<ItemsWrapGrid ItemWidth="120" ItemHeight="140"/>
</ItemsPanelTemplate>
</GridView.ItemsPanel>
<GridViewItem Margin="4" Background="White" CornerRadius="6" Padding="8">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="6">
<Rectangle Width="70" Height="70" Fill="#FF7A7A" />
<TextBlock Text="Tile 1" FontSize="14"/>
</StackPanel>
</GridViewItem>
<GridViewItem Margin="4" Background="White" CornerRadius="6" Padding="8">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="6">
<Rectangle Width="70" Height="70" Fill="#48CFC0" />
<TextBlock Text="Tile 2" FontSize="14"/>
</StackPanel>
</GridViewItem>
<GridViewItem Margin="4" Background="White" CornerRadius="6" Padding="8">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="6">
<Rectangle Width="70" Height="70" Fill="#FFD470" />
<TextBlock Text="Tile 3" FontSize="14"/>
</StackPanel>
</GridViewItem>
<GridViewItem Margin="4" Background="White" CornerRadius="6" Padding="8">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="6">
<Rectangle Width="70" Height="70" Fill="#8A3797" />
<TextBlock Text="Tile 4" FontSize="14"/>
</StackPanel>
</GridViewItem>
</GridView>
</StackPanel>
<!-- 3. ItemsRepeater + StackLayout (ItemsStackPanel) -->
<StackPanel>
<TextBlock Text="3. ItemsRepeater - StackLayout" FontSize="17" FontWeight="SemiBold"/>
<ItemsRepeater Height="160" Margin="0 8 0 0" ItemsSource="{x:Bind ListData}">
<ItemsRepeater.Layout>
<StackLayout/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Border Background="White" Margin="3" Padding="8" CornerRadius="5">
<StackPanel Orientation="Horizontal" Spacing="8">
<FontIcon Glyph="" FontSize="22" Foreground="#0078D4"/>
<TextBlock Text="{x:Bind}" FontSize="15" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel>
<!-- 4. ItemsRepeater + ItemsWrapGrid -->
<StackPanel>
<TextBlock Text="4. ItemsRepeater + ItemsWrapGrid Panel" FontSize="17" FontWeight="SemiBold"/>
<ItemsRepeater Height="200" Margin="0 8 0 0" ItemsSource="{x:Bind GridData}">
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Border Background="#EFF5FF" Margin="4" CornerRadius="6">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Spacing="4">
<FontIcon Glyph="" FontSize="28" Foreground="#2463EB"/>
<TextBlock Text="{x:Bind}" FontSize="13"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel>
<!-- 5. ItemsRepeater + LinedFlowLayout -->
<StackPanel>
<TextBlock Text="5. ItemsRepeater - LinedFlowLayout" FontSize="17" FontWeight="SemiBold"/>
<ItemsRepeater Height="240" Margin="0 8 0 0" ItemsSource="{x:Bind FlowData}">
<ItemsRepeater.Layout>
<LinedFlowLayout LineHeight="80"/>
</ItemsRepeater.Layout>
<ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="x:String">
<Border Background="White" Padding="10" Margin="3" CornerRadius="5" BorderBrush="#E0E2E6" BorderThickness="1">
<StackPanel Orientation="Horizontal" Spacing="8">
<Rectangle Width="50" Height="50" Fill="#10B981"/>
<TextBlock Text="{x:Bind}" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Border>
</DataTemplate>
</ItemsRepeater.ItemTemplate>
</ItemsRepeater>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Window>
Code language: C++ (cpp)
We used ItemsSource to bind data sources here, data objects are constructed in backend C++ code, for example ItemsSource=”{x:Bind FlowData}”.
Add Properties in IDL File
Add three bindable properties: ListData, GridData, FlowData
namespace AppWinui
{
[default_interface]
runtimeclass MainWindow : Microsoft.UI.Xaml.Window
{
MainWindow();
Int32 MyProperty;
Windows.Foundation.Collections.IObservableVector<String> ListData{ get; };
Windows.Foundation.Collections.IObservableVector<String> GridData{ get; };
Windows.Foundation.Collections.IObservableVector<String> FlowData{ get; };
}
}
Code language: C++ (cpp)
Modify Header (.h) File
Remove constructor implementation, keep only declaration.
Add three private member variables to store data collections.
Add three public getter methods to expose data for XAML binding, e.g. ListData().
#pragma once
#include "MainWindow.g.h"
namespace winrt::AppWinui::implementation
{
struct MainWindow : MainWindowT<MainWindow>
{
private:
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_listData;
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_gridData;
winrt::Windows::Foundation::Collections::IObservableVector<hstring> m_flowData;
public:
winrt::Windows::Foundation::Collections::IObservableVector<hstring> ListData();
winrt::Windows::Foundation::Collections::IObservableVector<hstring> GridData();
winrt::Windows::Foundation::Collections::IObservableVector<hstring> FlowData();
MainWindow();
int32_t MyProperty();
void MyProperty(int32_t value);
};
}
namespace winrt::AppWinui::factory_implementation
{
struct MainWindow : MainWindowT<MainWindow, implementation::MainWindow>
{
};
}
Code language: C++ (cpp)
Initialize Data Sources in .cpp File
#include "pch.h"
#include "MainWindow.xaml.h"
#if __has_include("MainWindow.g.cpp")
#include "MainWindow.g.cpp"
#endif
using namespace winrt;
using namespace Microsoft::UI::Xaml;
// To learn more about WinUI, the WinUI project structure,
// and more about our project templates, see: http://aka.ms/winui-project-info.
namespace winrt::AppWinui::implementation
{
int32_t MainWindow::MyProperty()
{
throw hresult_not_implemented();
}
void MainWindow::MyProperty(int32_t /* value */)
{
throw hresult_not_implemented();
}
MainWindow::MainWindow()
{
InitializeComponent();
m_listData = winrt::single_threaded_observable_vector<hstring>(
{ L"Alpha", L"Beta", L"Gamma" });
m_gridData = winrt::single_threaded_observable_vector<hstring>(
{ L"Tile A", L"Tile B", L"Tile C", L"Tile D" });
m_flowData = winrt::single_threaded_observable_vector<hstring>(
{ L"Flow Item 1", L"Flow Item 2", L"Flow Item 3" });
}
winrt::Windows::Foundation::Collections::IObservableVector<hstring> MainWindow::ListData()
{
return m_listData;
}
winrt::Windows::Foundation::Collections::IObservableVector<hstring> MainWindow::GridData()
{
return m_gridData;
}
winrt::Windows::Foundation::Collections::IObservableVector<hstring> MainWindow::FlowData()
{
return m_flowData;
}
}
Code language: C++ (cpp)
Inside the constructor, initialize observable vector data and assign to private fields, then implement three public getter functions to return the collections.
Project Download
WinUI 3 C++ Controls Guide – List & Collection Views