Dela via


Visa flera vyer med AppWindow

AppWindow och dess relaterade API:er förenklar skapandet av appar med flera fönster genom att du kan visa appinnehållet i sekundära fönster medan du fortfarande arbetar med samma gränssnittstråd i varje fönster.

Anmärkning

AppWindow är för närvarande i förhandsversion. Det innebär att du kan skicka appar som använder AppWindow till Store, men vissa plattforms- och ramverkskomponenter är kända för att inte fungera med AppWindow (se Begränsningar).

Här visar vi några scenarier för flera fönster med en exempelapp med namnet HelloAppWindow. Exempelappen visar följande funktioner:

  • Ta bort dockningen av en kontroll från huvudsidan och öppna den i ett nytt fönster.
  • Öppna nya instanser av en sida i nya fönster.
  • Ändra storlek på och placera nya fönster i appen programmatiskt.
  • Associera en ContentDialog med lämpligt fönster i appen.

Exempelapp med ett enda fönster

Exempelapp med ett enda fönster

Exempelapp med odockad färgväljare och sekundärt fönster

Exempelapp med odockad färgväljare och sekundärt fönster

Viktiga API:er: Windows.UI.WindowManagement-namnrymd, AppWindow-klass

API-översikt

Klassen AppWindow och andra API:er i WindowManagement-namnområdet är tillgängliga från och med Windows 10 version 1903 (SDK 18362). Om din app riktar in sig på tidigare versioner av Windows 10 måste du använda ApplicationView för att skapa sekundära fönster. WindowManagement-API:er är fortfarande under utveckling och har begränsningar enligt beskrivningen i API-referensdokumenten.

Här är några av de viktiga API:er som du använder för att visa innehåll i en AppWindow.

Appfönster

Klassen AppWindow kan användas för att visa en del av en UWP-app i ett sekundärt fönster. Det är liknande i konceptet som en ApplicationView-, men är inte detsamma i beteende och livslängd. En viktig funktion i AppWindow är att varje instans delar samma användargränssnittsbearbetningstråd (inklusive händelseutskickaren) som de skapades från, vilket förenklar appar med flera fönster.

Du kan bara ansluta XAML-innehåll till din AppWindow, det finns inget stöd för inbyggt DirectX- eller Holographic-innehåll. Du kan dock visa en XAML SwapChainPanel som är värd för DirectX-innehåll.

Fönstermiljö

Med WindowingEnvironment-API :et får du veta mer om miljön där appen presenteras så att du kan anpassa din app efter behov. Den beskriver vilken typ av fönster miljön stöder. till exempel Overlapped om appen körs på en dator eller Tiled om appen körs på en Xbox. Den innehåller också en uppsättning DisplayRegion-objekt som beskriver de områden där en app kan visas på en logisk skärm.

Visningsregion

Api:et DisplayRegion beskriver den region där en vy kan visas för en användare på en logisk skärm. På en stationär dator är det till exempel den fullständiga skärmen minus området i aktivitetsfältet. Det är inte nödvändigtvis en 1:1-mappning med det fysiska visningsområdet för bakgrundsövervakaren. Det kan finnas flera visningsområden inom samma bildskärm, eller så kan en DisplayRegion konfigureras för att sträcka sig över flera bildskärmar om dessa bildskärmar är homogena i alla avseenden.

AppWindowPresenter

Med Api:et AppWindowPresenter kan du enkelt växla windows till fördefinierade konfigurationer som FullScreen eller CompactOverlay. Dessa konfigurationer ger användaren en konsekvent upplevelse på alla enheter som stöder konfigurationen.

Usergränssnittskontext

UIContext är en unik identifierare för ett appfönster eller en vy. Den skapas automatiskt och du kan använda egenskapen UIElement.UIContext för att hämta UIContext. Varje UIElement i XAML-trädet har samma UIContext.

UIContext är viktigt eftersom API:er som Window.Current och GetForCurrentView mönstret förlitar sig på att ha en enda ApplicationView/CoreWindow med ett enda XAML-träd per tråd att arbeta med. Detta är inte fallet när du använder en AppWindow, så du använder UIContext för att identifiera ett visst fönster i stället.

XamlRoot

Klassen XamlRoot innehåller ett XAML-elementträd, ansluter det till fönstrets värdobjekt (till exempel AppWindow eller ApplicationView) och innehåller information som storlek och synlighet. Du skapar inte ett XamlRoot-objekt direkt. I stället skapas ett när du kopplar ett XAML-element till en AppWindow. Du kan sedan använda egenskapen UIElement.XamlRoot för att hämta XamlRoot.

