.NET 11 Preview 6:MAUI CollectionView 登陆 Windows,Android Shell 加速 Handler 化

2026-07-29 31 预计阅读时间: 1 分钟
来源: infoq.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:9 分钟

.NET 11 Preview 6 对 .NET MAUI 的调整重点不是增加一批表层控件,而是继续改造跨平台 UI 的底层架构:新一代 CollectionView 实现扩展到 Windows,Android Shell 向 Handler 模型迁移,Native AOT 兼容性继续改善,媒体选择器也开始处理操作被系统中断后的恢复问题。这些变化分别指向列表一致性、平台代码可维护性、启动与部署,以及移动端生命周期可靠性。

Windows CollectionView 开始进入新实现

CollectionView 是 MAUI 应用中最常见、也最容易暴露平台差异的控件之一。数据虚拟化、滚动、选择、分组和模板复用都依赖原生平台实现。新一代实现进入 Windows,意味着 MAUI 正在缩小 Windows 与其他目标平台之间的实现代差。

对业务项目来说,升级后的验证重点不应只是“页面能否打开”,还要覆盖真实压力场景:

  • 快速滚动包含图片和复杂模板的长列表;
  • 在列表显示期间增删、排序或替换数据;
  • 单选、多选与取消选择;
  • 空数据、分组数据和增量加载;
  • 页面来回导航后的滚动位置与内存占用。

可以这样实践:先建立一个足够小的回归页面,用同一份代码分别在升级前后的 Windows 版本运行。下面的页面可直接加入 MAUI 项目,观察动态更新和选择行为。

<!-- MainPage.xaml -->
<ContentPage
    x:Class="MauiPreviewCheck.MainPage"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml">

    <Grid RowDefinitions="Auto,*" Padding="16" RowSpacing="12">
        <Button Text="追加 100 条" Clicked="OnAddItemsClicked" />

        <CollectionView
            x:Name="ItemsView"
            Grid.Row="1"
            ItemsSource="{Binding Items}"
            SelectionMode="Single"
            SelectionChanged="OnSelectionChanged">
            <CollectionView.ItemTemplate>
                <DataTemplate>
                    <Grid Padding="12" ColumnDefinitions="72,*">
                        <Label Text="{Binding Id}" FontAttributes="Bold" />
                        <Label Grid.Column="1" Text="{Binding Name}" />
                    </Grid>
                </DataTemplate>
            </CollectionView.ItemTemplate>
        </CollectionView>
    </Grid>
</ContentPage>
// MainPage.xaml.cs
using System.Collections.ObjectModel;

namespace MauiPreviewCheck;

public partial class MainPage : ContentPage
{
    public ObservableCollection<RowItem> Items { get; } = new();

    public MainPage()
    {
        InitializeComponent();
        BindingContext = this;
        AddItems(200);
    }

    private void OnAddItemsClicked(object sender, EventArgs e) => AddItems(100);

    private async void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (e.CurrentSelection.FirstOrDefault() is RowItem item)
            await DisplayAlert("已选择", item.Name, "确定");
    }

    private void AddItems(int count)
    {
        var start = Items.Count;
        for (var i = 0; i < count; i++)
            Items.Add(new RowItem(start + i + 1, $"订单 {start + i + 1}"));
    }
}

public sealed record RowItem(int Id, string Name);

这段代码使用公开的 MAUI 控件接口,不依赖 Preview 6 的内部类型。真正的差异应通过 Windows 上的滚动流畅度、选择事件、布局结果和内存曲线来判断,而不是通过编译是否成功来判断。

Android Shell 向 Handler 模型迁移意味着什么

MAUI 的 Handler 模型负责把跨平台虚拟视图映射到 Android、iOS、Windows 等平台的原生视图。Android Shell 向 Handler 模型移动,是一项架构层面的现代化工作:平台映射路径将更接近 MAUI 当前的控件扩展方式,也有利于减少旧渲染架构与新架构并存产生的维护成本。

