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

Windows平台CommunityToolkit.Maui Popup中CollectionView自动缩放问题

CommunityToolkit.Maui Popup中CollectionView Windows平台自动高度失效问题

问题描述

我正在为CommunityToolkit.Maui的toolkit:Popup中的CollectionView实现自动高度调整。Popup内包含标题、输入框和触发填充CollectionView的按钮,但Popup或CollectionView的高度无法自动扩展,导致搜索结果无法正常显示:

  • Android平台运行正常
  • Windows平台仅在热重载修改HeightRequest/MinimumHeightRequest时临时生效,重新调试后失效
  • 已尝试修改HorizontalOptions、VerticalOptions、最小/最大宽高,甚至将VerticalStackLayout替换为Grid,问题仍未解决

代码示例

<?xml version="1.0" encoding="utf-8" ?>
<toolkit:Popup xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               x:Class="SimpleRunManager.Views.Popups.SetStaticLocalizationPopup"
               xmlns:toolkit="http://schemas.microsoft.com/dotnet/2022/maui/toolkit"
               xmlns:viewmodel="clr-namespace:SimpleRunManager.ViewModels"
               x:DataType="viewmodel:SetStaticLocalizationPopupViewModel"
               xmlns:model="clr-namespace:SimpleRunManager.Models"
               Color="{StaticResource MainPopup}"
               CanBeDismissedByTappingOutsideOfPopup="True"
               HorizontalOptions="{OnPlatform Default='Fill', WinUI='Center'}"
               VerticalOptions="Center">
    <!-- TODO -> style -->
    <VerticalStackLayout MinimumWidthRequest="{OnPlatform WinUI='500'}"
                         BackgroundColor="{StaticResource MainPopup}"
                         MaximumHeightRequest="{OnPlatform WinUI='601'}"
                         VerticalOptions="FillAndExpand">
        <Grid ColumnDefinitions="{OnPlatform Default='*,auto', WinUI='*,*'}">
            <Label Grid.ColumnSpan="{OnPlatform Default='1', WinUI='2'}"
                   Text="Set localization"
                   VerticalOptions="Center" 
                   HorizontalOptions="CenterAndExpand" 
                   Style="{StaticResource HeaderLabel}"
                   FontAttributes="Bold"
                   Padding="10,20,10,20"/>
            <Button Grid.Column="1"
                    Text="Delete"
                    Style="{StaticResource DangerButton}"
                    HorizontalOptions="End"
                    Margin="0,20,15,20"
                    Command="{Binding DeleteStaticLocalizationCommand}"
                    CommandParameter="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type toolkit:Popup}}}"></Button>
        </Grid>
        
        <Grid ColumnDefinitions="*,*"
              ColumnSpacing="15"
              Padding="15,0,15,20">
            <Entry Placeholder="City name" 
                   Text="{Binding CityName}"
                   Grid.Column="0"
                   TextColor="Snow"></Entry>
            <Button Text="Search"
                    Command="{Binding SearchCommand}"
                    CommandParameter="{Binding Source={RelativeSource Mode=FindAncestor, AncestorType={x:Type toolkit:Popup}}}"
                    Grid.Column="1"></Button>
        </Grid>
        <CollectionView IsVisible="{Binding IsSearched}"
                        ItemsSource="{Binding CityChoices}">
            <CollectionView.ItemTemplate>
                <DataTemplate x:DataType="model:CityInfo">
                    <VerticalStackLayout HorizontalOptions="FillAndExpand"
                                             Padding="10,20,10,20"
                                             HeightRequest="100">
                            <VerticalStackLayout.GestureRecognizers>
                                <TapGestureRecognizer CommandParameter="{Binding .}" Command="{Binding Source={RelativeSource AncestorType={x:Type viewmodel:SetStaticLocalizationPopupViewModel}}, Path=SetChosenCityCommand}"></TapGestureRecognizer>
                            </VerticalStackLayout.GestureRecognizers>
                            <Label Style="{StaticResource CityInfoLabel}">
                                <Label.Text>
                                    <MultiBinding StringFormat="{}{0} - {1}">
                                        <Binding Path="CityName"></Binding>
                                        <Binding Path="CountryName"></Binding>
                                    </MultiBinding>
                                </Label.Text>
                            </Label>
                            <Label Style="{StaticResource CityInfoLabel}">
                                <Label.Text>
                                    <MultiBinding StringFormat="{}({0} | {1})">
                                        <Binding Path="Lat"></Binding>
                                        <Binding Path="Lon"></Binding>
                                    </MultiBinding>
                                </Label.Text>
                            </Label>
                        </VerticalStackLayout>
                </DataTemplate>
            </CollectionView.ItemTemplate>
            <CollectionView.EmptyView>
                <Label IsVisible="{Binding IsSearched}"
                       Text="Failed to find city with that name"
                       Style="{StaticResource CityInfoLabel}"
                       Padding="10,20,10,20"
                       TextColor="OrangeRed"></Label>
            </CollectionView.EmptyView>
        </CollectionView>
    </VerticalStackLayout>
</toolkit:Popup>

解决方案

针对Windows平台的布局限制问题,可尝试以下几种修复方式:

1. 动态绑定CollectionView高度

在ViewModel中添加计算属性,根据CityChoices的数量动态计算高度(每个Item的HeightRequest为100,可根据实际调整):

public int CollectionViewHeight => CityChoices.Count * 100;

然后在XAML中绑定到CollectionView的HeightRequest:

<CollectionView IsVisible="{Binding IsSearched}"
                ItemsSource="{Binding CityChoices}"
                HeightRequest="{Binding CollectionViewHeight}">

2. 调整Popup与内部布局的VerticalOptions

Windows平台的Popup设置VerticalOptions="Center"可能限制高度扩展,修改为平台差异化配置:

<toolkit:Popup ...
               VerticalOptions="{OnPlatform Default='Center', WinUI='Fill'}">

同时将内部VerticalStackLayout的VerticalOptions改为Start,让内容从顶部自动扩展:

<VerticalStackLayout ...
                     VerticalOptions="Start">

3. 用ScrollView包裹CollectionView

为CollectionView添加ScrollView容器,确保内容超出时可滚动,同时让Popup感知内容高度:

<ScrollView VerticalOptions="FillAndExpand"
            MaximumHeightRequest="{OnPlatform WinUI='400'}">
    <CollectionView IsVisible="{Binding IsSearched}"
                    ItemsSource="{Binding CityChoices}">
        <!-- 保留原有CollectionView内容 -->
    </CollectionView>
</ScrollView>

4. 手动触发Popup布局更新

在搜索命令执行完成后,调用Popup的InvalidateMeasure()强制重新计算布局:

public ICommand SearchCommand => new Command<Popup>(async (popup) =>
{
    // 原有搜索逻辑,填充CityChoices
    CityChoices = await GetCitiesAsync(CityName);
    
    // 强制Popup重新计算布局
    popup.Dispatcher.Dispatch(() =>
    {
        popup.InvalidateMeasure();
    });
});

内容的提问来源于stack exchange,提问作者Bartosz Zięba

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 13:03:20