Sdílet prostřednictvím


Zobrazení více zobrazení pomocí AppWindow

AppWindow a jeho související rozhraní API zjednodušují vytváření aplikací s více okny tím, že vám umožní zobrazit obsah aplikace v sekundárních oknech a současně pracovat na stejném vlákně uživatelského rozhraní v každém okně.

Poznámka:

AppWindow je aktuálně ve verzi Preview. To znamená, že můžete odesílat aplikace, které používají AppWindow, do obchodu, ale je známo, že některé komponenty platformy a architektury s AppWindow nefungují (viz Omezení).

Tady si ukážeme některé scénáře pro více oken s ukázkovou aplikací nazvanou HelloAppWindow. Ukázková aplikace ukazuje následující funkce:

  • Zrušte ukotvení ovládacího prvku z hlavní stránky a otevřete ho v novém okně.
  • Otevřete nové instance stránky v nových oknech.
  • Velikost a umístění nových oken v aplikaci prostřednictvím kódu programu
  • Přidružte ContentDialog k příslušnému okně v aplikaci.

Ukázková aplikace s jedním oknem

Ukázková aplikace s jedním oknem

Ukázková aplikace s nedokovaným výběrem barev a sekundárním oknem

Ukázková aplikace s neukotveným výběrem barev a sekundárním oknem

důležitá rozhraní API: obor názvů Windows.UI.WindowManagement, třída AppWindow

Přehled rozhraní API

Třída AppWindow a další rozhraní API v oboru názvů WindowManagement jsou k dispozici od Windows 10 verze 1903 (SDK 18362). Pokud vaše aplikace cílí na starší verze Windows 10, musíte k vytvoření sekundárních oken použít ApplicationView. Rozhraní API služby WindowManagement jsou stále ve vývoji a mají omezení, jak je popsáno v referenčních dokumentech k rozhraní API.

Tady jsou některá důležitá rozhraní API, která používáte k zobrazení obsahu v AppWindow.

Okno aplikace

Třídu AppWindow lze použít k zobrazení části aplikace pro UPW v sekundárním okně. Je podobné ApplicationViewv konceptu, ale liší se v chování a životnosti. Hlavní funkcí AppWindow je, že každá instance sdílí stejné vlákno zpracování uživatelského rozhraní (včetně dispečeru událostí), ze kterého byly vytvořeny, což zjednodušuje aplikace s více okny.

Obsah XAML můžete připojit jenom k AppWindow, není k dispozici žádná podpora nativního directX nebo holografického obsahu. Můžete ale zobrazit xaml SwapChainPanel , který hostuje obsah DirectX.

Okenní prostředí

Rozhraní API WindowingEnvironment vás informuje o prostředí, ve kterém se vaše aplikace prezentuje, abyste ji mohli podle potřeby přizpůsobit. Popisuje druh okna, které prostředí podporuje; Pokud je například Overlapped aplikace spuštěná na počítači nebo Tiled pokud je aplikace spuštěná na Xboxu. Poskytuje také sadu objektů DisplayRegion, které popisují oblasti, ve kterých může být aplikace zobrazena na logickém displeji.

Oblast zobrazení

Rozhraní API DisplayRegion popisuje oblast, ve které lze zobrazit zobrazení uživateli na logickém displeji; například na stolním počítači je to celý displej kromě oblasti hlavního panelu. Není to nutně mapování 1:1 s fyzickou zobrazovací plochou podpůrného monitoru. Ve stejném monitoru může být více oblastí zobrazení nebo lze oblast displayregion nakonfigurovat tak, aby se rozprostřela mezi více monitory, pokud jsou tyto monitory ve všech aspektech homogenní.

AppWindowPresenter

Rozhraní API AppWindowPresenter umožňuje snadno přepínat okna do předdefinovaných konfigurací, jako je FullScreen nebo CompactOverlay. Tyto konfigurace poskytují uživateli konzistentní prostředí na jakémkoli zařízení, které konfiguraci podporuje.

Kontext uživatelského rozhraní

UIContext je jedinečný identifikátor okna nebo zobrazení aplikace. Vytváří se automaticky a k načtení UIContext můžete použít vlastnost UIElement.UIContext. Každý prvek UIElement ve stromu XAML má stejný UIContext.

UIContext je důležitý, protože rozhraní API jako Window.Current a vzor GetForCurrentView spoléhají na to, že na každém vlákně existuje jeden CoreWindow s jedním stromem XAML, se kterým lze pracovat. To není případ, kdy použijete AppWindow, takže k identifikaci konkrétního okna použijete UIContext.

XamlRoot

Třída XamlRoot obsahuje strom elementů XAML, připojí ho k objektu hostitele okna (například AppWindow nebo ApplicationView) a poskytuje informace, jako je velikost a viditelnost. Objekt XamlRoot nevytvoříte přímo. Místo toho se vytvoří při připojení elementu XAML k AppWindow. Pak můžete použít vlastnost UIElement.XamlRoot k načtení XamlRoot.

Další informace o UIContext a XamlRoot naleznete v tématu „Jak přenést kód mezi různými hostiteli oken“ v části a.

Zobrazit nové okno

Pojďme se podívat na postup zobrazení obsahu v nové aplikaci AppWindow.

Zobrazení nového okna

  1. Zavolejte statickou metodu AppWindow.TryCreateAsync pro vytvoření nového AppWindow.

    AppWindow appWindow = await AppWindow.TryCreateAsync();
    
  2. Vytvořte obsah okna.

    Obvykle vytvoříte XAML rámec a pak v něm přejdete na stránku XAML , kde jste definovali obsah aplikace. Více informací o rámcích a stránkách viz téma Peer-to-peer navigace mezi dvěma stránkami.

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

    V AppWindow ale můžete zobrazit libovolný obsah XAML, ne jenom rámec a stránku. Můžete například zobrazit jenom jeden ovládací prvek, například ColorPicker, nebo můžete zobrazit SwapChainPanel , který je hostitelem obsahu DirectX.

  3. Zavolejte metodu ElementCompositionPreview.SetAppWindowContent pro připojení obsahu XAML k AppWindow.

    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
    

    Volání této metody vytvoří XamlRoot objekt a nastaví jej jako XamlRoot vlastnost pro zadané UIElement.

    Tuto metodu můžete volat pouze jednou pro instanci AppWindow. Po nastavení obsahu se další volání SetAppWindowContent pro tuto instanci AppWindow nezdaří. Pokud se také pokusíte odpojit obsah AppWindow předáním null UIElement objektu, volání selže.

  4. Voláním metody AppWindow.TryShowAsync zobrazte nové okno.

    await appWindow.TryShowAsync();
    

Uvolnění prostředků při zavření okna

Vždy byste měli zpracovat událost AppWindow.Closed, abyste mohli uvolnit prostředky XAML (obsah AppWindow) a odkazy na AppWindow.

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

Návod

Měli byste udržovat množství kódu ve své obslužné rutině události Closed co nejmenší, abyste se vyhnuli neočekávaným problémům.

Sledování instancí AppWindow

V závislosti na tom, jak ve své aplikaci používáte více oken, můžete nebo nemusíme udržovat přehled o instancích AppWindow, které vytvoříte. Příklad HelloAppWindow ukazuje několik různých způsobů, jak můžete obvykle použít AppWindow. Tady se podíváme, proč by se tato okna měla sledovat a jak to udělat.

Jednoduché sledování

Okno pro výběr barev je hostitelem jednoho ovládacího prvku XAML a kód pro interakci s výběrem barvy se nachází v MainPage.xaml.cs souboru. Okno pro výběr barvy umožňuje pouze jednu instanci a je v podstatě rozšířením MainWindow. Aby bylo zajištěno, že se vytvoří pouze jedna instance, bude okno pro výběr barvy sledováno s proměnnou na úrovni stránky. Před vytvořením nového okna pro výběr barvy zkontrolujete, jestli instance existuje, a pokud ano, přeskočte kroky k vytvoření nového okna a stačí volat TryShowAsync v existujícím okně.

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

Sledujte instanci AppWindow ve svém hostovaném obsahu

Okno AppWindowPage hostuje úplnou stránku XAML a kód pro interakci se stránkou se nachází v AppWindowPage.xaml.cs. Umožňuje více instancí, z nichž každá funguje nezávisle.

Funkce stránky umožňuje manipulovat s oknem, nastavit ho na FullScreen nebo CompactOverlaya také naslouchá na události AppWindow.Changed, aby zobrazila informace o okně. Aby AppWindowPage mohl volat tato rozhraní API, potřebuje odkaz na AppWindow, který je hostitelem.

Pokud je to vše, co potřebujete, můžete vytvořit vlastnost a AppWindowPage přiřadit k ní instanci AppWindow při jejím vytvoření.

AppWindowPage.xaml.cs

V AppWindowPage vytvořte vlastnost pro uchování odkazu na AppWindow.

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

    // ...
}

MainPage.xaml.cs

V MainPagezískáte odkaz na instanci stránky a přiřaďte nově vytvořené AppWindow k vlastnosti v 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;

    // ...
}

Sledování oken aplikací pomocí UIContext

Můžete také chtít mít přístup k instancím AppWindow z jiných částí aplikace. Můžete mít například MainPage tlačítko Zavřít vše, které zavře všechny sledované instance AppWindow.

V tomto případě byste měli použít identifikátor jedinečný UIContext ke sledování instancí okna ve slovníku.

MainPage.xaml.cs

V MainPageaplikaci vytvořte slovník jako statickou vlastnost. Potom přidejte stránku do slovníku, když ji vytvoříte, a po zavření stránky ji odeberte. Kontext uživatelského rozhraní můžete získat z Frame obsahu (appWindowContentFrame.UIContext) po zavolání 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

Pokud chcete použít instanci AppWindow ve vašem kódu AppWindowPage, použijte UIContext stránky k získání ze statického slovníku v MainPage. Měli byste to udělat v Načteno události stránky obslužném modulu události, nikoli v konstruktoru, aby UIContext nebyl null. UiContext můžete získat ze stránky: 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;
    }
    // ...
}

Poznámka:

Příklad HelloAppWindow ukazuje oba způsoby sledování okna v AppWindowPage, ale obvykle použijete jeden nebo druhý, ne oba.

Velikost a umístění okna žádosti

Třída AppWindow má několik metod, které můžete použít k řízení velikosti a umístění okna. Jak vyplývá z názvů metod, systém může nebo nemusí respektovat požadované změny v závislosti na environmentálních faktorech.

Zavolejte RequestSize pro zadání požadované velikosti okna, například takto.

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

Metody správy umístění okna mají název RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.

V tomto příkladu tento kód přesune okno vedle hlavního zobrazení, ze kterého se okno vytvoří.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

Chcete-li získat informace o aktuální velikosti a umístění okna, zavolejte GetPlacement. Vrací objekt AppWindowPlacement, který poskytuje aktuální DisplayRegion, posuna velikost okna.

Můžete například volat tento kód, který přesune okno do pravého horního rohu zobrazení. Tento kód se musí volat po zobrazení okna; Jinak velikost okna vrácená voláním GetPlacement bude 0,0 a posun bude nesprávný.

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

Vyžádání konfigurace prezentace

AppWindowPresenter třída umožňuje zobrazit AppWindow pomocí předdefinované konfigurace vhodné pro zařízení, na které se zobrazuje. K umístění okna do režimu nebo FullScreen můžete použít hodnotu CompactOverlay.

Tento příklad ukazuje, jak provést následující akce:

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

Opakované použití elementů XAML

AppWindow umožňuje mít více stromů XAML se stejným vláknem uživatelského rozhraní. Element XAML však lze přidat do stromu XAML pouze jednou. Pokud chcete přesunout část uživatelského rozhraní z jednoho okna do jiného, musíte ho spravovat ve stromu XAML.

Tento příklad ukazuje, jak znovu použít ovládací prvek ColorPicker při přesouvání mezi hlavním oknem a sekundárním oknem.

Výběr barvy je deklarován v XAML pro MainPage, který ho umístí do MainPage stromu XAML.

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

Když se výběr barvy odpojí, aby byl umístěn v nové aplikaci AppWindow, musíte ho nejprve odebrat ze stromu MainPage XAML odebráním z nadřazeného kontejneru. I když to není povinné, tento příklad také skryje nadřazený kontejner.

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

Pak ho můžete přidat do nového stromu XAML. Tady nejprve vytvoříte mřížku , která bude nadřazeným kontejnerem pro ColorPicker, a přidáte ColorPicker jako podřízenou položku mřížky. (To vám umožní později snadno odebrat ColorPicker z tohoto stromu XAML.) Potom nastavíte mřížku jako kořen stromu XAML v novém okně.

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

Když je AppWindow zavřený, vrátíte proces zpět. Nejprve odeberte ColorPicker z Grid, poté jej přidejte jako podřízený prvek do StackPanel v 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();
}

Zobrazit dialogové okno

Ve výchozím nastavení se obsahové dialogy zobrazují modálně vůči kořenové ApplicationView. Při použití ContentDialog uvnitř AppWindowmusíte ručně nastavit vlastnost XamlRoot dialogového okna na kořen hostitele XAML.

Tak provedete nastavení vlastnosti XamlRoot na stejnou XamlRoot jako prvek, který je již v AppWindow. Tento kód se nachází v obslužné rutině události kliknutí na tlačítko, takže můžete použít odesílatele (kliknutí na tlačítko) a získat XamlRoot.

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

Pokud máte kromě hlavního okna (ApplicationView) otevřené jedno nebo více oken AppWindows, může se každé okno pokusit otevřít dialogové okno, protože modální dialogové okno zablokuje jenom okno, ve kterém je zakořeněno. Najednou však může být otevřen pouze jeden ContentDialog na jedno vlákno. Při pokusu o otevření dvou ContentDialogů dojde k výjimce, i když se pokoušejí otevřít v samostatných oknech aplikace AppWindows.

Abyste toto řídili, měli byste alespoň otevřít dialogové okno v bloku try/catch, aby se zachytila výjimku v případě, že je již otevřené jiné dialogové okno.

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

Dalším způsobem, jak spravovat dialogy, je sledovat aktuálně otevřené dialogové okno a zavřít ho před otevřením nového dialogového okna. Tady vytvoříte statickou vlastnost MainPage volanou CurrentDialog pro tento účel.

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;

   // ...
}

Potom zkontrolujte, zda je aktuálně otevřené dialogové okno, a pokud ano, zavolejte metodu Skrýt pro zavření. Nakonec přiřaďte nové dialogové okno CurrentDialoga zkuste ho zobrazit.

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

Pokud není žádoucí, aby dialogové okno bylo zavřené programově, nepřiřaďte ho jako CurrentDialog. Tady MainPage zobrazí důležité dialogové okno, které by mělo být zavřeno pouze po kliknutí na tlačítko Ok. Vzhledem k tomu, že není přiřazen jako CurrentDialog, není proveden žádný pokus o zavření programově.

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.
        }
    }
    // ...
}

Kompletní kód

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