普通 Shell 路由通常不需要因为内部迁移而重写,但使用平台定制代码的项目必须重点检查。高风险区域包括:

  • 自定义 Shell Renderer 或平台专用 Renderer;
  • 通过反射访问 Shell 内部字段;
  • 假设某个 Android 原生视图层级固定不变;
  • 第三方库对 Shell 导航栏、标签栏或 Flyout 的深度定制。

升级时应先搜索这些耦合点:

rg -n "ShellRenderer|Renderer|Handler|PlatformView|Microsoft\.Maui\.Controls\.Platform" .
dotnet build -f net11.0-android

其中 net11.0-android 需要已安装兼容的 .NET 11 Preview SDK 与 MAUI 工作负载。预览版的具体 SDK 版本应以团队实际安装版本为准,可以先运行 dotnet --list-sdks 确认。若项目只使用标准 ShellContent、路由和导航 API,重点应放在导航回退、深链、Flyout 与标签切换的行为回归,而不是提前改写业务代码。

Native AOT 与媒体选择器都在修补真实边界

Native AOT 兼容性改善值得关注,但“兼容性更好”不等于任意 MAUI 应用都能无修改发布。反射、运行时动态生成代码、缺少裁剪标注的依赖,以及某些平台绑定仍可能成为障碍。评估时应使用接近生产的发布配置,而不是只执行 Debug 构建。

可以这样检查 Android 发布链路:

dotnet workload list
dotnet restore
dotnet publish -f net11.0-android -c Release

如果项目计划采用 Native AOT,还应按照目标平台当前支持的发布属性建立独立实验分支,并记录包体、启动时间、发布时间和崩溃日志。不要仅为了追求 AOT 而隐藏裁剪告警;这些告警往往指出依赖真实存在的运行时假设。

媒体选择器的恢复支持解决的是另一类移动端问题。用户打开系统照片或文件界面时,应用可能进入后台,甚至因内存压力被系统终止。恢复能力改善后,应用更有机会继续处理被中断的选择流程,但业务层仍应把它当作可取消、可失败的外部操作。

下面是一个可改造的标准调用方式。它不假设 Preview 6 新增了未在摘要中说明的公开 API,而是展示业务层应保留的取消和异常边界:

private async Task<string?> PickPhotoAsync(CancellationToken cancellationToken)
{
    try
    {
        var result = await MediaPicker.Default.PickPhotoAsync(
            new MediaPickerOptions { Title = "选择一张照片" });

        cancellationToken.ThrowIfCancellationRequested();

        if (result is null)
            return null;

        var target = Path.Combine(FileSystem.CacheDirectory, result.FileName);
        await using var source = await result.OpenReadAsync();
        await using var destination = File.Create(target);
        await source.CopyToAsync(destination, cancellationToken);
        return target;
    }
    catch (OperationCanceledException)
    {
        return null;
    }
    catch (Exception ex)
    {
        System.Diagnostics.Debug.WriteLine($"媒体选择失败: {ex}");
        return null;
    }
}

生产项目还应避免把选择结果只保存在页面字段中。若后续需要上传,可以先将文件复制到应用目录,再把上传任务状态持久化;这样即使页面重建,也不必依赖已经失效的临时 URI 或流对象。

预览版适合验证,不适合无条件替换生产基线

Preview 6 展示了 MAUI 的明确方向:统一列表实现、继续 Handler 化、减少 AOT 阻力,并正面处理移动系统中断工作流。它适合用于兼容性实验和提前发现平台定制风险,但预览 SDK、工作负载与第三方组件仍可能变化。

建议采用一条受控升级路径:锁定预览 SDK,保留当前稳定分支,在 Windows 上建立 CollectionView 压力用例,在 Android 上覆盖 Shell 导航与系统回收场景,并用 Release 发布验证 Native AOT 和裁剪相关问题。只有当这些测试结果可重复、关键依赖已声明支持时,才应考虑扩大试用范围。


相关推荐