Mer information om UIContext och XamlRoot finns i Göra koden portabel över fönstervärdar.

Visa ett nytt fönster

Nu ska vi ta en titt på stegen för att visa innehåll i en ny AppWindow.

Så här visar du ett nytt fönster

  1. Anropa den statiska metoden AppWindow.TryCreateAsync för att skapa en ny AppWindow.

    AppWindow appWindow = await AppWindow.TryCreateAsync();
    
  2. Skapa fönstrets innehåll.

    Vanligtvis skapar du en XAML-ram och navigerar sedan till en XAML-sida där du har definierat ditt appinnehåll. Mer information om ramar och sidor finns i Peer-to-peer-navigering mellan två sidor.

    Frame appWindowContentFrame = new Frame();
    appWindowContentFrame.Navigate(typeof(AppWindowMainPage));
    

    Du kan dock visa valfritt XAML-innehåll i AppWindow, inte bara en ram och sida. Du kan till exempel bara visa en enda kontroll, till exempel ColorPicker, eller så kan du visa en SwapChainPanel som är värd för DirectX-innehåll.

  3. Anropa metoden ElementCompositionPreview.SetAppWindowContent för att koppla XAML-innehållet till AppWindow.

    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
    

    Anropet till den här metoden skapar ett XamlRoot-objekt och anger det som XamlRoot-egenskapen för det angivna UIElement.

    Du kan bara anropa den här metoden en gång per AppWindow-instans. När innehållet har angetts misslyckas ytterligare anrop till SetAppWindowContent för den här AppWindow-instansen. Om du försöker koppla från AppWindow-innehållet genom att skicka in ett null UIElement-objekt misslyckas anropet.

  4. Anropa metoden AppWindow.TryShowAsync för att visa det nya fönstret.

    await appWindow.TryShowAsync();
    

Frigöra resurser när ett fönster stängs

Du bör alltid hantera händelsen AppWindow.Closed för att släppa XAML-resurser (AppWindow-innehållet) och referenser till AppWindow.

appWindow.Closed += delegate
{
    appWindowContentFrame.Content = null;
    appWindow = null;
};

Tips/Råd

Du bör hålla mängden kod i din Closed-händelsehanterare så låg som möjligt för att undvika oväntade problem.

Spåra instanser av AppWindow

Beroende på hur du använder flera fönster i din app kanske du inte behöver hålla reda på de instanser av AppWindow som du skapar. I exemplet HelloAppWindow visas några olika sätt du vanligtvis kan använda en AppWindow-. Här ska vi titta på varför dessa fönster ska spåras och hur du gör det.

Enkel spårning

Färgväljarens fönster är värd för en enda XAML-kontroll, och koden för att interagera med färgväljaren finns i MainPage.xaml.cs filen. Fönstret för färgväljaren tillåter endast en enskild instans och är i princip ett tillägg av MainWindow. För att säkerställa att endast en instans skapas spåras färgväljarens fönster med en sidnivåvariabel. Innan du skapar ett nytt färgväljarefönster kontrollerar du om det finns en instans, och om den gör det hoppar du över stegen för att skapa ett nytt fönster och anropar bara TryShowAsync i det befintliga fönstret.

AppWindow colorPickerAppWindow;

// ...

private async void DetachColorPickerButton_Click(object sender, RoutedEventArgs e)
{
    // Create the color picker window.
    if (colorPickerAppWindow == null)
    {
        // ...
        // Create a new window
        colorPickerAppWindow = await AppWindow.TryCreateAsync();
        // ...
    }
    // Show the window.
    await colorPickerAppWindow.TryShowAsync();
}

Spåra en AppWindow-instans i dess värdbaserade innehåll

Fönstret AppWindowPage är värd för en fullständig XAML-sida och koden för att interagera med sidan finns i AppWindowPage.xaml.cs. Det tillåter flera instanser, som var och en fungerar oberoende av varandra.

Med funktionen på sidan kan du ändra fönstret, ställa in det på FullScreen eller CompactOverlayoch även lyssna efter AppWindow.Changed händelser för att visa information om fönstret. För att kunna anropa dessa API:er AppWindowPage behöver du en referens till den AppWindow-instans som är värd för den.

Om det är allt du behöver kan du skapa en egenskap i AppWindowPage och tilldela AppWindow-instansen till den när du skapar den.

