深入了解.NET MAUI项目结构与应用启动流程

Viewed 0

安装并设定 .NET MAUI 工具之后,您就可以使用 Visual Studio 来构建 .NET MAUI(多平台应用程序用户界面)应用程序。在本单元中,您将了解 Visual Studio 中的 .NET MAUI 模板结构,并使用此模板创建跨平台的移动和桌面应用程序。

如何开始使用

若要使用 Visual Studio 创建新的 .NET MAUI 项目,请在“创建新项目”对话框中选择 .NET MAUI 项目类型,然后选择“.NET MAUI 应用程序”模板。遵循向导中的步骤来命名项目并指定位置。

新创建的 .NET MAUI 项目包含如下所示的项:

.NET MAUI 项目结构和应用程序启动

项目内容包括下列项:

  • App.xaml:此文件定义应用程序在 XAML(Extensible Application Markup Language)页面布局中使用的应用程序资源。默认资源位于 Resources 文件夹中,并为每个 .NET MAUI 内置控件定义应用程序整体色彩和默认样式。以下代码显示两个合并在一起的资源字典:
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
               xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
               xmlns:local="clr-namespace:MyMauiApp"
               x:Class="MyMauiApp.App">
      <Application.Resources>
          <ResourceDictionary>
              <ResourceDictionary.MergedDictionaries>
                  <ResourceDictionary Source="Resources/Colors.xaml" />
                  <ResourceDictionary Source="Resources/Styles.xaml" />
              </ResourceDictionary.MergedDictionaries>
          </ResourceDictionary>
      </Application.Resources>
</Application>
  • App.xaml.cs:这文件是 App.xaml 文件的代码后置。其定义 App 类。此类在运行时呈现应用程序。该类创建初始窗口,并将其指派给 MainPage 属性;此属性决定应用程序开始执行时显示哪个页面。此外,此类还可让您覆盖常用的平台中立应用程序生命周期事件处理程序。事件包括 OnStartOnResumeOnSleep。这些处理程序定义为 Application 基类的成员。以下代码显示默认模板的示例,以及覆盖这些事件的能力:
public partial class App : Application
{
      public App()
      {
          InitializeComponent();
      }

      protected override Window CreateWindow(IActivationState? activationState)
      {
          return new Window(new AppShell());
      }

      // Optional events to implement for the application lifecycle. The Window created
      // above also has lifecycle events that can be used to track the Window lifecycle.
      protected override void OnStart()
      {
          base.OnStart();
      }

      protected override void OnResume()
      {
          base.OnResume();
      }

      protected override void OnSleep()
      {
          base.OnSleep();
      }
}

您还可以覆盖应用程序第一次开始执行时的平台专用生命周期事件。

  • AppShell.xaml:此文件是 .NET MAUI 应用程序的主要结构。 .NET MAUI Shell 提供许多有利于多平台应用程序的功能,包括应用程序样式、URI 型浏览,以及页面布局选项(包括飞出窗口浏览和应用程序根目录的选项卡)。默认模板提供单一页面(或 ShellContent),在应用程序启动时会放大。
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
    x:Class="MyMauiApp.AppShell"
    xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
    xmlns:local="clr-namespace:MyMauiApp"
    Shell.FlyoutBehavior="Flyout"
    Title="MyMauiApp">
    <ShellContent
        Title="Home"
        ContentTemplate="{DataTemplate local:MainPage}"
        Route="MainPage" />
