|
| 1 | +--- |
| 2 | +description: Use multiple windows to show your app content. |
| 3 | +title: Use the Window class to show secondary windows for an app |
| 4 | +ms.date: 06/27/2025 |
| 5 | +ms.topic: article |
| 6 | +ms.localizationpriority: medium |
| 7 | +no-loc: [Window, Page, AppWindow, Frame, Dictionary, WindowId] |
| 8 | +appliesto: |
| 9 | + - ✅ <a href="https://learn.microsoft.com/en-us/windows/apps/winui/winui3/" target="_blank">WinUI 3</a> |
| 10 | + - ✅ <a href="hhttps://learn.microsoft.com/en-us/windows/apps/windows-app-sdk/" target="_blank">Windows App SDK</a> |
| 11 | +--- |
| 12 | +# Show multiple windows for your app |
| 13 | + |
| 14 | +In your WinUI 3 app, you can show your app content in secondary windows while still working on the same UI thread across each window. |
| 15 | + |
| 16 | +> [!div class="checklist"] |
| 17 | +> |
| 18 | +> - **Important APIs**: [Microsoft.UI.Windowing namespace](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing), [Window class](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window), [AppWindow class](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindow) |
| 19 | +
|
| 20 | +> [!div class="nextstepaction"] |
| 21 | +> [Open the WinUI 3 Gallery app and see multiple windows in action](winui3gallery://item/CreateMultipleWindows) |
| 22 | +
|
| 23 | +[!INCLUDE [winui-3-gallery](../../../includes/winui-3-gallery.md)] |
| 24 | + |
| 25 | +> [!TIP] |
| 26 | +> A common reason to use multiple windows is to allow [TabView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.tabview) tabs to be torn out into a new window. For information and examples specific to this scenario, see [Tab tear-out](/windows/apps/design/controls/tab-view#tab-tear-out) in the [Tab view](../../design/controls/tab-view.md) article. |
| 27 | +
|
| 28 | +## API overview |
| 29 | + |
| 30 | +Here are some of the important APIs you use to show content in multiple windows. |
| 31 | + |
| 32 | +### XAML Window and AppWindow |
| 33 | + |
| 34 | +The [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window) and [AppWindow](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindow) classes can be used to display a portion of an app in a secondary window. An important feature of WinUI windows is that each instance shares the same UI processing thread (including the event dispatcher) from which they were created, which simplifies multi-window apps. |
| 35 | + |
| 36 | +See [Windowing overview for WinUI and Windows App SDK](windowing-overview.md) for a more detailed explanation of Window and AppWindow. |
| 37 | + |
| 38 | +### AppWindowPresenter |
| 39 | + |
| 40 | +The [AppWindowPresenter](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindowpresenter) API lets you easily switch windows into pre-defined configurations like `FullScreen` or `CompactOverlay`. For more info, see [Manage app windows](windowing-overview.md). |
| 41 | + |
| 42 | +### XamlRoot |
| 43 | + |
| 44 | +The [XamlRoot](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.xamlroot) class holds a XAML element tree, connects it to the window host object, and provides info such as size and visibility. You don't create a XamlRoot object directly. Instead, one is created when you attach a XAML element to a Window. You can then use the [UIElement.XamlRoot](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.uielement.xamlroot) property to retrieve the XamlRoot. |
| 45 | + |
| 46 | +### WindowId |
| 47 | + |
| 48 | +[WindowId](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowid) is a unique identifier for an app window. It's created automatically, and identifies both the [AppWindow](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowing.appwindow) and the top-level Win32 HWND it's associated with. |
| 49 | + |
| 50 | +From a visual element, you can access [UIElement.XamlRoot](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.uielement.xamlroot); then [XamlRoot.ContentIslandEnvironment](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.xamlroot.contentislandenvironment); then the [ContentIslandEnvironment.AppWindowId](/windows/windows-app-sdk/api/winrt/microsoft.ui.content.contentislandenvironment.appwindowid) property contains the ID of window that the UIElement is in. |
| 51 | + |
| 52 | +## Show a new window |
| 53 | + |
| 54 | +You can create a new Window in XAML or in code. If you create a Window in XAML, you're actually creating a sub-class of the Window class. For example, see `MainWindow.xaml` that's created by the Visual Studio app template. |
| 55 | + |
| 56 | +Let's take a look at the steps to show content in a new window. |
| 57 | + |
| 58 | +**To create a new window with XAML** |
| 59 | + |
| 60 | +1. In the **Solution Explorer** pane, right-click on the project name and select **Add > New Item...** |
| 61 | +1. In the **Add New Item** dialog, select **WinUI** in the template list on the left-side of the window. |
| 62 | +1. Select the **Blank Window** template. |
| 63 | +1. Name the file. |
| 64 | +1. Press **Add**. |
| 65 | + |
| 66 | +**To show a new window** |
| 67 | + |
| 68 | +1. Instantiate a new instance of [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window), or a Window subclass if you created a Window subclass with a `.xaml` file. |
| 69 | + |
| 70 | + ```csharp |
| 71 | + Window newWindow = new Window(); |
| 72 | + ``` |
| 73 | + |
| 74 | +1. Create the window content. |
| 75 | + |
| 76 | + If you created a [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window) subclass with a `.xaml` file, you can add the window content directly in XAML. Otherwise, you add the content in code as shown here. |
| 77 | + |
| 78 | + It's common to create a XAML [Frame](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.frame), then navigate the Frame to a XAML [Page](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.page where you've defined your app content. For more info about frames and pages, see [Peer-to-peer navigation between two pages](/windows/apps/design/basics/navigate-between-two-pages). |
| 79 | + |
| 80 | + ```csharp |
| 81 | + Frame contentFrame = new Frame(); |
| 82 | + contentFrame.Navigate(typeof(SecondaryPage)); |
| 83 | + ``` |
| 84 | + |
| 85 | + However, you can show any XAML content in the AppWindow, not just a Frame and Page. For example, you can show just a single control, like [ColorPicker](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.colorpicker), as shown later. |
| 86 | + |
| 87 | +1. Set your XAML content to the [Content](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.content) property of the [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window). |
| 88 | + |
| 89 | + ```csharp |
| 90 | + newWindow.Content = contentFrame; |
| 91 | + ``` |
| 92 | + |
| 93 | +1. Call the [Window.Activate](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.activate) method to show the new window. |
| 94 | + |
| 95 | + ```csharp |
| 96 | + newWindow.Activate(); |
| 97 | + ``` |
| 98 | + |
| 99 | +## Track instances of Window |
| 100 | + |
| 101 | +You might want to have access to the [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window) instances from other parts of your app, but after you create an instance of a Window, there's no way to access it from other code unless you keep a reference to it. For example, you might want to handle the [Window.SizeChanged](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.sizechanged) event in `MainPage` to rearrange UI elements when the window is resized, or you could have a 'close all' button that closes all the tracked instances of Window. |
| 102 | + |
| 103 | +In this case, you should use the [WindowId](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowid) unique identifier to track the window instances in a [Dictionary](/dotnet/api/system.collections.generic.dictionary-2?view=dotnet-uwp-10.0&preserve-view=true), with the WindowId as the `Key` and the Window instance as the `Value`. ([TabView](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.tabview) tab tear-out APIs also use WindowId to track Windows.) |
| 104 | + |
| 105 | +In your `App` class, create the [Dictionary](/dotnet/api/system.collections.generic.dictionary-2?view=dotnet-uwp-10.0&preserve-view=true) as a static property. Then, add each page to the Dictionary when you create it, and remove it when the page is closed. |
| 106 | + |
| 107 | +```csharp |
| 108 | +// App.xaml.cs |
| 109 | +public partial class App : Application |
| 110 | +{ |
| 111 | + private Window? _window; |
| 112 | + public static Dictionary<WindowId, Window> ActiveWindows { get; set; } = new Dictionary<WindowId, Window>(); |
| 113 | + |
| 114 | + // ... |
| 115 | +
|
| 116 | + protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) |
| 117 | + { |
| 118 | + _window = new MainWindow(); |
| 119 | + _window.Activate(); |
| 120 | + // Track the new window in the dictionary. |
| 121 | + ActiveWindows.Add(_window.AppWindow.Id, _window); |
| 122 | + } |
| 123 | +} |
| 124 | +``` |
| 125 | + |
| 126 | +The following code creates a new window when a button is clicked in `MainPage`. The `TrackWindow` method adds the new window to the `ActiveWindows` [Dictionary](/dotnet/api/system.collections.generic.dictionary-2?view=dotnet-uwp-10.0&preserve-view=true), and handles the [Window.Closed](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window.closed) event to remove it from `ActiveWindows` when the window is closed. |
| 127 | + |
| 128 | +```csharp |
| 129 | +// MainPage.xaml.cs |
| 130 | +private Window CreateWindow() |
| 131 | +{ |
| 132 | + Window newWindow = new Window(); |
| 133 | + |
| 134 | + // Configure the window. |
| 135 | + newWindow.AppWindow.Resize(new SizeInt32(1200, 800)); |
| 136 | + newWindow.Title = "Window " + newWindow.AppWindow.Id.Value.ToString(); |
| 137 | + newWindow.SystemBackdrop = new MicaBackdrop(); |
| 138 | + |
| 139 | + TrackWindow(newWindow); |
| 140 | + return newWindow; |
| 141 | +} |
| 142 | + |
| 143 | +private void TrackWindow(Window window) |
| 144 | +{ |
| 145 | + window.Closed += (sender, args) => { |
| 146 | + App.ActiveWindows.Remove(window.AppWindow.Id, out window); |
| 147 | + }; |
| 148 | + App.ActiveWindows.Add(window.AppWindow.Id, window); |
| 149 | +} |
| 150 | + |
| 151 | +``` |
| 152 | + |
| 153 | +### Get a tracked window from your app code |
| 154 | + |
| 155 | +To access a [Window](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.window) instance from your app code, you need to get the [WindowId](/windows/windows-app-sdk/api/winrt/microsoft.ui.windowid) for the current window to retrieve it from the static [Dictionary](/dotnet/api/system.collections.generic.dictionary-2?view=dotnet-uwp-10.0&preserve-view=true) in your `App` class. You should do this in the page's [Loaded](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.frameworkelement.loaded) event handler rather than in the constructor so that [XamlRoot](/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.uielement.xamlroot) is not `null`. |
| 156 | + |
| 157 | +```csharp |
| 158 | +public sealed partial class SecondaryPage : Page |
| 159 | +{ |
| 160 | + Window window; |
| 161 | + |
| 162 | + public SecondaryPage() |
| 163 | + { |
| 164 | + InitializeComponent(); |
| 165 | + Loaded += AppWindowPage_Loaded; |
| 166 | + } |
| 167 | + |
| 168 | + private void AppWindowPage_Loaded(object sender, RoutedEventArgs e) |
| 169 | + { |
| 170 | + // Get the reference to this Window that was stored when it was created. |
| 171 | + // Do this in the Page Loaded handler rather than the constructor to |
| 172 | + // ensure that the XamlRoot is created and attached to the Window. |
| 173 | + WindowId windowId = this.XamlRoot.ContentIslandEnvironment.AppWindowId; |
| 174 | + |
| 175 | + if (App.ActiveWindows.ContainsKey(windowId)) |
| 176 | + { |
| 177 | + window = App.ActiveWindows[windowId]; |
| 178 | + } |
| 179 | + } |
| 180 | +} |
| 181 | +``` |
| 182 | + |
| 183 | +## Related topics |
| 184 | + |
| 185 | +- [Windowing overview](windowing-overview.md) |
| 186 | +- [Manage app windows](manage-app-windows.md) |
| 187 | +- [Tab view](../../design/controls/tab-view.md) |
| 188 | +- [Show multiple views (UWP)](/windows/uwp/ui-input/show-multiple-views) |
0 commit comments