AppWindowPage.xaml.cs

I AppWindowPageskapar du en egenskap som innehåller AppWindow-referensen.

public sealed partial class AppWindowPage : Page
{
    public AppWindow MyAppWindow { get; set; }

    // ...
}

MainPage.xaml.cs

I MainPagehämtar du en referens till sidinstansen och tilldelar den nyligen skapade AppWindow till egenskapen i AppWindowPage.

private async void ShowNewWindowButton_Click(object sender, RoutedEventArgs e)
{
    // Create a new window.
    AppWindow appWindow = await AppWindow.TryCreateAsync();

    // Create a Frame and navigate to the Page you want to show in the new window.
    Frame appWindowContentFrame = new Frame();
    appWindowContentFrame.Navigate(typeof(AppWindowPage));

    // Get a reference to the page instance and assign the
    // newly created AppWindow to the MyAppWindow property.
    AppWindowPage page = (AppWindowPage)appWindowContentFrame.Content;
    page.MyAppWindow = appWindow;

    // ...
}

Spårning av appfönster med UIContext

Du kanske också vill ha åtkomst till AppWindow-instanserna från andra delar av appen. Du kan till exempel MainPage ha en "stäng alla"-knapp som stänger alla spårade instanser av AppWindow.

I det här fallet bör du använda den UIContext unika identifieraren för att spåra fönsterinstanserna i en Dictionary.

MainPage.xaml.cs

I MainPageskapar du ordlistan som en statisk egenskap. Lägg sedan till sidan i ordlistan när du skapar den och ta bort den när sidan stängs. Du kan hämta UIContext från innehållsramen (appWindowContentFrame.UIContext) när du anropar ElementCompositionPreview.SetAppWindowContent.

public sealed partial class MainPage : Page
{
    // Track open app windows in a Dictionary.
    public static Dictionary<UIContext, AppWindow> AppWindows { get; set; }
        = new Dictionary<UIContext, AppWindow>();

    // ...

    private async void ShowNewWindowButton_Click(object sender, RoutedEventArgs e)
    {
        // Create a new window.
        AppWindow appWindow = await AppWindow.TryCreateAsync();

        // Create a Frame and navigate to the Page you want to show in the new window.
        Frame appWindowContentFrame = new Frame();
        appWindowContentFrame.Navigate(typeof(AppWindowPage));

        // Attach the XAML content to the window.
        ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);

        // Add the new page to the Dictionary using the UIContext as the Key.
        AppWindows.Add(appWindowContentFrame.UIContext, appWindow);
        appWindow.Title = "App Window " + AppWindows.Count.ToString();

        // When the window is closed, be sure to release
        // XAML resources and the reference to the window.
        appWindow.Closed += delegate
        {
            MainPage.AppWindows.Remove(appWindowContentFrame.UIContext);
            appWindowContentFrame.Content = null;
            appWindow = null;
        };

        // Show the window.
        await appWindow.TryShowAsync();
    }

    private async void CloseAllButton_Click(object sender, RoutedEventArgs e)
    {
        while (AppWindows.Count > 0)
        {
            await AppWindows.Values.First().CloseAsync();
        }
    }
    // ...
}

AppWindowPage.xaml.cs

Om du vill använda AppWindow-instansen i koden AppWindowPage använder du sidans UIContext för att hämta den från den statiska ordlistan i MainPage. Du bör göra detta i sidans Läs in händelsehanterare, istället för i konstruktorn, så att UIContext inte blir null. Du kan hämta UIContext från sidan: this.UIContext.

public sealed partial class AppWindowPage : Page
{
    AppWindow window;

    // ...
    public AppWindowPage()
    {
        this.InitializeComponent();

        Loaded += AppWindowPage_Loaded;
    }

    private void AppWindowPage_Loaded(object sender, RoutedEventArgs e)
    {
        // Get the reference to this AppWindow that was stored when it was created.
        window = MainPage.AppWindows[this.UIContext];

        // Set up event handlers for the window.
        window.Changed += Window_Changed;
    }
    // ...
}

Anmärkning

Exemplet HelloAppWindow visar båda sätten att spåra fönstret i AppWindowPage, men du använder vanligtvis det ena eller det andra, inte båda.

Storlek och placering av begärandefönster

Klassen AppWindow har flera metoder som du kan använda för att styra fönstrets storlek och placering. Som antyds av metodnamnen kan eller kan inte systemet uppfylla de begärda ändringarna beroende på miljöfaktorer.

