.NET MAUI windows

The .NET Multi-platform App UI (.NET MAUI) Window class provides the ability to create, configure, show, and manage multiple windows.

Window defines the following properties:

  • FlowDirection, of type FlowDirection, defines the direction in which the UI element of the window are laid out.
  • Height, of type double, specifies the height of the window on Windows.
  • MaximumHeight, of type double, represents the maximum height of the window on desktop platforms. Valid values are between 0 and double.PositiveInfinity.
  • MaximumWidth, of type double, represents the maximum width of the window on desktop platforms. Valid values are between 0 and double.PositiveInfinity.
  • MinimumHeight, of type double, represents the minimum height of the window on desktop platforms. Valid values are between 0 and double.PositiveInfinity.
  • MinimumWidth, of type double, represents the minimum width of the window on desktop platforms. Valid values are between 0 and double.PositiveInfinity.
  • Overlays, of type IReadOnlyCollection<IWindowOverlay>, represents the collection of window overlays.
  • Page, of type Page, indicates the page being displayed by the window. This property is the content property of the Window class, and therefore does not need to be explicitly set.
  • Title, of type string, represents the title of the window.
  • Width, of type double, specifies the width of the window on Windows.
  • X, of type double, specifies the X coordinate of the window on Windows.
  • Y, of type double, specifies the Y coordinate of the window on Windows.

These properties, with the exception of the Overlays property, are backed by BindableProperty objects, which means that they can be targets of data bindings, and styled.

The Window class defines the following events:

  • Created, which is raised when the window is created.
  • Resumed, which is raised when the window is resumed from a sleeping state.
  • Activated, which is raised when the window is activated.
  • Deactivated, which is raised when the window is deactivated.
  • Stopped, which is raised when the window is stopped.
  • Destroying, which is raised when the window is destroyed.
  • SizeChanged, which is raised on desktop platforms when the window changes size.
  • Backgrounding, with an accompanying BackgroundingEventArgs object, which is raised on iOS and Mac Catalyst when the window is closed or enters a background state. This event can be used to persist any string state to the State property of the BackgroundingEventArgs object, which the OS will preserve until it's time to resume the window. When the window is resumed the state is provided via the IActivationState argument to the CreateWindow method.
  • <xref:Microsoft.Maui.Controls.WindowDisplayDensityChanged, with an accompanying DisplayDensityChangedEventArgs object, which is raised on Android and Windows when the effective dots per inch (DPI) for the window has changed.

For more information about the lifecycle events, and their associated overrides, see App lifecycle.

The Window class also defines the following modal navigation events:

  • ModalPopped, with ModalPoppedEventArgs, which is raised when a view has been popped modally.
  • ModalPopping, with ModalPoppingEventArgs, which is raised when a view is modally popped.
  • ModalPushed, with ModalPushedEventArgs, which is raised after a view has been pushed modally.
  • ModalPushing, with ModalPushingEventArgs, which is raised when a view is modally pushed.
  • PopCanceled, which is raised when a modal pop is cancelled.

The VisualElement class has a Window property that exposes the parent Window object. This property can be accessed from any page, layout, or view, to manipulate Window objects.

Create a Window

By default, .NET MAUI creates a Window object when you set the MainPage property to a Page object in your App class. However, you can also override the CreateWindow method in your App class to create a Window object:

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

While the Window class has a default constructor and a constructor that accepts a Page argument, which represents the root page of the app, you can also call the base CreateWindow method to return the .NET MAUI created Window object.

In addition, you can also create your own Window-derived object:

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

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

        // Override Window methods
    }
}

The Window-derived class can then be consumed by creating a MyWindow object in the CreateWindow override in your App class.

Regardless of how your Window object is created, it will be the parent of the root page in your app.

Multi-window support

Multiple windows can be simultaneously opened on Android, iOS on iPad (iPadOS), Mac Catalyst, and Windows. This can be achieved by creating a Window object and opening it using the OpenWindow method on the Application object:

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

The Application.Current.Windows collection, of type IReadOnlyList<Window> maintains references to all Window objects that are registered with the Application object.

Windows can be closed with the Application.Current.CloseWindow method:

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

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

Important

Multi-window support works on Android and Windows without additional configuration. However, additional configuration is required on iPadOS and Mac Catalyst.

iPadOS and macOS configuration

To use multi-window support on iPadOS and Mac Catalyst, add a class named SceneDelegate to the Platforms > iOS and Platforms > MacCatalyst folders:

using Foundation;
using Microsoft.Maui;
using UIKit;

namespace MyMauiApp;

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

Then, in the XML editor, open the Platforms > iOS > Info.plist file and the Platforms > MacCatalyst > Info.plist file and add the following XML to the end of each file:

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

Important

Multi-window support doesn't work on iOS for iPhone.

Position and size a Window

The position and size of a window can be programmatically defined for a .NET MAUI app on Windows by setting the X, Y, Width, and Height properties on a Window object.

Warning

Mac Catalyst doesn't support resizing or repositioning windows programmatically by setting the X, Y, Width, and Height properties.

For example, to set the window position and size on launch you should override the CreateWindow method in your App class and set the X, Y, Width, and Height properties on a Window object:

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

Alternatively, a window can be positioned and sized by accessing the Window property from any page, layout, or view. For example, the following code shows how to position a window in the center of the screen:

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

For information about obtaining the device's screen metrics, see Device display information.

Mac Catalyst

Mac Catalyst doesn't support resizing or repositioning windows programmatically. However, a workaround to enable resizing is to set the MinimumWidth and MaximumWidth properties to the desired width of the window, and the MinimumHeight and MaximumHeight properties to the desired height of the window. This will trigger a resize, and you can then revert the properties back to their original values:

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;
});

Decouple window management from the App class

Window management can be decoupled from the App class by creating a class that implements the IWindowCreator interface, and adding your window management code in the CreateWindow method:

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

Then, in the MauiProgram class you should register your window management type as a dependency in the app's service container:

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

Important

Ensure that your registration code specifies the IWindowCreator interface as well as its concrete type.

Then, ensure that your App class doesn't set the MainPage property:

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

Provided that the IWindowCreator interface and its concrete type have been registered with the app's service container, and that the MainPage property of the Application class isn't set, your registered type will be used to create the Window.