</Shell>
  • MainPage.xaml:此文件包含用户界面定义。 MAUI 应用程序模板生成的示例应用程序包含两个标签、一个按钮和一个图像。控件通过 VerticalStackLayout 括住的 ScrollView 来排列。VerticalStackLayout 元素将控件垂直排列(堆叠),ScrollView 可在视图过大而无法显示在设备上时提供滚动条。您打算将此文件的内容替换为自己的 UI 页面布局。如果您有多页应用程序,也可以定义更多 XAML 页面。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
              x:Class="MyMauiApp.MainPage">
      <ScrollView>
          <VerticalStackLayout
              Padding="30,0"
              Spacing="25">
              <Image
                  Source="dotnet_bot.png"
                  HeightRequest="185"
                  Aspect="AspectFit"
                  SemanticProperties.Description="dot net bot in a hovercraft number nine" />
              <Label
                  Text="Hello, World!"
                  Style="{StaticResource Headline}"
                  SemanticProperties.HeadingLevel="Level1" />
              <Label
                  Text="Welcome to &#10;.NET Multi-platform App UI"
                  Style="{StaticResource SubHeadline}"
                  SemanticProperties.HeadingLevel="Level2"
                  SemanticProperties.Description="Welcome to dot net Multi platform App U I" />
              <Button
                  x:Name="CounterBtn"
                  Text="Click me"
                  SemanticProperties.Hint="Counts the number of times you click"
                  Clicked="OnCounterClicked"
                  HorizontalOptions="Fill" />
          </VerticalStackLayout>
      </ScrollView>
</ContentPage>
  • MainPage.xaml.cs:这文件包含页面的代码后置。在此文件中,您定义各种事件处理程序的逻辑,以及页面上的控件所触发的其他动作。示例代码针对页面上的按钮实现 Clicked 事件的处理程序。代码只是递增计数器变量,并在页面上的标签中显示结果。 MAUI Essentials 库中提供的 Semantic 服务支持可访问性。SemanticScreenReader 类的 Announce 静态方法指定当用户选取按钮时,由屏幕阅读器念出的文字:
namespace MyMauiApp;
public partial class MainPage : ContentPage
{
      int count = 0;
      public MainPage()
      {
          InitializeComponent();
      }
      private void OnCounterClicked(object sender, EventArgs e)
      {
          count++;
          if (count == 1)
              CounterBtn.Text = $"Clicked {count} time";
          else
              CounterBtn.Text = $"Clicked {count} times";
          SemanticScreenReader.Announce(CounterBtn.Text);
      }
}
  • MauiProgram.cs:每个原生平台各有不同的起点来创建和初始化应用程序。您可以在项目的 Platforms 文件夹中找到此代码。此代码是平台专用,但最后会调用 MauiProgram 静态类的 CreateMauiApp 方法。您可以使用 CreateMauiApp 方法创建应用程序建立器对象,以设定应用程序。您至少需要使用应用程序建立器对象的 UseMauiApp 泛型方法,指定描述应用程序的类;类型参数(<App>)指定应用程序类。应用程序建立器也提供方法来执行作业,例如注册字体、设定依赖注入的服务、注册控件的自定义处理程序等。以下代码示范使用应用程序建立器来注册字体:
using Microsoft.Extensions.Logging;
namespace MyMauiApp;
public static class MauiProgram
{
      public static MauiApp CreateMauiApp()
      {
          var builder = MauiApp.CreateBuilder();
          builder
              .UseMauiApp<App>()
              .ConfigureFonts(fonts =>
              {
                  fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
                  fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
              });
#if DEBUG
          builder.Logging.AddDebug();
#endif
          return builder.Build();
      }
}
  • Platforms:此文件夹包含平台专用的初始化代码文件和资源。有 Android、iOS、MacCatalyst、Tizen 和 Windows 的文件夹。在运行时,应用程序以平台专用的方式启动。启动流程的绝大部分已由 MAUI 库的本质所抽离,但这些文件夹中的代码文件有机制可链接您自己的自定义初始化。重点是初始化完成时,平台专用代码会调用 MauiProgram.CreateMauiApp 方法,此方法再创建并执行 App 对象,如前文所述。例如,Android 文件夹中的 MainApplication.cs 文件、iOSMacCatalyst 文件夹中的 AppDelegate.cs 文件,以及 Windows 文件夹中的 App.xaml.cs 文件都包含覆盖:
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

.NET MAUI 应用程序启动时的控制流程如下:从原生专用启动流向创建 MAUI 应用程序函数,最终流向应用程序对象构造函数。

项目资源

主项目的项目文件(.csproj)包含几个值得注意的区段。初始 PropertyGroup 指定项目的目标平台架构,以及一些项目,例如应用程序标题、标识符、版本、显示版本和支持的操作系统。您可以视需要修改这些属性。

