Megosztás a következőn keresztül:


Több nézet megjelenítése az AppWindow használatával

Az AppWindow és a kapcsolódó API-k leegyszerűsítik a többablakos alkalmazások létrehozását azáltal, hogy lehetővé teszik az alkalmazás tartalmának megjelenítését a másodlagos ablakokban, miközben továbbra is ugyanazon a felhasználói felületen dolgoznak az egyes ablakokon.

Megjegyzés:

Az AppWindow jelenleg előzetes verzióban érhető el. Ez azt jelenti, hogy az AppWindow-t használó alkalmazásokat beküldheti az Áruházba, de egyes platform- és keretrendszerösszetevőkről ismert, hogy nem működnek az AppWindow-nal (lásd : Korlátozások).

Itt bemutatunk néhány forgatókönyvet több ablakhoz egy úgynevezett HelloAppWindowmintaalkalmazással. A mintaalkalmazás a következő funkciókat mutatja be:

  • Törölje a vezérlő rögzítését a főoldalról, és nyissa meg egy új ablakban.
  • Nyisson meg új lappéldányokat az új ablakokban.
  • Programozott módon méretezheti és helyezheti el az új ablakokat az alkalmazásban.
  • ContentDialog társítása az alkalmazás megfelelő ablakával.

Mintaalkalmazás egyetlen ablakkal

Mintaalkalmazás egyetlen ablakkal

mintaalkalmazás leválasztott színválasztóval és másodlagos ablakkal

Mintaalkalmazás szabadon lebegő színválasztóval és másodlagos ablakkal

Fontos API-k: Windows.UI.WindowManagement névtér, AppWindow osztály

API – Áttekintés

Az AppWindow osztály és a WindowsManagement névtér egyéb API-i a Windows 10 1903-es verziójától (SDK 18362) érhetők el. Ha az alkalmazás a Windows 10 korábbi verzióit célozza meg, az ApplicationView használatával másodlagos Windows-kell létrehoznia. A WindowManagement API-k még fejlesztés alatt állnak, és korlátozások az API referenciadokumentumaiban leírtak szerint.

Az alábbiakban néhány fontos API-t használ az AppWindow-tartalmak megjelenítéséhez.

Alkalmazásablak

Az AppWindow osztály használható az UWP-alkalmazások egy részének másodlagos ablakban való megjelenítésére. Ez a fogalom hasonló az ApplicationView-hoz, de eltérő a viselkedése és élettartama. Az AppWindow fő funkciója, hogy minden példány ugyanazt a felhasználói felületi feldolgozási szálat használja (beleértve az eseményszolgáltatót is), amelyből létrehozták őket, ami leegyszerűsíti a többablakos alkalmazásokat.

Az XAML-tartalmat csak az AppWindow-hoz csatlakoztathatja, a natív DirectX- és Holographic-tartalmak nem támogatottak. Azonban megjeleníthet egy XAML-SwapChainPanel, amely DirectX-tartalmat üzemeltet.

Ablakkezelő környezet

A WindowingEnvironment API tájékoztatja arról a környezetről, amelyben az alkalmazás megjelenik, hogy szükség szerint adaptálhassa az alkalmazást. Leírja, hogy milyen típusú ablakot támogat a környezet; Például Overlapped ha az alkalmazás PC-n fut, vagy Tiled ha az alkalmazás Xbox konzolon fut. Emellett DisplayRegion-objektumok készletét is biztosítja, amelyek leírják azokat a területeket, ahol egy alkalmazás megjeleníthető egy logikai kijelzőn.

MegjelenítésiRégió

A DisplayRegion API azt a régiót írja le, amelyben egy nézet megjeleníthető egy felhasználó számára egy logikai kijelzőn; Asztali pc-n például ez a teljes kijelző mínusz a tálca területe. Ez nem feltétlenül egy 1:1-es leképezés a háttérfigyelő fizikai megjelenítési területével. Ugyanazon a monitoron belül több megjelenítési régió is lehet, vagy a DisplayRegion konfigurálható úgy, hogy több monitorra is kiterjedjen, ha ezek a monitorok minden szempontból homogének.

AppWindowPresenter

Az AppWindowPresenter API segítségével egyszerűen válthat az ablakok előre definiált konfigurációkra, például FullScreen vagy CompactOverlay. Ezek a konfigurációk konzisztens élményt biztosítanak a felhasználónak minden olyan eszközön, amely támogatja a konfigurációt.

