.NET MAUI 窗口

.NET Multi-platform App UI (.NET MAUI) Window 类提供创建、配置、显示和管理多窗口的功能。

Window 定义以下属性:

  • FlowDirection,类型为 FlowDirection,定义窗口的 UI 元素布局的方向。
  • Height,类型为 double,指定 Windows 上窗口的高度。
  • MaximumHeight,类型为 double,表示桌面平台上窗口的最大高度。 有效值介于 0 和 double.PositiveInfinity 之间。
  • MaximumWidth,类型为 double,表示桌面平台上窗口的最大宽度。 有效值介于 0 和 double.PositiveInfinity 之间。
  • MinimumHeight,类型为 double,表示桌面平台上窗口的最小高度。 有效值介于 0 和 double.PositiveInfinity 之间。
  • MinimumWidth,类型为 double,表示桌面平台上窗口的最小宽度。 有效值介于 0 和 double.PositiveInfinity 之间。
  • Overlays,类型为 IReadOnlyCollection<IWindowOverlay>,表示窗口覆盖的集合。
  • Page,类型为 Page,指示窗口显示的页面。 此属性是 Window 类的内容属性,因此不需要显式设置。
  • Title,类型为 string,表示窗口的标题。
  • Width,类型为 double,指定 Windows 上的窗口宽度。
  • X,类型为 double,指定 Windows 上窗口的 X 坐标。
  • Y,类型为 double,指定 Windows 上窗口的 Y 坐标。

所有这些属性(Overlays 属性除外)都由 BindableProperty 对象提供支持,这意味着它们可以作为数据绑定的目标,并进行样式设置。

Window 类定义以下事件:

  • Created,在创建窗口时引发。
  • Resumed,当窗口从休眠状态恢复时引发。
  • Activated,在激活窗口时引发。
  • Deactivated,在停用窗口时引发。
  • Stopped,在窗口停止时引发。
  • Destroying,在窗口被销毁时引发。
  • SizeChanged,当窗口更改大小时在桌面平台上引发。
  • Backgrounding 附带 BackgroundingEventArgs 对象,当窗口关闭或进入后台状态时,iOS 和 Mac Catalyst 上会引发该对象。 此事件可用于将任何 string 状态保存到 BackgroundingEventArgs 对象的 State 属性,OS 将保留该状态,直到恢复窗口时为止。 恢复窗口时,状态通过 CreateWindow 方法的 IActivationState 参数提供。
  • DisplayDensityChanged,附带 DisplayDensityChangedEventArgs 对象,当窗口的每英寸点数 (DPI) 发生更改时在 Android 和 Windows 上引发。

有关生命周期事件及其关联替代的详细信息,请参阅应用生命周期

Window 类还定义以下模式导航事件:

  • ModalPopped,包含 ModalPoppedEventArgs,以模式方式弹出视图时引发。
  • ModalPopping,包含 ModalPoppingEventArgs,以模式方式弹出视图时引发。
  • ModalPushed,包含 ModalPushedEventArgs,以模式方式推送视图后引发。
  • ModalPushing,包含 ModalPushingEventArgs,以模式方式推送视图时引发。
  • PopCanceled,在取消模式弹出时引发。

VisualElement 类具有公开父级 Window 对象的 Window 属性。 可以从任何页面、布局或视图访问此属性,以操作 Window 对象。

创建窗口

默认情况下,在 App 类中将 MainPage 属性设置为 Page 对象时,.NET MAUI 会创建一个 Window 对象。 但是,也可以重写 App 类中的 CreateWindow 方法以创建 Window 对象:

namespace MyMauiApp
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();

            MainPage = new MainPage();
        }

        protected override Window CreateWindow(IActivationState activationState)
        {
            Window window = base.CreateWindow(activationState);

            // Manipulate Window object

            return window;
        }
    }
}

虽然 Window 类有默认构造函数和接受 Page 参数(表示应用的根页)的构造函数,但还可以调用基 CreateWindow 方法来返回 Window 对象创建的 .NET MAUI。

默认情况下,.NET MAUI 应用会重写 CreateWindow 类中 App 的方法以创建对象 Window

namespace MyMauiApp
{
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
        }

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

Window 类具有默认构造函数和接受 Page 参数的构造函数,该参数表示应用的根页。

此外,还可以创建自己的 Window 派生对象:

namespace MyMauiApp
{
    public class MyWindow : Window
    {
        public MyWindow() : base()
        {
        }

        public MyWindow(Page page) : base(page)
        {
        }

        // Override Window methods
    }
}

然后,可以通过在 App 类的 CreateWindow 重写中创建 MyWindow 对象来使用 Window 派生类。

无论 Window 对象是如何创建的,它都将是应用中根页的父级。

多窗口支持

可以在 Android、iPad 上的 iOS (iPadOS)、Mac Catalyst 和 Windows 上同时打开多个窗口。 可以通过创建 Window 对象,并使用 Application 对象上的 OpenWindow 方法将其打开的方式实现此目的:

Window secondWindow = new Window(new MyPage());
Application.Current?.OpenWindow(secondWindow);

IReadOnlyList<Window> 类型的 Application.Current.Windows 集合保持对使用 Application 对象注册的所有 Window 对象的引用。

可以在 Mac Catalyst 和 Windows 上使用 Application.Current.ActivateWindow 方法将特定窗口置于最前面:

Application.Current?.ActivateWindow(secondWindow);

可以使用 Application.Current.CloseWindow 方法关闭 Windows:

// Close a specific window
Application.Current?.CloseWindow(secondWindow);

// Close the active window
Application.Current?.CloseWindow(GetParentWindow());

重要

多窗口支持适用于 Windows,无需进行其他配置。 但是,Android、iPadOS 和 Mac Catalyst 需要额外的配置。

Android 配置

要在 Android 上使用多窗口支持,你必须将 Platforms > Android > MainActivity.cs 中的 MainActivity 启动模式从 LaunchMode.SingleTop 更改为 LaunchMode.Multiple :

using Android.App;
using Android.Content.PM;
using Android.OS;

namespace MyMauiApp;

[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.Multiple, ...)]
public class MainActivity : MauiAppCompatActivity
{
}

iPadOS 和 macOS 配置

若要在 iPadOS 和 Mac Catalyst 上使用多窗口支持,请将一个名为 SceneDelegate 的类添加至“平台”>“iOS”以及“平台”>“MacCatalyst”文件夹:

using Foundation;
using Microsoft.Maui;
using UIKit;

namespace MyMauiApp;

[Register("SceneDelegate")]
public class SceneDelegate : MauiUISceneDelegate
{
}

然后,在 XML 编辑器中,打开“平台”>“iOS”> Info.plist 文件以及“平台”>“MacCatalyst”> Info.plist 文件,并将以下 XML 添加到每个文件的末尾:

<key>UIApplicationSceneManifest</key>
<dict>
  <key>UIApplicationSupportsMultipleScenes</key>
  <true/>
  <key>UISceneConfigurations</key>
  <dict>
    <key>UIWindowSceneSessionRoleApplication</key>
    <array>
      <dict>
        <key>UISceneConfigurationName</key>
        <string>__MAUI_DEFAULT_SCENE_CONFIGURATION__</string>
        <key>UISceneDelegateClassName</key>
        <string>SceneDelegate</string>
      </dict>
    </array>
  </dict>
</dict>

重要说明

多窗口支持不适用于 iOS for iPhone。

调整窗口的位置和大小

可以通过设置 Window 对象的 XYWidthHeight 属性,以编程方式为 Windows 上的 .NET MAUI 应用定义窗口的位置和大小。

警告

Mac Catalyst 不支持通过设置 XYWidthHeight 属性以编程方式调整窗口的大小或位置。

例如,若要在启动时设置窗口位置和大小,应重写 App 类中的 CreateWindow 方法,并设置 Window 对象的 XYWidthHeight 属性:

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
    }

    protected override Window CreateWindow(IActivationState activationState) =>
        new Window(new AppShell())
        {
            Width = 700,
            Height = 500,
            X = 100,
            Y = 100
        };
}

或者,可以通过从任何页面、布局或视图访问 Window 属性来调整窗口的位置和大小。 例如,以下代码显示如何将窗口置于屏幕中心:

// Get display size
var displayInfo = DeviceDisplay.Current.MainDisplayInfo;

// Center the window
Window.X = (displayInfo.Width / displayInfo.Density - Window.Width) / 2;
Window.Y = (displayInfo.Height / displayInfo.Density - Window.Height) / 2;

有关获取设备屏幕指标的信息,请参阅设备显示信息

Mac Catalyst

Mac Catalyst 不支持以编程方式调整窗口的大小或位置。 但是,启用大小调整的解决方法是将 MinimumWidthMaximumWidth 属性设置为所需的窗口宽度,并将 MinimumHeightMaximumHeight 属性设置为所需的窗口高度。 这会触发重设大小,然后可以将属性还原,返回到其原始值:

Window.MinimumWidth = 700;
Window.MaximumWidth = 700;
Window.MinimumHeight = 500;
Window.MaximumHeight = 500;

// Give the Window time to resize
Dispatcher.Dispatch(() =>
{
    Window.MinimumWidth = 0;
    Window.MinimumHeight = 0;
    Window.MaximumWidth = double.PositiveInfinity;
    Window.MaximumHeight = double.PositiveInfinity;
});

从 App 类分离窗口管理

通过创建实现 IWindowCreator 接口的类并在 CreateWindow 方法中添加窗口管理代码,可以将窗口管理与 App 类分离:

public class WindowCreator : IWindowCreator
{
    public Window CreateWindow(Application app, IActivationState activationState)
    {
        var window = new Window(new ContentPage
        {
            Content = new Grid
            {
                new Label
                {
                    Text = "Hello from IWindowCreator",
                    HorizontalOptions = LayoutOptions.Center,
                    VerticalOptions = LayoutOptions.Center
                }
            }
        });

        return window;
    }
}

然后,在 MauiProgram 类中,应将窗口管理类型注册为应用服务容器中的依赖项:

builder.Services.AddSingleton<IWindowCreator, WindowCreator>();

重要说明

确保注册代码指定 IWindowCreator 接口及其具体类型。

然后,确保 App 类未设置 MainPage 属性:

public partial class App : Application
{
    public App()
    {
        InitializeComponent();
    }
}

如果 IWindowCreator 接口及其具体类型已注册到应用的服务容器中,并且未设置 Application 类的 MainPage 属性,则注册的类型将用于创建 Window