You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WinUI 3:如何创建带浮动可展开行与统一滚动的GridView

WinUI 3 实现可展开浮动GridView(统一滚动)

核心问题分析

你之前用两个分离的GridView(一个在ToggleButton、一个在Popup),导致两者不在同一滚动上下文,无法实现统一滚动。正确思路是用单个GridView承载所有数据,通过控制显示高度实现“初始只显示第一行、展开显示全部”的效果,同时将GridView放在浮动容器中实现覆盖效果。

解决方案代码

1. XAML 布局

<Page
    x:Class="WinUI3GridViewDemo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WinUI3GridViewDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Page.Resources>
        <local:BoolToHeightConverter x:Key="BoolToHeightConverter"/>
        <local:BoolToReverseTextConverter x:Key="BoolToReverseTextConverter"/>
    </Page.Resources>

    <Grid>
        <!-- 页面原有内容 -->
        <StackPanel Margin="20">
            <TextBlock Text="页面其他内容区域" FontSize="24" Margin="0 0 0 40"/>
            <TextBlock Text="展开的GridView会覆盖在此区域上方" FontSize="16"/>
        </StackPanel>

        <!-- 浮动GridView容器 -->
        <Grid Panel.ZIndex="10" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="20">
            <!-- 展开/收起按钮 -->
            <Button x:Name="ToggleExpandBtn" 
                    Content="{x:Bind IsGridViewExpanded, Converter={StaticResource BoolToReverseTextConverter}, Mode=OneWay}"
                    Click="ToggleExpandBtn_Click"
                    Width="120" Height="40"/>

            <!-- 核心GridView:承载所有数据 -->
            <GridView x:Name="CategoryGridView"
                      Margin="0 50 0 0"
                      Width="800"
                      Height="{x:Bind IsGridViewExpanded, Converter={StaticResource BoolToHeightConverter}, Mode=OneWay}"
                      SelectionMode="Single">
                <GridView.ItemTemplate>
                    <DataTemplate x:DataType="local:Category">
                        <Border Height="100" Width="150" Background="#FF5C5C5C" Margin="5" CornerRadius="4">
                            <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
                                <TextBlock Text="{Binding Name}" FontSize="16" Foreground="White"/>
                            </StackPanel>
                        </Border>
                    </DataTemplate>
                </GridView.ItemTemplate>
                <GridView.ItemsPanel>
                    <ItemsPanelTemplate>
                        <ItemsWrapGrid Orientation="Horizontal" ItemWidth="160" ItemHeight="110"/>
                    </ItemsPanelTemplate>
                </GridView.ItemsPanel>
            </GridView>
        </Grid>
    </Grid>
</Page>

2. 后台代码与转换器

首先添加两个转换器:

using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Data;
using System;

namespace WinUI3GridViewDemo
{
    // 控制GridView高度:收起时仅显示第一行,展开时自适应
    public class BoolToHeightConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return value is bool isExpanded ? double.NaN : 110; // 110 = Item高度(100) + 上下Margin(10)
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

    // 切换按钮文本:展开/收起
    public class BoolToReverseTextConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            return value is bool isExpanded ? "收起" : "展开";
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

然后是页面后台逻辑:

using Microsoft.UI.Xaml;
using System.Collections.Generic;
using System.ComponentModel;

namespace WinUI3GridViewDemo
{
    public sealed partial class MainPage : Page, INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private bool _isGridViewExpanded;
        public bool IsGridViewExpanded
        {
            get => _isGridViewExpanded;
            set
            {
                _isGridViewExpanded = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsGridViewExpanded)));
            }
        }

        public MainPage()
        {
            this.InitializeComponent();
            this.DataContext = this;

            // 模拟测试数据(10个分类,刚好两行)
            var categoryList = new List<Category>();
            for (int i = 1; i <= 10; i++)
            {
                categoryList.Add(new Category { Name = $"分类 {i}" });
            }
            CategoryGridView.ItemsSource = categoryList;
        }

        private void ToggleExpandBtn_Click(object sender, RoutedEventArgs e)
        {
            IsGridViewExpanded = !IsGridViewExpanded;
        }
    }

    // 数据模型
    public class Category
    {
        public string Name { get; set; }
    }
}

实现说明

  1. 统一滚动:所有数据都在同一个GridView中,自带的ScrollViewer会处理所有行的滚动,天然支持无缝切换。
  2. 浮动覆盖:通过设置Panel.ZIndex="10"让GridView容器位于页面原有内容上方,实现覆盖效果;也可以用Popup替代高ZIndex的Grid,只需调整PlacementTarget和Placement属性即可。
  3. 显示控制:通过BoolToHeightConverter在收起时将GridView高度设为第一行的总高度,仅显示第一行;展开时设为double.NaN(自适应),显示所有行。

内容的提问来源于stack exchange,提问作者Bevara Satyasairam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 11:50:57