UIContext

Az UIContext egy alkalmazásablak vagy nézet egyedi azonosítója. Ez automatikusan létrejön, és a UIElement.UIContext tulajdonság használatával lekérheti az UIContextet. Az XAML-fa minden UIElement eleméhez ugyanaz a UIContext tartozik.

A UIContext azért fontos, mert az API-k, például a Window.Current és a GetForCurrentView minta azt igénylik, hogy egy szálonként egyetlen ApplicationView/CoreWindow és XAML-fa legyen, amellyel együtt dolgoznak. Nem ez a helyzet az AppWindow használata esetén, ezért a UIContext használatával azonosít egy adott ablakot.

XamlRoot

A XamlRoot osztály egy XAML elemfát tartalmaz, csatlakoztatja az ablakgazdaobjektumhoz (például az AppWindow-hoz vagy az ApplicationView-hoz), és olyan információkat biztosít, mint a méret és a láthatóság. Nem hozhat létre közvetlenül XamlRoot objektumot. Ehelyett akkor jön létre, amikor egy XAML-elemet csatol egy AppWindow-hoz. Ezután a UIElement.XamlRoot tulajdonság használatával lekérheti a XamlRoot tulajdonságot.

További információ az UIContext és az XamlRoot használatáról: A kód hordozhatóságának biztosítása különböző ablakos gazdagépeken.

Új ablak megjelenítése

Tekintsük meg az új AppWindow-tartalmak megjelenítésének lépéseit.

Új ablak megjelenítése

  1. Új AppWindow létrehozásához hívja meg a statikus AppWindow.TryCreateAsync metódust.

    AppWindow appWindow = await AppWindow.TryCreateAsync();
    
  2. Hozza létre az ablak tartalmát.

    Általában létrehoz egy XAML-Keretet, majd a Keretet egy XAML-Lapra navigálja, ahol meghatározta az alkalmazás tartalmát. A képkockákkal és a lapokkal kapcsolatos további információkért lásd a két oldal közötti közvetlen navigációt pontban.

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

    Az AppWindow-ban azonban bármilyen XAML-tartalmat megjeleníthet, nem csak kereteket és lapokat. Megjeleníthet például egyetlen vezérlőt, például a ColorPickert, vagy megjeleníthet egy SwapChainPanelt , amely DirectX-tartalmat üzemeltet.

  3. Hívja meg az ElementCompositionPreview.SetAppWindowContent metódust , hogy csatolja az XAML-tartalmat az AppWindow-hoz.

    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
    

    A metódus hívása létrehoz egy XamlRoot objektumot , és beállítja azt a megadott UIElement XamlRoot tulajdonságaként.

    Ezt a metódust appWindow-példányonként csak egyszer hívhatja meg. A tartalom beállítása után az AppWindow-példányhoz tartozó SetAppWindowContent további hívásai sikertelenek lesznek. Ha megkísérli az AppWindow tartalmának leválasztását egy null referenciájú UIElement objektum átadásával, a hívás sikertelen lesz.

  4. Hívja meg az AppWindow.TryShowAsync metódust az új ablak megjelenítéséhez.

    await appWindow.TryShowAsync();
    

Erőforrások felszabadítása egy ablak bezárásakor

Mindig az AppWindow.Closed eseményt kell kezelnie az XAML-erőforrások (az AppWindow-tartalom) kiadásához, valamint az AppWindow-ra mutató hivatkozások kiadásához.

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

Jótanács

A váratlan problémák elkerülése érdekében az eseménykezelőben Closed a kód mennyiségét a lehető legkisebbre kell tartania.

Az AppWindow példányainak nyomon követése

Attól függően, hogy miként használ több ablakot az alkalmazásban, előfordulhat, hogy nem kell nyomon követnie a létrehozott AppWindow-példányokat. A HelloAppWindow példa bemutat néhány különböző módszert, ahogyan az AppWindowáltalában használható. Itt áttekintjük, hogy miért érdemes nyomon követni ezeket az ablakokat, és hogyan kell elvégezni.

Egyszerű nyomon követés

A színválasztó ablak egyetlen XAML-vezérlőt üzemeltet, és a színválasztóval való interakció kódja mind a MainPage.xaml.cs fájlban található. A színválasztó ablak csak egyetlen példányt engedélyez, és lényegében a bővítménye MainWindow. Annak biztosítása érdekében, hogy csak egy példány létezzen, a színválasztó ablakot egy oldalszintű változó követi nyomon. Az új színválasztó ablak létrehozása előtt ellenőrizze, hogy létezik-e egy példány, és ha igen, hagyja ki az új ablak létrehozásához szükséges lépéseket, és csak hívja meg a TryShowAsync parancsot a meglévő ablakban.

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

AppWindow-példány nyomon követése az üzemeltetett tartalomban

A AppWindowPage ablak XAML-lapot üzemeltet, és a lapohoz való interakció kódja a AppWindowPage.xaml.cs-ben található. Több példányt is lehetővé tesz, amelyek mindegyike egymástól függetlenül működik.

A lap funkciója lehetővé teszi az ablak módosítását, beállítását FullScreen vagy CompactOverlay, valamint figyeli az AppWindow.Changed eseményeket az ablak információinak megjelenítéséhez. Ezeknek az API-knak AppWindowPage a meghívásához hivatkoznia kell az azt üzemeltető AppWindow-példányra.

Ha csak erre van szüksége, létrehozhat egy tulajdonságot a AppWindowPage-ban, majd a AppWindow példányát hozzárendelheti hozzá a létrehozásakor.

AppWindowPage.xaml.cs

Z AppWindowPage-ban hozzon létre egy tulajdonságot az AppWindow hivatkozás tárolásához.

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

    // ...
}

MainPage.xaml.cs

Szerezzen be egy hivatkozást a lappéldányra a MainPagehelyen, és rendelje hozzá az újonnan létrehozott AppWindow-t a AppWindowPagetulajdonságához.

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;

    // ...
}

Alkalmazásablakok nyomon követése az UIContext használatával

Előfordulhat, hogy az alkalmazás más részeiből is hozzá szeretne férni az AppWindow-példányokhoz . Lehet például egy MainPage 'minden bezárása' gomb, amely bezárja az AppWindow összes nyomon követett példányát.

Ebben az esetben a UIContext egyedi azonosítót kell használnia az ablakpéldányok nyomon követéséhez egy szótár.

MainPage.xaml.cs

A MainPage-ben hozz létre egy szótárt statikus tulajdonságként. Ezután a létrehozáskor vegye fel a lapot a szótárba, és távolítsa el a lap bezárásakor. Az UIContextet a Frame (appWindowContentFrame.UIContext) tartalomból hívhatja le, miután meghívta a ElementCompositionPreview.SetAppWindowContentmetódust.

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

Az AppWindow példányának használatához a AppWindowPage kódjában, használja a lap UIContext-et, hogy lekérje azt a MainPagestatikus szótárából. Ezt a lap Betöltött eseménykezelőjében kell elvégeznie, nem pedig a konstruktorban, hogy az UIContext ne legyen null értékű. Az UIContext a lapról érhető el: 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;
    }
    // ...
}

Megjegyzés:

A HelloAppWindow példa mindkét módszert mutatja az ablak nyomon követésére AppWindowPage, de általában az egyiket vagy a másikat fogja használni, nem mindkettőt.

Ablak méretének és elhelyezésének kérése

Az AppWindow osztály számos módszerrel szabályozhatja az ablak méretét és elhelyezését. Ahogy a metódusnevek is sugallják, a rendszer a környezeti tényezőktől függően elfogadhatja vagy figyelmen kívül hagyhatja a kért módosításokat.

Hívja meg a RequestSize parancsot a kívánt ablakméret megadásához, ehhez hasonlóan.

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

Az ablakelhelyezés kezelésére szolgáló módszerek neve RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.

Ebben a példában ez a kód áthelyezi az ablakot annak a fő nézetnek a mellette, ahonnan az ablak származik.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

Az ablak aktuális méretével és elhelyezésével kapcsolatos információkért hívja meg a GetPlacementet. Ez egy AppWindowPlacement objektumot ad vissza, amely biztosítja az ablak aktuális DisplayRegion, eltolásátés méretét.

Ezt a kódot hívhatja például úgy, hogy az ablakot a képernyő jobb felső sarkába helyezze. Ezt a kódot az ablak megjelenése után kell meghívni; ellenkező esetben a GetPlacement hívás által visszaadott ablakméret 0,0 lesz, és az eltolás helytelen lesz.

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

Bemutatókonfiguráció kérése

Az AppWindowPresenter osztály lehetővé teszi az AppWindow megjelenítését az eszköznek megfelelő előre definiált konfigurációval. Az AppWindowPresentationConfiguration érték használatával helyezheti el az ablakot FullScreen módba vagy CompactOverlay módba.

Ez a példa a következőket mutatja be:

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

XAML-elemek újrafelhasználása

Az AppWindow lehetővé teszi, hogy több XAML-fát kezeljen ugyanazzal a felhasználói felület szálával. Az XAML-elemek azonban csak egyszer vehetők fel egy XAML-fához. Ha a felhasználói felület egy részét az egyik ablakból a másikba szeretné áthelyezni, akkor azt az XAML-fában kell kezelnie.

Ez a példa bemutatja, hogyan használható újra egy ColorPicker-vezérlő a főablak és a másodlagos ablak közötti áthelyezés során.

A színválasztó a MainPageXAML-ben van deklarálva, ami a MainPage XAML-fába helyezi.

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

Ha a színválasztó el lett választva, hogy egy új AppWindow-ba helyezzük, először el kell távolítania azt a MainPage XAML-fából azáltal, hogy eltávolítja a szülőtárolójából. Bár nem kötelező, ez a példa a szülőtárolót is elrejti.

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

Ezután hozzáadhatja az új XAML-fához. Itt először létre kell hoznia egy Rács-et, amely a ColorPicker szülőtárolója lesz, majd gyermekként hozzáadja a Rácshoz a ColorPickert. (Így később egyszerűen eltávolíthatja a ColorPickert ebből az XAML-fából.) Ezután az új ablakban állítsa be a Rácsot az XAML-fa gyökerének.

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

Amikor a AppWindow bezárul, megfordítja a folyamatot. Először távolítsa el a ColorPicker-t a Grid-ból, majd adja hozzá a StackPanel gyermekéhez a MainPage-ban.

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

Párbeszédpanel megjelenítése

Alapértelmezés szerint a tartalom párbeszédpanelek modálisan jelennek meg a gyökér ApplicationView-hoz képest. Ha egy ContentDialog elemet használ egy AppWindowablakban, manuálisan kell beállítania a párbeszédpanel XamlRoot tulajdonságát az XAML-gazdagép gyökerére.

Ehhez állítsa be a ContentDialog XamlRoot tulajdonságát ugyanarra a XamlRoot-re, mint amire az AppWindow egy elemének XamlRoot-ja már be van állítva. Itt ez a kód egy gomb Kattintás eseménykezelőben található, így a küldő objektumot (a kattintott gomb) használva lekérheti a XamlRoot-ot.

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

Ha a főablakon (ApplicationView) kívül egy vagy több AppWindows is meg van nyitva, minden ablak megkísérlhet megnyitni egy párbeszédpanelt, mert a modális párbeszédpanel csak a gyökerező ablakot blokkolja. Szálanként azonban egyszerre csak egy ContentDialog lehet megnyitva. Két ContentDialog megnyitása kivételt eredményez, még akkor is, ha külön AppWindowsban próbálnak megnyitni.

Ahhoz, hogy ezt kezelje, legalább meg kell nyitnia a párbeszédpanelt egy try/catch-blokkban annak érdekében, hogy kezelje a kivételt, ha egy másik párbeszédpanel már meg van nyitva.

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

A párbeszédpanelek kezelésének másik módja az aktuálisan megnyitott párbeszédpanel nyomon követése és bezárása, mielőtt új párbeszédpanelt próbálna megnyitni. Itt egy statikus tulajdonságot hoz létre a MainPage-ban CurrentDialog néven erre a célra.

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;

   // ...
}

Ezután ellenőrizze, hogy van-e éppen megnyitott párbeszédablak, és ha van, hívja meg a Elrejtés metódust a bezárásához. Végül rendelje hozzá az új párbeszédpanelt CurrentDialog-hoz, és próbálja megmutatni.

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

Ha nem kívánatos egy párbeszédpanelt programozott módon bezárni, ne állítsa be azt CurrentDialog-ként. Itt MainPage egy fontos párbeszédpanelt jelenít meg, amelyet csak akkor szabad bezárni, ha a felhasználó Ok-re kattint. Mivel nincs hozzárendelve CurrentDialog, a program nem próbálja meg programozott módon bezárni.

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

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