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; } } }
实现说明
- 统一滚动:所有数据都在同一个
GridView中,自带的ScrollViewer会处理所有行的滚动,天然支持无缝切换。 - 浮动覆盖:通过设置
Panel.ZIndex="10"让GridView容器位于页面原有内容上方,实现覆盖效果;也可以用Popup替代高ZIndex的Grid,只需调整PlacementTarget和Placement属性即可。 - 显示控制:通过
BoolToHeightConverter在收起时将GridView高度设为第一行的总高度,仅显示第一行;展开时设为double.NaN(自适应),显示所有行。
内容的提问来源于stack exchange,提问作者Bevara Satyasairam
相关产品推荐
相关产品推荐