Anropa RequestSize för att ange en önskad fönsterstorlek, så här.

colorPickerAppWindow.RequestSize(new Size(300, 428));

Metoderna för att hantera fönsterplacering heter RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.

I det här exemplet flyttar den här koden fönstret till den huvudvy som fönstret skapas från.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

Om du vill få information om fönstrets aktuella storlek och placering anropar du GetPlacement. Detta returnerar ett AppWindowPlacement-objekt som innehåller fönstrets aktuella DisplayRegion, Offset och Size .

Du kan till exempel anropa den här koden för att flytta fönstret till det övre högra hörnet av skärmen. Den här koden måste anropas när fönstret har visats. Annars blir fönsterstorleken som returneras av anropet till GetPlacement 0,0 och förskjutningen blir felaktig.

DisplayRegion displayRegion = window.GetPlacement().DisplayRegion;
double displayRegionWidth = displayRegion.WorkAreaSize.Width;
double windowWidth = window.GetPlacement().Size.Width;
int horizontalOffset = (int)(displayRegionWidth - windowWidth);
window.RequestMoveRelativeToDisplayRegion(displayRegion, new Point(horizontalOffset, 0));

Begära en presentationskonfiguration

Med klassen AppWindowPresenter kan du visa en AppWindow med en fördefinierad konfiguration som är lämplig för den enhet som den visas på. Du kan använda ett AppWindowPresentationConfiguration-värde för att placera fönstret i FullScreen eller CompactOverlay läge.

Det här exemplet visar hur du gör följande:

private void Window_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
    if (args.DidAvailableWindowPresentationsChange)
    {
        EnablePresentationButtons(sender);
    }

    if (args.DidWindowPresentationChange)
    {
        ConfigText.Text = window.Presenter.GetConfiguration().Kind.ToString();
    }

    if (args.DidSizeChange)
    {
        SizeText.Text = window.GetPlacement().Size.ToString();
    }
}

private void EnablePresentationButtons(AppWindow window)
{
    // Check whether the current AppWindowPresenter supports CompactOverlay.
    if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.CompactOverlay))
    {
        // Show the CompactOverlay button...
        compactOverlayButton.Visibility = Visibility.Visible;
    }
    else
    {
        // Hide the CompactOverlay button...
        compactOverlayButton.Visibility = Visibility.Collapsed;
    }

    // Check whether the current AppWindowPresenter supports FullScreen?
    if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.FullScreen))
    {
        // Show the FullScreen button...
        fullScreenButton.Visibility = Visibility.Visible;
    }
    else
    {
        // Hide the FullScreen button...
        fullScreenButton.Visibility = Visibility.Collapsed;
    }
}

private void CompactOverlayButton_Click(object sender, RoutedEventArgs e)
{
    if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.CompactOverlay)
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.CompactOverlay);
        fullScreenButton.IsChecked = false;
    }
    else
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
    }
}

private void FullScreenButton_Click(object sender, RoutedEventArgs e)
{
    if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.FullScreen)
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.FullScreen);
        compactOverlayButton.IsChecked = false;
    }
    else
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
    }
}

Återanvända XAML-element

Med En AppWindow kan du ha flera XAML-träd med samma användargränssnittstråd. Ett XAML-element kan dock bara läggas till i ett XAML-träd en gång. Om du vill flytta en del av användargränssnittet från ett fönster till ett annat måste du hantera placeringen i XAML-trädet.

Det här exemplet visar hur du återanvänder en ColorPicker-kontroll när du flyttar den mellan huvudfönstret och ett sekundärt fönster.

Färgväljaren deklareras i XAML för MainPage, vilket placerar den i MainPage XAML-trädet.

<StackPanel x:Name="colorPickerContainer" Grid.Column="1" Background="WhiteSmoke">
    <Button Click="DetachColorPickerButton_Click" HorizontalAlignment="Right">
        <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE2B4;" />
    </Button>
    <ColorPicker x:Name="colorPicker" Margin="12" Width="288"
                 IsColorChannelTextInputVisible="False"
                 ColorChanged="ColorPicker_ColorChanged"/>
</StackPanel>

När färgväljaren kopplas från för att placeras i en ny AppWindow måste du först ta bort den från MainPage XAML-trädet genom att ta bort den från sin överordnade behållare. Även om det inte krävs döljer det här exemplet även den överordnade containern.

colorPickerContainer.Children.Remove(colorPicker);
colorPickerContainer.Visibility = Visibility.Collapsed;

Sedan kan du lägga till den i det nya XAML-trädet. Här skapar du först en Grid- som blir den överordnade containern för ColorPicker och lägger till ColorPicker som underordnad i rutnätet. (På så sätt kan du enkelt ta bort ColorPicker från det här XAML-trädet senare.) Sedan anger du rutnätet som roten för XAML-trädet i det nya fönstret.

Grid appWindowRootGrid = new Grid();
appWindowRootGrid.Children.Add(colorPicker);

// Create a new window
colorPickerAppWindow = await AppWindow.TryCreateAsync();

// Attach the XAML content to our window
ElementCompositionPreview.SetAppWindowContent(colorPickerAppWindow, appWindowRootGrid);

När AppWindow stängs återställer du processen. Ta först bort ColorPicker- från Grid-och lägg sedan till den som ett underordnat objekt till StackPanel- i MainPage.

// When the window is closed, be sure to release XAML resources
// and the reference to the window.
colorPickerAppWindow.Closed += delegate
{
    appWindowRootGrid.Children.Remove(colorPicker);
    appWindowRootGrid = null;
    colorPickerAppWindow = null;

    colorPickerContainer.Children.Add(colorPicker);
    colorPickerContainer.Visibility = Visibility.Visible;
};
private async void DetachColorPickerButton_Click(object sender, RoutedEventArgs e)
{
    ColorPickerContainer.Visibility = Visibility.Collapsed;

    // Create the color picker window.
    if (colorPickerAppWindow == null)
    {
        ColorPickerContainer.Children.Remove(colorPicker);

        Grid appWindowRootGrid = new Grid();
        appWindowRootGrid.Children.Add(colorPicker);

        // Create a new window
        colorPickerAppWindow = await AppWindow.TryCreateAsync();
        colorPickerAppWindow.RequestMoveAdjacentToCurrentView();
        colorPickerAppWindow.RequestSize(new Size(300, 428));
        colorPickerAppWindow.Title = "Color picker";

        // Attach the XAML content to our window
        ElementCompositionPreview.SetAppWindowContent(colorPickerAppWindow, appWindowRootGrid);

        // When the window is closed, be sure to release XAML resources
        // and the reference to the window.
        colorPickerAppWindow.Closed += delegate
        {
            appWindowRootGrid.Children.Remove(colorPicker);
            appWindowRootGrid = null;
            colorPickerAppWindow = null;

            ColorPickerContainer.Children.Add(colorPicker);
            ColorPickerContainer.Visibility = Visibility.Visible;
        };
    }
    // Show the window.
    await colorPickerAppWindow.TryShowAsync();
}

Visa en dialogruta

Som standard visas innehållsdialogrutorna modalt i förhållande till roten ApplicationView. När du använder en ContentDialog- i en AppWindow-måste du manuellt ange XamlRoot i dialogrutan till XAML-värdens rot.

Det gör du genom att ange egenskapen XamlRoot för ContentDialog till samma XamlRoot som ett element som redan finns i AppWindow. Här finns den här koden i en knapps Klick händelsehanterare, så du kan använda sender (den klickade knappen) för att hämta XamlRoot.

if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
    simpleDialog.XamlRoot = ((Button)sender).XamlRoot;
}

Om du har en eller flera AppWindows öppna utöver huvudfönstret (ApplicationView) kan varje fönster försöka öppna en dialogruta, eftersom den modala dialogrutan endast blockerar det fönster som den är rotad i. Det kan dock bara finnas en ContentDialog öppen per tråd i taget. Att försöka öppna två innehållsdialoger utlöser ett undantag, även om de försöker öppna i separata appfönster.

Om du vill hantera detta bör du åtminstone öppna dialogrutan i ett try/catch block för att fånga undantaget om en annan dialogruta redan är öppen.

try
{
    ContentDialogResult result = await simpleDialog.ShowAsync();
}
catch (Exception)
{
    // The dialog didn't open, probably because another dialog is already open.
}

Ett annat sätt att hantera dialogrutor är att spåra den öppna dialogrutan och stänga den innan du försöker öppna en ny dialogruta. Här skapar du en statisk egenskap i MainPage anropad CurrentDialog för det här ändamålet.

public sealed partial class MainPage : Page
{
    // Track the last opened dialog so you can close it if another dialog tries to open.
    public static ContentDialog CurrentDialog { get; set; } = null;

   // ...
}

Sedan kontrollerar du om det finns en dialogruta som är öppen för tillfället, och om det finns det anropar du metoden Dölj för att stänga den. Slutligen tilldelar du den nya dialogrutan till CurrentDialogoch försöker visa den.

private async void DialogButton_Click(object sender, RoutedEventArgs e)
{
    ContentDialog simpleDialog = new ContentDialog
    {
        Title = "Content dialog",
        Content = "Dialog box for " + window.Title,
        CloseButtonText = "Ok"
    };

    if (MainPage.CurrentDialog != null)
    {
        MainPage.CurrentDialog.Hide();
    }
    MainPage.CurrentDialog = simpleDialog;

    // Use this code to associate the dialog to the appropriate AppWindow by setting
    // the dialog's XamlRoot to the same XamlRoot as an element that is already
    // present in the AppWindow.
    if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
    {
        simpleDialog.XamlRoot = ((Button)sender).XamlRoot;
    }

    try
    {
        ContentDialogResult result = await simpleDialog.ShowAsync();
    }
    catch (Exception)
    {
        // The dialog didn't open, probably because another dialog is already open.
    }
}

Om det inte är önskvärt att ha en dialogruta stängd programmatiskt ska du inte tilldela den som CurrentDialog. Här visar MainPage en viktig dialogruta som bara ska stängas när användaren klickar på Ok. Eftersom den inte har tilldelats som CurrentDialoggörs inget försök att stänga den programmatiskt.

public sealed partial class MainPage : Page
{
    // Track the last opened dialog so you can close it if another dialog tries to open.
    public static ContentDialog CurrentDialog { get; set; } = null;

    // ...
    private async void DialogButton_Click(object sender, RoutedEventArgs e)
    {
        ContentDialog importantDialog = new ContentDialog
        {
            Title = "Important dialog",
            Content = "This dialog can only be dismissed by clicking Ok.",
            CloseButtonText = "Ok"
        };

        if (MainPage.CurrentDialog != null)
        {
            MainPage.CurrentDialog.Hide();
        }
        // Do not track this dialog as the MainPage.CurrentDialog.
        // It should only be closed by clicking the Ok button.
        MainPage.CurrentDialog = null;

        try
        {
            ContentDialogResult result = await importantDialog.ShowAsync();
        }
        catch (Exception)
        {
            // The dialog didn't open, probably because another dialog is already open.
        }
    }
    // ...
}

Fullständig kod

MainPage.xaml

<Page
    x:Class="HelloAppWindow.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloAppWindow"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Button x:Name="NewWindowButton" Content="Open new window" 
                    Click="ShowNewWindowButton_Click" Margin="0,12"/>
            <Button Content="Open dialog" Click="DialogButton_Click" 
                    HorizontalAlignment="Stretch"/>
            <Button Content="Close all" Click="CloseAllButton_Click" 
                    Margin="0,12" HorizontalAlignment="Stretch"/>
        </StackPanel>

<StackPanel x:Name="colorPickerContainer" Grid.Column="1" Background="WhiteSmoke">
    <Button Click="DetachColorPickerButton_Click" HorizontalAlignment="Right">
        <FontIcon FontFamily="Segoe MDL2 Assets" Glyph="&#xE2B4;" />
    </Button>
            <ColorPicker x:Name="colorPicker" Margin="12" Width="288"
                 IsColorChannelTextInputVisible="False"
                 ColorChanged="ColorPicker_ColorChanged"/>
        </StackPanel>
    </Grid>
</Page>

MainPage.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using Windows.Foundation;
using Windows.UI;
using Windows.UI.WindowManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Hosting;
using Windows.UI.Xaml.Media;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace HelloAppWindow
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainPage : Page
    {
        AppWindow colorPickerAppWindow;

        // Track open app windows in a Dictionary.
        public static Dictionary<UIContext, AppWindow> AppWindows { get; set; }
            = new Dictionary<UIContext, AppWindow>();

        // Track the last opened dialog so you can close it if another dialog tries to open.
        public static ContentDialog CurrentDialog { get; set; } = null;

        public MainPage()
        {
            this.InitializeComponent();
        }

        private async void ShowNewWindowButton_Click(object sender, RoutedEventArgs e)
        {
            // Create a new window.
            AppWindow appWindow = await AppWindow.TryCreateAsync();

            // Create a Frame and navigate to the Page you want to show in the new window.
            Frame appWindowContentFrame = new Frame();
            appWindowContentFrame.Navigate(typeof(AppWindowPage));

            // Get a reference to the page instance and assign the
            // newly created AppWindow to the MyAppWindow property.
            AppWindowPage page = (AppWindowPage)appWindowContentFrame.Content;
            page.MyAppWindow = appWindow;
            page.TextColorBrush = new SolidColorBrush(colorPicker.Color);

            // Attach the XAML content to the window.
            ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);

            // Add the new page to the Dictionary using the UIContext as the Key.
            AppWindows.Add(appWindowContentFrame.UIContext, appWindow);
            appWindow.Title = "App Window " + AppWindows.Count.ToString();

            // When the window is closed, be sure to release XAML resources
            // and the reference to the window.
            appWindow.Closed += delegate
            {
                MainPage.AppWindows.Remove(appWindowContentFrame.UIContext);
                appWindowContentFrame.Content = null;
                appWindow = null;
            };

            // Show the window.
            await appWindow.TryShowAsync();
        }

        private async void DialogButton_Click(object sender, RoutedEventArgs e)
        {
            ContentDialog importantDialog = new ContentDialog
            {
                Title = "Important dialog",
                Content = "This dialog can only be dismissed by clicking Ok.",
                CloseButtonText = "Ok"
            };

            if (MainPage.CurrentDialog != null)
            {
                MainPage.CurrentDialog.Hide();
            }
            // Do not track this dialog as the MainPage.CurrentDialog.
            // It should only be closed by clicking the Ok button.
            MainPage.CurrentDialog = null;

            try
            {
                ContentDialogResult result = await importantDialog.ShowAsync();
            }
            catch (Exception)
            {
                // The dialog didn't open, probably because another dialog is already open.
            }
        }

        private async void DetachColorPickerButton_Click(object sender, RoutedEventArgs e)
        {
            // Create the color picker window.
            if (colorPickerAppWindow == null)
            {
                colorPickerContainer.Children.Remove(colorPicker);
                colorPickerContainer.Visibility = Visibility.Collapsed;

                Grid appWindowRootGrid = new Grid();
                appWindowRootGrid.Children.Add(colorPicker);

                // Create a new window
                colorPickerAppWindow = await AppWindow.TryCreateAsync();
                colorPickerAppWindow.RequestMoveAdjacentToCurrentView();
                colorPickerAppWindow.RequestSize(new Size(300, 428));
                colorPickerAppWindow.Title = "Color picker";

                // Attach the XAML content to our window
                ElementCompositionPreview.SetAppWindowContent(colorPickerAppWindow, appWindowRootGrid);

                // Make sure to release the reference to this window, 
                // and release XAML resources, when it's closed
                colorPickerAppWindow.Closed += delegate
                {
                    appWindowRootGrid.Children.Remove(colorPicker);
                    appWindowRootGrid = null;
                    colorPickerAppWindow = null;

                    colorPickerContainer.Children.Add(colorPicker);
                    colorPickerContainer.Visibility = Visibility.Visible;
                };
            }
            // Show the window.
            await colorPickerAppWindow.TryShowAsync();
        }

        private void ColorPicker_ColorChanged(ColorPicker sender, ColorChangedEventArgs args)
        {
            NewWindowButton.Background = new SolidColorBrush(args.NewColor);
        }

        private async void CloseAllButton_Click(object sender, RoutedEventArgs e)
        {
            while (AppWindows.Count > 0)
            {
                await AppWindows.Values.First().CloseAsync();
            }
        }
    }
}

AppWindowPage.xaml

<Page
    x:Class="HelloAppWindow.AppWindowPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:HelloAppWindow"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <Grid>
        <TextBlock x:Name="TitleTextBlock" Text="Hello AppWindow!" FontSize="24" HorizontalAlignment="Center" Margin="24"/>

        <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
            <Button Content="Open dialog" Click="DialogButton_Click"
                    Width="200" Margin="0,4"/>
            <Button Content="Move window" Click="MoveWindowButton_Click"
                    Width="200" Margin="0,4"/>
            <ToggleButton Content="Compact Overlay" x:Name="compactOverlayButton" Click="CompactOverlayButton_Click"
                          Width="200" Margin="0,4"/>
            <ToggleButton Content="Full Screen" x:Name="fullScreenButton" Click="FullScreenButton_Click"
                          Width="200" Margin="0,4"/>
            <Grid>
                <TextBlock Text="Size:"/>
                <TextBlock x:Name="SizeText" HorizontalAlignment="Right"/>
            </Grid>
            <Grid>
                <TextBlock Text="Presentation:"/>
                <TextBlock x:Name="ConfigText" HorizontalAlignment="Right"/>
            </Grid>
        </StackPanel>
    </Grid>
</Page>

AppWindowPage.xaml.cs

using System;
using Windows.Foundation;
using Windows.Foundation.Metadata;
using Windows.UI;
using Windows.UI.WindowManagement;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media;

// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=234238

namespace HelloAppWindow
{
    /// <summary>
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class AppWindowPage : Page
    {
        AppWindow window;

        public AppWindow MyAppWindow { get; set; }

        public SolidColorBrush TextColorBrush { get; set; } = new SolidColorBrush(Colors.Black);

        public AppWindowPage()
        {
            this.InitializeComponent();

            Loaded += AppWindowPage_Loaded;
        }

        private void AppWindowPage_Loaded(object sender, RoutedEventArgs e)
        {
            // Get the reference to this AppWindow that was stored when it was created.
            window = MainPage.AppWindows[this.UIContext];

            // Set up event handlers for the window.
            window.Changed += Window_Changed;

            TitleTextBlock.Foreground = TextColorBrush;
        }

        private async void DialogButton_Click(object sender, RoutedEventArgs e)
        {
            ContentDialog simpleDialog = new ContentDialog
            {
                Title = "Content dialog",
                Content = "Dialog box for " + window.Title,
                CloseButtonText = "Ok"
            };

            if (MainPage.CurrentDialog != null)
            {
                MainPage.CurrentDialog.Hide();
            }
            MainPage.CurrentDialog = simpleDialog;

            // Use this code to associate the dialog to the appropriate AppWindow by setting
            // the dialog's XamlRoot to the same XamlRoot as an element that is already 
            // present in the AppWindow.
            if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
            {
                simpleDialog.XamlRoot = ((Button)sender).XamlRoot;
            }

            try
            {
                ContentDialogResult result = await simpleDialog.ShowAsync();
            }
            catch (Exception)
            {
                // The dialog didn't open, probably because another dialog is already open.
            }
        }

        private void Window_Changed(AppWindow sender, AppWindowChangedEventArgs args)
        {
            if (args.DidAvailableWindowPresentationsChange)
            {
                EnablePresentationButtons(sender);
            }

            if (args.DidWindowPresentationChange)
            {
                ConfigText.Text = window.Presenter.GetConfiguration().Kind.ToString();
            }

            if (args.DidSizeChange)
            {
                SizeText.Text = window.GetPlacement().Size.ToString();
            }
        }

        private void EnablePresentationButtons(AppWindow window)
        {
            // Check whether the current AppWindowPresenter supports CompactOverlay.
            if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.CompactOverlay))
            {
                // Show the CompactOverlay button...
                compactOverlayButton.Visibility = Visibility.Visible;
            }
            else
            {
                // Hide the CompactOverlay button...
                compactOverlayButton.Visibility = Visibility.Collapsed;
            }

            // Check whether the current AppWindowPresenter supports FullScreen?
            if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.FullScreen))
            {
                // Show the FullScreen button...
                fullScreenButton.Visibility = Visibility.Visible;
            }
            else
            {
                // Hide the FullScreen button...
                fullScreenButton.Visibility = Visibility.Collapsed;
            }
        }

        private void CompactOverlayButton_Click(object sender, RoutedEventArgs e)
        {
            if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.CompactOverlay)
            {
                window.Presenter.RequestPresentation(AppWindowPresentationKind.CompactOverlay);
                fullScreenButton.IsChecked = false;
            }
            else
            {
                window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
            }
        }

        private void FullScreenButton_Click(object sender, RoutedEventArgs e)
        {
            if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.FullScreen)
            {
                window.Presenter.RequestPresentation(AppWindowPresentationKind.FullScreen);
                compactOverlayButton.IsChecked = false;
            }
            else
            {
                window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
            }
        }

        private void MoveWindowButton_Click(object sender, RoutedEventArgs e)
        {
            DisplayRegion displayRegion = window.GetPlacement().DisplayRegion;
            double displayRegionWidth = displayRegion.WorkAreaSize.Width;
            double windowWidth = window.GetPlacement().Size.Width;
            int horizontalOffset = (int)(displayRegionWidth - windowWidth);
            window.RequestMoveRelativeToDisplayRegion(displayRegion, new Point(horizontalOffset, 0));
        }
    }
}