.NET MAUI for .NET 9 中的新增功能
.NET 9 中的 .NET Multi-platform App UI (.NET MAUI) 侧重于提升产品质量。 这包括扩展测试覆盖范围、端到端方案测试和 bug 修复。 若要详细了解 .NET MAUI 9 中的产品质量提升情况,请参阅以下发行说明:
- .NET MAUI 9 RC2
- .NET MAUI 9 RC1
- .NET MAUI 9 预览版 7
- .NET MAUI 9 预览版 6
- .NET MAUI 9 预览版 5
- .NET MAUI 9 预览版 4
- .NET MAUI 9 预览版 3
- .NET MAUI 9 预览版 2
- .NET MAUI 9 预览版 1
重要
由于使用外部依赖项(例如 Xcode 或 Android SDK Tools),.NET MAUI 支持策略与 .NET 和 .NET Core 支持策略不同。 有关详细信息,请参阅 .NET MAUI 支持策略。
与 Xcode 16 兼容(包括对 iOS 18、iPadOS 18、tvOS 18 和 macOS 15)的 SDK 支持,在使用 .NET MAUI 9 进行生成时是必需的。 Xcode 16 需要运行 macOS 14.5 或更高版本的 Mac。
在 .NET 9 中,.NET MAUI 作为 .NET 工作负载和多个 NuGet 包提供。 这种方法的优势在于,它使你能够轻松地将项目固定到特定版本,同时使你能够轻松预览未发布的版本或实验性版本。 创建新的 .NET MAUI 项目时,所需的 NuGet 包会自动添加到项目中。
最低部署目标
.NET MAUI 9 的最低部署目标要求为 iOS 12.2 和 Mac Catalyst 15.0 (macOS 12.0)。 Android 和 Windows 最低部署目标保持不变。 有关详细信息,请参阅 .NET MAUI 应用支持的平台。
新控件
.NET MAUI 9 包括两个新控件。
HybridWebView
HybridWebView 支持在 Web 视图中托管任意 HTML/JS/CSS 内容,并允许 Web 视图 (JavaScript) 中的代码与托管 Web 视图 (C#/.NET) 的代码之间进行通信。 例如,如果已有 React JS 应用,则可以将其托管在跨平台 .NET MAUI 本机应用中,并使用 C# 和 .NET 生成应用的后端。
若要使用 HybridWebView 生成 .NET MAUI 应用,需要:
- 应用的 Web 内容,由静态 HTML、JavaScript、CSS、图像和其他文件组成。
- 作为应用 UI 的一部分的 HybridWebView 控件。 这可以通过在应用的 XAML 中引用它来实现。
- Web 内容和 C#/.NET 中的代码,使用 HybridWebView API 在两个组件之间发送消息。
整个应用(包括 Web 内容)已打包并在设备上本地运行,并可以发布到对应的应用商店。 Web 内容托管在本机 Web 视图控件中,并在应用的上下文中运行。 应用的任何部分都可以访问外部 Web 服务,但这不是必须的。
有关详细信息,请参阅 HybridWebView。
适用于 Windows 的标题栏
该 TitleBar 控件提供在 Windows 上向应用添加自定义标题栏的功能:
可以在任何 TitleBar 上将 TitleBar 设置为 Window.TitleBar 属性的值:
<Window.TitleBar>
<TitleBar x:Name="TeamsTitleBar"
Title="Hello World"
Icon="appicon.png"
HeightRequest="46">
<TitleBar.Content>
<SearchBar Placeholder="Search"
PlaceholderColor="White"
MaximumWidthRequest="300"
HorizontalOptions="Fill"
VerticalOptions="Center" />
</TitleBar.Content>
</TitleBar>
</Window.TitleBar>
其在 C# 中使用的示例为:
Window window = new Window
{
TitleBar = new TitleBar
{
Icon = "titlebar_icon.png"
Title = "My App",
Subtitle = "Demo"
Content = new SearchBar { ... }
}
};
TitleBar 可通过其 Content、LeadingContent 和 TrailingContent 属性进行高度自定义:
<TitleBar Title="My App"
BackgroundColor="#512BD4"
HeightRequest="48">
<TitleBar.Content>
<SearchBar Placeholder="Search"
MaximumWidthRequest="300"
HorizontalOptions="Fill"
VerticalOptions="Center" />
</TitleBar.Content>
<TitleBar.TrailingContent>
<ImageButton HeightRequest="36"
WidthRequest="36"
BorderWidth="0"
Background="Transparent">
<ImageButton.Source>
<FontImageSource Size="16"
Glyph=""
FontFamily="SegoeMDL2"/>
</ImageButton.Source>
</ImageButton>
</TitleBar.TrailingContent>
</TitleBar>
以下屏幕截图显示了结果:
注意
将在未来版本中添加对 TitleBar
控件的 Mac Catalyst 支持。
有关详细信息,请参阅 TitleBar。
控件增强功能
.NET MAUI 9 包括控件增强功能。
BackButtonBehavior OneWay 绑定模式
Shell 应用中 BackButtonBehavior 的 IsVisible
和 IsEnabled
的绑定模式现在为 BindingMode.OneWay
,而不是 BindingMode.OneTime
。 这样就可以更轻松地通过数据绑定在运行时控制后退按钮的行为:
<ContentPage ...>
<Shell.BackButtonBehavior>
<BackButtonBehavior Command="{Binding BackCommand}"
IsVisible="{Binding IsBackButtonVisible}"
IconOverride="back.png" />
</Shell.BackButtonBehavior>
...
</ContentPage>
BlazorWebView
在 iOS 和 Mac Catalyst 18 上,.NET MAUI 9 将 BlazorWebView 中托管内容的默认行为更改为 localhost
。 用于托管内容的内部 0.0.0.1
地址不再有效,导致 BlazorWebView 无法加载任何内容并呈现为空矩形。
若要选择使用 0.0.0.1
地址,请将以下代码添加到 MauiProgram.cs中的 CreateMauiApp
方法:
// Set this switch to use the LEGACY behavior of always using 0.0.0.1 to host BlazorWebView
AppContext.SetSwitch("BlazorWebView.AppHostAddressAlways0000", true);
如果在 Android 上遇到 BlazorWebView 挂起的情况,则应在 MauiProgram
类的 CreateMauiApp
方法中启用 AppContext 开关:
AppContext.SetSwitch("BlazorWebView.AndroidFireAndForgetAsync", true);
此开关允许 BlazorWebView 触发和忘记发生的异步处置,从而修复 Android 上发生的大多数处置死锁。 有关详细信息,请参阅 修复 Android 上的处置死锁。
iOS 上的按钮
Button iOS 上的控件现在遵循间距、填充、边框宽度和边距比之前版本中更准确的边距。 现在,一 Button 个大图像的大小将调整为最大大小,同时考虑到间距、填充、边框宽度和边距。 但是,如果 Button 包含文本和图像,则可能无法容纳按钮中的所有内容,因此应手动调整图像大小以实现所需的布局。
CollectionView 和 CarouselView
.NET MAUI 9 在 iOS 和 Mac Catalyst 上包含两个可选的新处理程序,可提高 CollectionView
和 CarouselView
的性能和稳定性。 这些处理程序基于 UICollectionView
API。
若要选择使用这些处理程序,请将以下代码添加到 MauiProgram
类:
#if IOS || MACCATALYST
builder.ConfigureMauiHandlers(handlers =>
{
handlers.AddHandler<Microsoft.Maui.Controls.CollectionView, Microsoft.Maui.Controls.Handlers.Items2.CollectionViewHandler2>();
handlers.AddHandler<Microsoft.Maui.Controls.CarouselView, Microsoft.Maui.Controls.Handlers.Items2.CarouselViewHandler2>();
});
#endif
ContentPage
在 .NET MAUI 9 中,Mac Catalyst 以及 Android 和 iOS 也支持 HideSoftInputOnTapped 属性。
软键盘输入支持
.NET MAUI 9 添加了对 Password
、Date
和 Time
的新软键盘输入支持。 可以针对 Editor 和 Entry 控件启用这些功能:
<Entry Keyboard="Date" />
Text alignment
TextAlignment 枚举添加 Justify
成员,该成员可用于对齐文本控件中的文本。 例如,可以使用 HorizontalTextAlignment.Justify
水平对齐 Label 中的文本:
<Label Text="Lorem ipsum dolor sit amet, consectetur adipiscing elit. In facilisis nulla eu felis fringilla vulputate."
HorizontalTextAlignment="Justify"/>
TimePicker
TimePicker 获取一个 TimeSelected 事件,在所选时间更改时会触发该事件。 TimeSelected
事件附带的 TimeChangedEventArgs 对象具有 NewTime
和 OldTime
属性,分别指定新时间和旧时间。
WebView
WebView 添加了 ProcessTerminated
事件,当 WebView 进程意外结束时,将引发该事件。 此事件附带的 WebViewProcessTerminatedEventArgs
对象定义特定于平台的属性,这些属性表示进程失败的原因。
代码中已编译的绑定
用代码编写的绑定通常使用通过反射在运行时解析的字符串路径,执行此操作的开销因平台而异。 .NET MAUI 9 引入了一个附加 SetBinding 的扩展方法,该方法使用 Func
参数而不是字符串路径定义绑定:
// in .NET 8
MyLabel.SetBinding(Label.TextProperty, "Text");
// in .NET 9
MyLabel.SetBinding(Label.TextProperty, static (Entry entry) => entry.Text);
此编译的绑定方法提供以下好处:
- 通过在编译时而不是运行时解析绑定表达式,提升了数据绑定性能。
- 更好的开发人员故障排除体验,因为无效的绑定将被报告为生成错误。
- 编辑时的 Intellisense。
并非所有方法都可用于定义已编译的绑定。 表达式必须是简单的属性访问表达式。 以下示例展示了有效和无效的绑定表达式:
// Valid: Property access
static (PersonViewModel vm) => vm.Name;
static (PersonViewModel vm) => vm.Address?.Street;
// Valid: Array and indexer access
static (PersonViewModel vm) => vm.PhoneNumbers[0];
static (PersonViewModel vm) => vm.Config["Font"];
// Valid: Casts
static (Label label) => (label.BindingContext as PersonViewModel).Name;
static (Label label) => ((PersonViewModel)label.BindingContext).Name;
// Invalid: Method calls
static (PersonViewModel vm) => vm.GetAddress();
static (PersonViewModel vm) => vm.Address?.ToString();
// Invalid: Complex expressions
static (PersonViewModel vm) => vm.Address?.Street + " " + vm.Address?.City;
static (PersonViewModel vm) => $"Name: {vm.Name}";
此外,.NET MAUI 9 还添加了一个 BindingBase.Create 方法,该方法使用 Func
直接在对象上设置绑定,并返回绑定对象实例:
// in .NET 8
myEntry.SetBinding(Entry.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
new Binding(nameof(Entry.FontFamily), source: RelativeBindingSource.Self),
new Binding(nameof(Entry.FontSize), source: RelativeBindingSource.Self),
new Binding(nameof(Entry.FontAttributes), source: RelativeBindingSource.Self),
},
Converter = new StringConcatenationConverter()
});
// in .NET 9
myEntry.SetBinding(Entry.TextProperty, new MultiBinding
{
Bindings = new Collection<BindingBase>
{
Binding.Create(static (Entry entry) => entry.FontFamily, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontSize, source: RelativeBindingSource.Self),
Binding.Create(static (Entry entry) => entry.FontAttributes, source: RelativeBindingSource.Self),
},
Converter = new StringConcatenationConverter()
});
重要
在 NativeAOT 应用和启用了完全修整功能的应用中,需要使用编译的绑定,而不是基于字符串的绑定。
XAML 中已编译的绑定
在 .NET MAUI 8 中,已编译的绑定对于定义 Source
属性的任何 XAML 绑定表达式都禁用,并且不受多绑定支持。 .NET MAUI 9 中已删除这些限制。 有关编译定义属性的 Source
XAML 绑定表达式的信息,请参阅定义属性的Source
编译绑定。
默认情况下,.NET MAUI 9 为不使用已编译绑定的绑定生成警告。 有关 XAML 编译绑定警告的详细信息,请参阅 XAML 编译绑定警告。
依赖关系注入
在 Shell 应用中,无需再将页面注册到依赖项注入容器,除非你想要影响页面相对于容器AddSingleton
AddTransient
的生存期(或AddScoped
方法)。 有关这些方法的详细信息,请参阅 依赖项生存期。
处理程序断开连接
使用处理程序实现自定义控件时,每个平台处理程序实现都需要实现 DisconnectHandler() 方法,以执行任何本机视图清理,例如取消订阅事件。 但是,在 .NET MAUI 9 之前,.NET MAUI 有意不调用 DisconnectHandler() 实现。 相反,在选择清理控件时(例如,在应用中向后导航时),必须自行调用它。
在 .NET MAUI 9 中,处理程序会在可能得情况下自动与其控件断开连接,例如在应用中向后导航时。 在某些情况下,你可能不希望出现此行为。 因此,.NET MAUI 9 添加了 HandlerProperties.DisconnectPolicy
附加属性,用于控制处理程序何时与其控件断开连接。 此属性需要一个 HandlerDisconnectPolicy 参数,枚举定义以下值:
Automatic
,指示处理程序将自动断开连接。 这是附加属性HandlerProperties.DisconnectPolicy
的默认值。Manual
,表示处理程序必须通过调用 DisconnectHandler() 实现来手动断开连接。
以下示例演示如何设置 HandlerProperties.DisconnectPolicy
附加属性:
<controls:Video x:Name="video"
HandlerProperties.DisconnectPolicy="Manual"
Source="video.mp4"
AutoPlay="False" />
等效 C# 代码如下:
Video video = new Video
{
Source = "video.mp4",
AutoPlay = false
};
HandlerProperties.SetDisconnectPolicy(video, HandlerDisconnectPolicy.Manual);
此外,还有一种 DisconnectHandlers 扩展方法可将处理程序与给定 IView 断开连接:
video.DisconnectHandlers();
断开连接时,DisconnectHandlers 方法将沿控件树向下传播,直到完成或到达已设置手动策略的控件。
多窗口支持
.NET MAUI 9 添加了在 Mac Catalyst 和 Windows 上通过 Application.Current.ActivateWindow
方法将特定窗口置于前面的功能:
Application.Current?.ActivateWindow(windowToActivate);
本机 AOT 部署
在 .NET MAUI 9 中,可以选择在 iOS 和 Mac Catalyst 上进行本机 AOT 部署。 本机 AOT 部署生成已预先编译为本机代码的 .NET MAUI 应用。 这将产生以下优势:
- 减少应用包大小,通常小于 2.5 倍。
- 启动时间更快,通常快 2 倍。
- 生成时间更快。
有关详细信息,请参阅 iOS 和 Mac Catalyst 上的本机 AOT 部署。
本机嵌入
.NET MAUI 9 包括用于本机嵌入方案的完整 API,以前必须手动将其添加到项目中:
var mauiApp = MauiProgram.CreateMauiApp();
#if ANDROID
var mauiContext = new MauiContext(mauiApp.Services, window);
#else
var mauiContext = new MauiContext(mauiApp.Services);
#endif
var mauiView = new MyMauiContent();
var nativeView = mauiView.ToPlatform(mauiContext);
或者,可以使用 ToPlatformEmbedded
方法,传入应用所运行平台的 Window
:
var mauiApp = MauiProgram.CreateMauiApp();
var mauiView = new MyMauiContent();
var nativeView = mauiView.ToPlatformEmbedded(mauiApp, window);
在这两个示例中,nativeView
都是 mauiView
特定于平台的版本。
若要在 .NET MAUI 9 中启动本机嵌入式应用,请在 MauiAppBuilder
对象上调用 UseMauiEmbeddedApp
扩展方法:
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiEmbeddedApp<App>();
return builder.Build();
}
}
有关详细信息,请参阅本机嵌入。
项目模板
.NET MAUI 9 向 Visual Studio 添加了 .NET MAUI Blazor Hybrid 和 Web 应用 项目模板,该模板使用 .NET MAUI Blazor Hybrid 应用和 Blazor Web 应用创建解决方案,其能够在 Razor 类库项目中共享通用代码。
此模板也可用于 dotnew new
:
dotnet new maui-blazor-web -n AllTheTargets
资源字典
在 .NET MAUI 9 中,独立 XAML ResourceDictionary(不受代码隐藏文件支持)默认已编译 XAML。 要选择退出此行为,请在 XML 标头后指定 <?xaml-comp compile="false" ?>
。
修整
现在,通过将 MSBuild 属性设置为 $(TrimMode)
full
支持完全修整。 有关详细信息,请参阅 剪裁 .NET MAUI 应用。
剪裁不兼容
以下 .NET MAUI 功能与完整修整不兼容,将由修整程序删除:
- 绑定表达式,其中绑定路径设置为字符串。 请改用已编译的绑定。 有关详细信息,请参阅已编译的绑定。
- 隐式转换运算符在将不兼容类型的值分配给 XAML 中的属性时,或者当两个不同类型的属性使用数据绑定时。 相反,应为类型定义一个,并使用 <
a0TypeConverter/a0> 将其附加到该类型。 有关详细信息,请参阅 定义 TypeConverter 以替换隐式转换运算符。 - 使用扩展方法在 LoadFromXaml 运行时加载 XAML。 可以通过批注可以在运行时使用
DynamicallyAccessedMembers
属性或DynamicDependency
属性加载的所有类型来保证此 XAML 的安全。 但是,这很容易出错,不建议这样做。 - 使用 QueryPropertyAttribute.. 接收导航数据。 相反,应在需要接受查询参数的类型上实现 IQueryAttributable 接口。 有关更多信息,请参阅使用单一方法处理导航数据。
SearchHandler.DisplayMemberName
属性。 相反,应提供 ItemTemplate 来定义 SearchHandler 结果的外观。 有关详细信息,请参阅 “定义搜索结果项”外观。
剪裁功能开关
.NET MAUI 具有剪裁程序指令(称为功能开关),因此可以保留非剪裁安全功能的代码。 当生成属性设置为 full
以及 NativeAOT 时$(TrimMode)
,可以使用这些剪裁器指令:
MSBuild 属性 | 说明 |
---|---|
MauiEnableVisualAssemblyScanning |
设置为 true 时,.NET MAUI 将扫描程序集以获取实现 IVisual 的类型和 [assembly:Visual(...)] 属性,并将注册这些类型。 默认情况下,此生成属性设置为 false 。 |
MauiShellSearchResultsRendererDisplayMemberNameSupported |
设置为 false 时,将忽略 SearchHandler.DisplayMemberName 的值。 相反,应提供 ItemTemplate 来定义 SearchHandler 结果的外观。 默认情况下,此生成属性设置为 true 。 |
MauiQueryPropertyAttributeSupport |
当设置为 false 时,导航时将不会使用 [QueryProperty(...)] 属性来设置属性值。 相反,应实现 IQueryAttributable 接口以接受查询参数。 默认情况下,此生成属性设置为 true 。 |
MauiImplicitCastOperatorsUsageViaReflectionSupport |
设置为 false “设置为”时,.NET MAUI 在将值从一种类型转换为另一种类型时,不会查找隐式转换运算符。 这可能会影响具有不同类型的属性之间的绑定,以及设置具有不同类型值的可绑定对象的属性值。 相反,应为类型定义 TypeConverter,并使用 TypeConverterAttribute 特性将其附加到该类型。 默认情况下,此生成属性设置为 true 。 |
_MauiBindingInterceptorsSupport |
设置为 false 时,.NET MAUI 不会截获对 SetBinding 方法的任何调用,也不会尝试编译它们。 默认情况下,此生成属性设置为 true 。 |
MauiEnableXamlCBindingWithSourceCompilation |
设置为 true .NET MAUI 时,将编译所有绑定,包括使用该属性的 Source 绑定。 如果启用此功能,请确保所有绑定都具有正确的 x:DataType 编译方式,或者清除 x:Data={x:Null}} 数据类型(如果不应编译绑定)。 默认情况下,此生成属性仅在启用完全修整或本机 AOT 部署时设置为 true 。 |
这些 MSBuild 属性还具有等效 AppContext 开关:
MauiEnableVisualAssemblyScanning
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.IsIVisualAssemblyScanningEnabled
..MauiShellSearchResultsRendererDisplayMemberNameSupported
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.IsShellSearchResultsRendererDisplayMemberNameSupported
..MauiQueryPropertyAttributeSupport
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.IsQueryPropertyAttributeSupported
..MauiImplicitCastOperatorsUsageViaReflectionSupport
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.IsImplicitCastOperatorsUsageViaReflectionSupported
.._MauiBindingInterceptorsSupport
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.AreBindingInterceptorsSupported
..MauiEnableXamlCBindingWithSourceCompilation
MSBuild 属性具有一个名为 AppContextMicrosoft.Maui.RuntimeFeature.MauiEnableXamlCBindingWithSourceCompilationEnabled
..
使用功能开关的最简单方法是将相应的 MSBuild 属性放入应用的项目文件(*.csproj),这会导致从 .NET MAUI 程序集中剪裁相关代码。
Windows 应用部署
调试并将新的 .NET MAUI 项目部署到 Windows 时,.NET MAUI 9 中的默认行为是部署未打包的应用。 有关详细信息,请参阅在 Windows 上部署和调试 .NET MAUI 应用。
XAML 编译器错误代码
在 .NET MAUI 9 中,XAML 编译器错误代码已将其前缀从 XFC
更改为 XC
。 确保更新 $(WarningsAsErrors)
应用项目文件中的 、 $(WarningsNotAsErrors)
生成 $(NoWarn)
属性(如果使用)来引用新前缀。
XAML 标记扩展
实现 IMarkupExtension、IMarkupExtension<T>、IValueProvider 和 IExtendedTypeConverter 的所有类都需要通过 RequireServiceAttribute 或 AcceptEmptyServiceProviderAttribute 进行批注。 之所以需要这样做,是因为 .NET MAUI 9 中引入的 XAML 编译器优化可生成更高效的代码,这有助于缩小应用大小并提高运行时性能。
有关使用这些属性批注标记扩展的信息,请参阅服务提供商。
Xcode 同步
.NET MAUI 9 包括 Xcode 同步 (xcsync
),这是一种工具,让你能够使用 Xcode 通过 .NET 项目管理 Apple 特定文件,包括资产目录、plist 文件、情节提要和 xib 文件。 该工具有两个主要命令,一是根据 .NET 项目生成临时 Xcode 项目,二是将 Xcode 文件中的更改同步回 .NET 项目。
可以将 dotnet build
与 xcsync-generate
或 xcsync-sync
命令一起使用,以生成或同步这些文件,并传入项目文件和其他参数:
dotnet build /t:xcsync-generate
/p:xcSyncProjectFile=<PROJECT>
/p:xcSyncXcodeFolder=<TARGET_XCODE_DIRECTORY>
/p:xcSyncTargetFrameworkMoniker=<FRAMEWORK>
/p:xcSyncVerbosity=<LEVEL>
有关详细信息,请参阅 Xcode 同步。
弃用的 API
.NET MAUI 9 弃用了某些 API,这些 API 将在未来版本中完全删除。
Frame
Frame 控件在 .NET MAUI 9 中标记为已过时,并将在未来版本中完全删除。 应使用 Border 控件代替它。 有关详细信息,请参阅“边框”。
MainPage
应在 Window 上将 Page 属性设置为应用的首页,而不是在 Application 对象上使用 MainPage 属性定义应用的首页。 这是设置 MainPage 属性时 .NET MAUI 内部发生的情况,因此 MainPage 属性未引入任何标记为已过时的行为更改。
以下示例演示如何通过 CreateWindow
重写在 Window 上设置 Page 属性:
public partial class App : Application
{
public App()
{
InitializeComponent();
}
protected override Window CreateWindow(IActivationState? activationState)
{
return new Window(new AppShell());
}
}
访问 Application.Current.MainPage
该属性的代码现在应使用单个窗口访问 Application.Current.Windows[0].Page
应用的属性。 对于具有多个窗口的应用,请使用 Application.Current.Windows
集合标识正确的窗口,然后访问 Page
该属性。 此外,每个元素都有一个属性,当元素是当前窗口的一 Window
部分时可访问的属性, Page
可从中访问该属性(Window.Page
)。 平台代码可以使用扩展方法检索应用 IWindow 的对象 Microsoft.Maui.Platform.GetWindow
。
MainPage虽然该属性保留在 .NET MAUI 9 中,但在将来的版本中将完全删除。
兼容性布局
Microsoft.Maui.Controls.Compatibility 命名空间中的兼容性布局类已过时。
旧度量值调用
以下 VisualElement 度量方法已过时:
这些是不符合 .NET MAUI 布局预期功能的旧度量方法。
作为替代方法, VisualElement.Measure(Double, Double) 已引入该方法。 此 方法返回元素在设备上显示所需的最小尺寸。 边距不包括在度量中,但会与尺寸一起返回。 这是测量视图时要调用的首选方法。
此外,SizeRequest 结构已过时。 相反,应使用 Size。
从 .NET 8 升级到 .NET 9
若要将 .NET MAUI 项目从 .NET 8 升级到 .NET 9,请先安装具有 Visual Studio 17.12+ 的 .NET MAUI 工作负载,或者安装 Visual Studio Code 和 .NET MAUI 扩展和 .NET 以及 .NET MAUI 工作负载,或者安装独立安装程序和dotnet workload install maui
命令。
更新项目文件
若要将 .NET MAUI 应用从 .NET 8 更新到 .NET 9,请打开应用的项目文件(.csproj),并将目标框架名字对象(TPM)从 8 更改为 9。 如果使用 TFM,例如 net8.0-ios15.2
,请确保匹配平台版本或将其整个删除。 以下示例显示了 .NET 8 项目的 TFM:
<TargetFrameworks>net8.0-android;net8.0-ios;net8.0-maccatalyst;net8.0-tizen</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net8.0-windows10.0.19041.0</TargetFrameworks>
以下示例演示 .NET 9 项目的 TPM:
<TargetFrameworks>net9.0-android;net9.0-ios;net9.0-maccatalyst;net9.0-tizen</TargetFrameworks>
<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net9.0-windows10.0.19041.0</TargetFrameworks>
如果应用的项目文件直接或通过$(MauiVersion)
生成属性引用 .NET 8 版本的 Microsoft.Maui.Controls
NuGet 包,请将它更新为 .NET 9 版本。 然后,删除 NuGet 包的 Microsoft.Maui.Controls.Compatibility
包引用,前提是应用不使用此包中的任何类型。 此外,将 NuGet 包的 Microsoft.Extensions.Logging.Debug
包引用更新为最新的 .NET 9 版本。
如果应用面向 iOS 或 Mac Catalyst,请将这些平台的 $(SupportedOSPlatformVersion)
生成属性更新为 15.0:
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
调试并将新的 .NET MAUI 项目部署到 Windows 时,.NET 9 中的默认行为是部署未打包的应用。 若要采用此行为,请参阅 将打包的 .NET MAUI Windows 应用转换为解压缩。
在首次生成升级的应用之前,请先删除 bin
和 obj
文件夹。 任何生成错误和警告都将指导你执行后续步骤。
更新 XAML 编译器错误代码
XAML 编译器错误代码已将其前缀更改为 XFC
XC
,因此$(WarningsAsErrors)
$(WarningsNotAsErrors)
更新应用$(NoWarn)
项目文件中的属性(如果使用)来引用新前缀。
解决已编译绑定的新 XAML 编译器警告
将为不使用已编译绑定的绑定生成警告,需要解决这些问题。 有关详细信息,请参阅 XAML 编译的绑定警告。
更新 XAML 标记扩展
XAML 标记扩展需要用 RequireServiceAttribute 或 AcceptEmptyServiceProviderAttribute. 这是必需的,因为 XAML 编译器优化可实现更高效的代码的生成,这有助于减小应用大小并提高运行时性能。 有关详细信息,请参阅服务提供商。
地址已弃用的 API
.NET MAUI 9 弃用了某些 API,这些 API 将在未来版本中完全删除。 因此,解决有关已弃用 API 的任何生成警告。 有关详细信息,请参阅 已弃用的 API。
采用设置 Source 属性的已编译绑定
可以选择编译设置属性的 Source
绑定,以利用更好的运行时性能。 有关详细信息,请参阅定义属性的Source
编译绑定。
采用 C 中的已编译绑定#
可以选择编译在代码中声明的绑定表达式,以利用更好的运行时性能。 有关详细信息,请参阅 代码中的已编译绑定。
采用完整修整
可以通过将 MSBuild 属性设置为 $(TrimMode)
full
剪裁 .NET MAUI 应用。
在受支持的平台上采用 NativeAOT 部署
可以选择在 iOS 和 Mac Catalyst 上进行本机 AOT 部署。 本机 AOT 部署生成已预先编译为本机代码的 .NET MAUI 应用。 有关详细信息,请参阅 iOS 和 Mac Catalyst 上的本机 AOT 部署。
.NET for Android
.NET 9 中的适用于 Android 的 .NET,它增加了对 API 35 的支持,包括减少生成时间的工作,以及提高应用的可剪裁性,以减少大小并提高性能。 有关 .NET 9 中适用于 Android 的 .NET 的详细信息,请参阅以下发行说明:
- 适用于 Android 9 RC2 的 .NET
- 适用于 Android 9 RC1 的 .NET
- .NET for Android 9 预览版 7
- .NET for Android 9 预览版 6
- .NET for Android 9 预览版 5
- .NET for Android 9 预览版 4
- .NET for Android 9 预览版 3
- .NET for Android 9 预览版 2
- .NET for Android 9 预览版 1
资产包
.NET 9 中的适用于 Android 的 .NET 引入了将资产放入单独的包(称为 资产包)的功能。 此功能支持上传通常大于 Google Play 允许的基本包大小的游戏和应用。 通过将这些资产放入单独的包中,可以上传大小高达 2Gb 的包,而非只能上传 200Mb 大小的基本包。
重要
资产包只能包含资产。 对于 .NET for Android,这意味着具有 AndroidAsset
生成操作的项目。
.NET MAUI 应用通过 MauiAsset
生成操作定义资产。 可以通过 AssetPack
属性指定资产包:
<MauiAsset
Include="Resources\Raw\**"
LogicalName="%(RecursiveDir)%(Filename)%(Extension)"
AssetPack="myassetpack" />
注意
其他平台将忽略其他元数据。
如果要将特定项放置在资产包中,则可以使用 Update
属性来定义 AssetPack
元数据:
<MauiAsset Update="Resources\Raw\MyLargeAsset.txt" AssetPack="myassetpack" />
资产包可以有不同的传递选项,用于控制何时在设备上安装资产:
- 安装时包与应用同时安装。 此类型包的大小最多可为 1Gb,但只能有一个此类型的包。 此传递类型使用
InstallTime
元数据指定。 - 应用完成安装后不久,即会安装快速跟进包。 在安装这种类型的包时,该应用将能够启动,因此应该先检查它是否已完成安装,然后再尝试使用资产。 此类资产包的大小可达 512Mb。 此传递类型使用
FastFollow
元数据指定。 - 按需包只有在应用专门发出请求时,才会下载到设备。 所有资产包的总大小不能超过 2Gb,最多可以有 50 个单独的资产包。 此传递类型使用
OnDemand
元数据指定。
在 .NET MAUI 应用中,可以使用 MauiAsset
上的 DeliveryType
属性指定传递类型:
<MauiAsset Update="Resources\Raw\myvideo.mp4" AssetPack="myassetpack" DeliveryType="FastFollow" />
有关 Android 资产包的详细信息,请参阅 Android 资产包。
Android 15 支持
.NET 9 中的 .NET for Android 添加了适用于 Android 15 的 .NET 绑定(API 35)。 若要为这些 API 生成,请将项目的目标框架更新为 net9.0-android
:
<TargetFramework>net9.0-android</TargetFramework>
注意
还可以指定 net9.0-android35
为目标框架,但数字 35 可能会在将来的 .NET 版本中更改,以匹配较新的 Android OS 版本。
默认情况下,64 位体系结构
默认情况下,.NET 9 中的适用于 Android 的 .NET 不再生成以下运行时标识符(RID):
android-arm
android-x86
这应该可以缩短生成时间并减小 Android .apk
文件的大小。 请注意,Google Play 支持按体系结构拆分应用捆绑包。
如果需要为这些体系结构生成,可以将它们添加到项目文件(.csproj):
<RuntimeIdentifiers>android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>
或在多目标项目中:
<RuntimeIdentifiers Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">android-arm;android-arm64;android-x86;android-x64</RuntimeIdentifiers>
Android 封送方法
对 .NET 9 中 Android 封送方法的改进使该功能在应用程序中更加可靠,但尚不是默认值。 启用此功能会导致 测试应用中的性能提高约 10%。
可以通过属性在项目文件(.csproj) $(AndroidEnableMarshalMethods)
中启用 Android 封送方法:
<PropertyGroup>
<AndroidEnableMarshalMethods>true</AndroidEnableMarshalMethods>
</PropertyGroup>
有关该功能的特定详细信息,请参阅 GitHub 上的功能文档 或 实现 。
剪裁增强功能
在 .NET 9 中,Android API 程序集(Mono.Android.dll,Java.Interop.dll)现在完全兼容剪裁。 若要选择完全修整,请在 $(TrimMode)
项目文件中设置属性(.csproj):
<PropertyGroup>
<TrimMode>Full</TrimMode>
</PropertyGroup>
这还支持剪裁分析器,以便针对任何有问题的 C# 代码引入警告。
有关详细信息,请参阅 剪裁粒度。
.NET for iOS
iOS、tvOS、Mac Catalyst 和 macOS 上的 .NET 9 对以下平台版本使用 Xcode 16.0:
- iOS:18.0
- tvOS:18.0
- Mac Catalyst:18.0
- macOS:15.0
要详细了解 iOS、tvOS、Mac Catalyst 和 macOS 上的 .NET 9,请参阅以下发行说明:
- .NET 9.0.1xx RC2
- .NET 9.0.1xx RC1
- .NET 9.0.1xx 预览版 7
- .NET 9.0.1xx 预览版 6
- .NET 9.0.1xx 预览版 5
- .NET 9.0.1xx 预览版 4
- .NET 9.0.1xx 预览版 3
- .NET 9.0.1xx 预览版 2
- .NET 9.0.1xx 预览版 1
绑定
.NET for iOS 9 引入了对多目标 .NET 版本进行 iOS 绑定的功能。 例如,可能需要为两个不同的 iOS 版本生成某个库项目:
<TargetFrameworks>net9.0-ios17.0;net9.0-ios17.2</TargetFrameworks>
这将生成两个库,一个使用 iOS 17.0 绑定,一个使用 iOS 17.2 绑定。
重要
应用项目应始终面向最新的 iOS SDK。
剪裁增强功能
在 .NET 9 中,iOS 和 Mac Catalyst 程序集(Microsoft.iOS.dll、 Microsoft.MacCatalyst.dll 等)现在完全兼容剪裁。 若要选择完全修整,请在 $(TrimMode)
项目文件中设置属性(.csproj):
<PropertyGroup>
<TrimMode>Full</TrimMode>
</PropertyGroup>
这还支持剪裁分析器,以便针对任何有问题的 C# 代码引入警告。
有关详细信息,请参阅 剪裁粒度。
适用于 iOS 和 Mac Catalyst 的本机 AOT
在 .NET for iOS 9 中,适用于 iOS 和 Mac Catalyst 的本机提前 (AOT) 编译利用完整剪裁来减少应用的包大小和启动性能。 NativeAOT 基于完全修整而构建,同时选择加入新的运行时。
重要
应用及其依赖项必须完全可剪裁才能利用此功能。
NativeAOT 要求使用零剪裁器警告生成应用程序,以便证明应用程序在运行时正常工作。