.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(可扩展应用程序标记语言)布局中定义应用程序资源。默认资源位于 Resources 文件夹中,为每个 .NET MAUI 内置控件定义应用范围内的颜色和默认样式。该文件合并两个资源字典:Resources/Colors.xamlResources/Styles.xaml。示例代码如下:
<?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。示例代码展示默认模板和事件重写能力:
public partial class App : Application
{
      public App()
      {
          InitializeComponent();
      }

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

      // 可选的生命周期事件实现
      protected override void OnStart()
      {
          base.OnStart();
      }

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

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

注意,当应用首次运行时,还可重写特定于平台的生命周期事件,这将在后续说明。

  • AppShell.xaml:此文件是 .NET MAUI 应用的主要结构,提供应用样式、基于 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:此文件包含用户界面定义,示例应用包括两个标签、一个按钮和一个图像,使用 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 事件处理程序,递增计数器并更新标签文本。使用 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 方法。此方法通过应用生成器对象配置应用程序,至少使用 UseMauiApp 泛型方法指定应用程序类,并提供注册字体、配置服务等方法。示例代码展示字体注册:
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 的特定平台初始化代码文件和资源。初始化后,平台特定代码调用 MauiProgram.CreateMauiApp 方法,创建并运行 App 对象。例如,Android 的 MainApplication.cs、iOS 和 MacCatalyst 的 AppDelegate.cs,以及 Windows 的 App.xaml.cs 都包含重写:
protected override MauiApp CreateMauiApp() => MauiProgram.CreateMauiApp();

.NET MAUI 应用启动时,控制流从本机特定启动开始,到创建 MAUI 应用函数,最后到应用对象构造函数。

项目资源

主项目的项目文件 (.csproj) 包含重要部分。初始 PropertyGroup 指定目标平台框架、应用程序标题、ID、版本、支持的操作系统等属性,可根据需要修改。示例片段:

<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>

		<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 -->
		<MauiAsset Include="Resources\Raw\**"
                   LogicalName="%(RecursiveDir)%(Filename)%(Extension)" />
	</ItemGroup>

    ...

</Project>

在 Visual Studio 的“解决方案资源管理器”中,可展开 Resources 文件夹查看这些项,并可添加其他字体、图像和图形资源。应用运行时,需在 CreateMauiApp 方法中注册添加到 fonts 文件夹的字体,使用 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>

此外,Resources 文件夹用于 Android,而 Platforms 文件夹下的 iOS 文件夹用于 iOS 特定资源,确保跨平台兼容性。

0 Answers