<Project Sdk="Microsoft.NET.Sdk">
	<PropertyGroup>
		<TargetFrameworks>net10.0-android;net10.0-ios;net10.0-maccatalyst</TargetFrameworks>
		<TargetFrameworks Condition="$([MSBuild]::IsOSPlatform('windows'))">$(TargetFrameworks);net10.0-windows10.0.19041.0</TargetFrameworks>
		<OutputType>Exe</OutputType>
		<RootNamespace>MyMauiApp</RootNamespace>
		<UseMaui>true</UseMaui>
		<SingleProject>true</SingleProject>
		<ImplicitUsings>enable</ImplicitUsings>
		<Nullable>enable</Nullable>
		<!-- Display name -->
		<ApplicationTitle>MyMauiApp</ApplicationTitle>
		<!-- App Identifier -->
		<ApplicationId>com.companyname.mymauiapp</ApplicationId>
		<!-- Versions -->
		<ApplicationDisplayVersion>1.0</ApplicationDisplayVersion>
		<ApplicationVersion>1</ApplicationVersion>
		<!-- To develop, package, and publish an app to the Microsoft Store, see: https://aka.ms/MauiTemplateUnpackaged -->
		<WindowsPackageType>None</WindowsPackageType>
		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'ios'">15.0</SupportedOSPlatformVersion>
		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'maccatalyst'">15.0</SupportedOSPlatformVersion>
		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'android'">21.0</SupportedOSPlatformVersion>
		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</SupportedOSPlatformVersion>
		<TargetPlatformMinVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'windows'">10.0.17763.0</TargetPlatformMinVersion>
		<SupportedOSPlatformVersion Condition="$([MSBuild]::GetTargetPlatformIdentifier('$(TargetFramework)')) == 'tizen'">6.5</SupportedOSPlatformVersion>
	</PropertyGroup>
    ...
</Project>

针对应用程序加载时,在出现第一个窗口之前出现的启动显示画面,初始属性群组下方的 ItemGroup 区段可让您指定图像和色彩。对于应用程序使用的字体、图像和资产,您也可以设定默认位置。

<Project Sdk="Microsoft.NET.Sdk">
    ...
	<ItemGroup>
		<!-- App Icon -->
		<MauiIcon Include="Resources\AppIcon\appicon.svg"
                  ForegroundFile="Resources\AppIcon\appiconfg.svg"
                  Color="#512BD4" />
		<!-- Splash Screen -->
		<MauiSplashScreen Include="Resources\Splash\splash.svg"
                          Color="#512BD4"
                          BaseSize="128,128" />
		<!-- Images -->
		<MauiImage Include="Resources\Images\*" />
		<MauiImage Update="Resources\Images\dotnet_bot.png"
                   Resize="True" BaseSize="300,185" />
		<!-- Custom Fonts -->
		<MauiFont Include="Resources\Fonts\*" />
		<!-- Raw Assets (also remove the "Resources\Raw" prefix) -->
		<MauiAsset Include="Resources\Raw\**"
                   LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
	</ItemGroup>
    ...
</Project>

在 Visual Studio 的“解决方案资源管理器”窗口中,您可以展开 Resources 文件夹来查看这些项。您可以将应用程序所需的其他任何字体、图像及其他图形资源,新增至此文件夹和子文件夹。

您应该在应用程序开始执行时,向应用程序建立器对象注册任何新增至字体文件夹的字体。回想一下,MauiProgram 类中的 CreateMauiApp 方法使用 ConfigureFonts 方法登记字体:

public static class MauiProgram
{
    public static MauiApp CreateMauiApp()
    {
        var builder = MauiApp.CreateBuilder();
        builder
            ...
            .ConfigureFonts(fonts =>
            {
                fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
            });
        ...
    }
}

在此示例中,AddFont 方法将字体与名称 OpenSansRegular 建立关联。在页面的 XAML 描述、应用程序或共享资源字典中,您可以指定此字体来设定项目的格式:

<ResourceDictionary ..>
    ...
    <Style TargetType="Button">
        ...
        <Setter Property="FontFamily" Value="OpenSansRegular" />
        ...
    </Style>
</ResourceDictionary>

使用 Platforms 文件夹下的 AndroidiOS 文件夹中的 Resources 文件夹,以存放 Android 和 iOS 平台专用的资源。

0 Answers