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="項目一" 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="項目二" 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="項目三" 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 標頭檔

移除建構子實作內容,僅保留宣告。

新增三個私有成員變數,用來存放資料集合。

新增三個公開取得方法,供 XAML 呼叫,例如 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"Alpha", L"Beta", L"Gamma" });

        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)

在建構子內初始化可觀測向量,指派至私有欄位,接著實作三個公開回傳函式。

專案下載

WinUI 3 C++ 控制項手冊 — 清單與集合檢視

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *