WinUI 3 C++ 컨트롤 가이드 – 목록 & 컬렉션 뷰

이번에는 여러 항목을 표시하는 뷰 컨트롤들을 소개하겠습니다. 여러 건의 데이터를 보여주는 세로 목록, 격자/표 레이아웃에 자주 사용됩니다.

컨트롤설명
ListView세로 가상화 목록
ListViewItemListView 목록 항목
GridView격자 카드 뷰 (타일/이미지 카드 레이아웃)
GridViewItemGridView 격자 항목
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="&#xE700;" 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="&#xE80F;" 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++ 컨트롤 가이드 – 목록 & 컬렉션 뷰

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다