이번에는 여러 항목을 표시하는 뷰 컨트롤들을 소개하겠습니다. 여러 건의 데이터를 보여주는 세로 목록, 격자/표 레이아웃에 자주 사용됩니다.
| 컨트롤 | 설명 |
|---|---|
| ListView | 세로 가상화 목록 |
| ListViewItem | ListView 목록 항목 |
| GridView | 격자 카드 뷰 (타일/이미지 카드 레이아웃) |
| GridViewItem | GridView 격자 항목 |
| ItemsRepeater | 커스텀 고성능 반복 항목 컨테이너 |
| ItemsStackPanel | 가상화 세로 레이아웃 패널 |
| ItemsWrapGrid | 가상화 자동 줄바꿈 격자 패널 |
| LinedFlowLayout | 텍스트 이미지 혼합 흐름 레이아웃 |
XAML에 컨트롤 추가하기
먼저 XAML 코드를 수정합니다. 페이지 타입이 Window가 아니라면 아래 예시를 참고하세요.
<?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="항목 1" 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="항목 2" 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="항목 3" 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="타일 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="타일 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="타일 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="타일 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 패널" 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)
위 코드에서 ItemsSource로 데이터 소스를 바인딩했으며, 데이터는 백엔드 C++ 코드에서 생성합니다. 예: ItemsSource=”{x:Bind FlowData}”
IDL 파일에 속성 추가
바인딩용 속성 세 개를 추가합니다: 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)
헤더(.h) 파일 수정
생성자 구현 코드를 지우고 선언만 남깁니다.
데이터를 저장할 private 멤버 변수 3개를 추가합니다.
XAML에서 호출할 public getter 메서드 3개를 추가합니다 (예: 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)
.cpp 파일에서 데이터 소스 초기화
#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"알파", L"베타", L"감마" });
m_gridData = winrt::single_threaded_observable_vector<hstring>(
{ L"타일 A", L"타일 B", L"타일 C", L"타일 D" });
m_flowData = winrt::single_threaded_observable_vector<hstring>(
{ L"흐름 항목 1", L"흐름 항목 2", L"흐름 항목 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)
생성자 내부에서 데이터 소스를 초기화하고 private 변수에 할당한 뒤, 3개의 public getter 함수를 구현하여 반환합니다.
프로젝트 다운로드
WinUI 3 C++ 컨트롤 가이드 – 목록 & 컬렉션 뷰