Notitie
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen u aan te melden of de directory te wijzigen.
Voor toegang tot deze pagina is autorisatie vereist. U kunt proberen de mappen te wijzigen.
AppWindow en de bijbehorende API's vereenvoudigen het maken van apps met meerdere vensters door uw app-inhoud in secundaire vensters weer te geven terwijl u nog steeds aan dezelfde UI-thread in elk venster werkt.
Opmerking
AppWindow is momenteel beschikbaar als preview-versie. Dit betekent dat u apps kunt indienen die AppWindow gebruiken in de Store, maar sommige platform- en frameworkonderdelen zijn bekend dat ze niet werken met AppWindow (zie Beperkingen).
Hier laten we enkele scenario's voor meerdere vensters zien met een voorbeeld-app met de naam HelloAppWindow. De voorbeeld-app demonstreert de volgende functionaliteit:
- Maak een besturingselement los van de hoofdpagina en open het in een nieuw venster.
- Open nieuwe exemplaren van een pagina in nieuwe vensters.
- Stel programmatisch de grootte en positie van nieuwe vensters in de app in.
- Koppel een ContentDialog aan het juiste venster in de app.
Voorbeeld-app met één venster
Voorbeeld-app met losgekoppelde kleurenkiezer en secundair venster
Belangrijke API's: Windows.UI.WindowManagement-naamruimte, AppWindow-klasse
API-overzicht
De AppWindow-klasse en andere API's in de WindowManagement-naamruimte zijn beschikbaar vanaf Windows 10, versie 1903 (SDK 18362). Als uw app is gericht op eerdere versies van Windows 10, moet u ApplicationView gebruiken om secundaire vensters te maken. WindowManagement-API's zijn nog in ontwikkeling en hebben beperkingen zoals beschreven in de API-referentiedocumenten.
Hier volgen enkele belangrijke API's die u gebruikt om inhoud in een AppWindow weer te geven.
AppVenster
De AppWindow-klasse kan worden gebruikt om een deel van een UWP-app weer te geven in een secundair venster. Het is vergelijkbaar met een ApplicationView, maar niet hetzelfde in gedrag en levensduur. Een belangrijke functie van AppWindow is dat elk exemplaar dezelfde ui-verwerkingsthread (inclusief de gebeurtenisverzender) deelt waaruit ze zijn gemaakt, waardoor apps met meerdere vensters worden vereenvoudigd.
U kunt alleen XAML-inhoud verbinden met uw AppWindow, er is geen ondersteuning voor systeemeigen DirectX- of Holographic-inhoud. U kunt echter een XAML SwapChainPanel weergeven waarop DirectX-inhoud wordt gehost.
Vensteromgeving
De WindowingEnvironment-API laat u weten over de omgeving waarin uw app wordt gepresenteerd, zodat u uw app naar behoefte kunt aanpassen. Het beschrijft het soort venster dat door de omgeving wordt ondersteund; Als de app bijvoorbeeld Overlapped wordt uitgevoerd op een pc of Tiled als de app wordt uitgevoerd op een Xbox. Het biedt ook een set DisplayRegion-objecten waarin de gebieden worden beschreven waarin een app kan worden weergegeven op een logische weergave.
DisplayRegion
De DisplayRegion-API beschrijft de regio waarin een weergave kan worden weergegeven aan een gebruiker op een logische weergave; Op een desktop-pc is dit bijvoorbeeld het volledige scherm min het gebied van de taakbalk. Het is niet noodzakelijkerwijs een 1:1-toewijzing met het fysieke schermoppervlak van de achtergrondmonitor. Er kunnen meerdere weergaveregio's binnen dezelfde monitor zijn, of een DisplayRegion kan zodanig worden geconfigureerd dat deze meerdere beeldschermen omvatten als deze monitors homogeen zijn in alle aspecten.
AppWindowPresenter
Met de AppWindowPresenter-API kunt u eenvoudig overschakelen naar vooraf gedefinieerde configuraties zoals FullScreen of CompactOverlay. Deze configuraties bieden de gebruiker een consistente ervaring op elk apparaat dat ondersteuning biedt voor de configuratie.
UIContext
UIContext is een unieke id voor een app-venster of -weergave. Deze wordt automatisch gemaakt en u kunt de eigenschap UIElement.UIContext gebruiken om de UIContext op te halen. Elk UIElement in de XAML-structuur heeft dezelfde UIContext.
UIContext is belangrijk omdat API's zoals Window.Current en het GetForCurrentView patroon afhankelijk zijn van één ApplicationView/CoreWindow met één XAML-structuur per thread om mee te werken. Dit is niet het geval wanneer u een AppWindow gebruikt, dus u gebruikt UIContext om een bepaald venster te identificeren.
XamlRoot
De XamlRoot-klasse bevat een XAML-elementstructuur, verbindt deze met het vensterhostobject (bijvoorbeeld appWindow of ApplicationView) en biedt informatie zoals grootte en zichtbaarheid. U maakt geen XamlRoot-object rechtstreeks. In plaats daarvan wordt er een gemaakt wanneer u een XAML-element koppelt aan een AppWindow. Vervolgens kunt u de eigenschap UIElement.XamlRoot gebruiken om de XamlRoot op te halen.
Zie Code draagbaar maken voor vensterhosts voor meer informatie over UIContext en XamlRoot.
Een nieuw venster weergeven
Laten we eens kijken naar de stappen om inhoud weer te geven in een nieuwe AppWindow.
Een nieuw venster weergeven
Roep de statische AppWindow.TryCreateAsync aan methode om een nieuwe AppWindow-te maken.
AppWindow appWindow = await AppWindow.TryCreateAsync();Maak de vensterinhoud.
Normaal gesproken maakt u een XAML-frame en navigeert u vervolgens naar een XAML-pagina waar u uw app-inhoud hebt gedefinieerd. Voor meer informatie over frames en pagina's, zie Peer-to-peernavigatie tussen twee pagina's.
Frame appWindowContentFrame = new Frame(); appWindowContentFrame.Navigate(typeof(AppWindowMainPage));U kunt echter elke XAML-inhoud weergeven in de AppWindow, niet alleen een frame en pagina. U kunt bijvoorbeeld slechts één besturingselement weergeven, zoals ColorPicker, of u kunt een SwapChainPanel weergeven dat DirectX-inhoud bevat.
Roep de methode ElementCompositionPreview.SetAppWindowContent aan om de XAML-inhoud aan de AppWindow toe te voegen.
ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);Met de aanroep van deze methode wordt een XamlRoot-object gemaakt en ingesteld als de eigenschap XamlRoot voor het opgegeven UIElement.
U mag deze methode slechts eenmaal aanroepen per AppWindow-exemplaar. Nadat de inhoud is ingesteld, mislukken verdere aanroepen naar SetAppWindowContent voor dit AppWindow-exemplaar. Als u de AppWindow-inhoud probeert los te koppelen door een null UIElement-object door te geven, mislukt de aanroep.
Roep de methode AppWindow.TryShowAsync aan om het nieuwe venster weer te geven.
await appWindow.TryShowAsync();
Resources vrijgeven wanneer een venster wordt gesloten
U moet altijd de gebeurtenis AppWindow.Closed afhandelen om XAML-resources (de AppWindow-inhoud) en verwijzingen naar de AppWindow vrij te geven.
appWindow.Closed += delegate
{
appWindowContentFrame.Content = null;
appWindow = null;
};
Aanbeveling
U moet de hoeveelheid code in uw Closed gebeurtenis-handler behouden tot het minimumbedrag dat mogelijk is om onverwachte problemen te voorkomen.
Exemplaren van AppWindow bijhouden
Afhankelijk van hoe u meerdere vensters in uw app gebruikt, hoeft u de exemplaren van AppWindow die u maakt, mogelijk of niet bij te houden. In HelloAppWindow het voorbeeld ziet u een aantal verschillende manieren waarop u doorgaans een AppWindow gebruikt. Hier bekijken we waarom deze vensters moeten worden bijgehouden en hoe u dit kunt doen.
Eenvoudig bijhouden
Het venster kleurkiezer fungeert als host voor één XAML-besturingselement en de code voor interactie met de kleurenkiezer bevindt zich allemaal in het MainPage.xaml.cs bestand. Het venster kleurkiezer staat slechts één exemplaar toe en is in wezen een uitbreiding van MainWindow. Om ervoor te zorgen dat er slechts één exemplaar wordt gemaakt, wordt het kleurenkiezervenster bijgehouden met een variabele op paginaniveau. Voordat u een nieuw kleurenkiezervenster maakt, controleert u of er een instantie bestaat en als dat het geval is, slaat u de stappen over om een nieuw venster te maken en voert u in het bestaande venster TryShowAsync uit.
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();
}
Een instance van AppWindow bijhouden in de gehoste content
Het AppWindowPage venster fungeert als host voor een volledige XAML-pagina en de code voor interactie met de pagina bevindt zich in AppWindowPage.xaml.cs. Hiermee kunnen meerdere exemplaren worden toegestaan, die elk onafhankelijk van elkaar functioneren.
Met de functionaliteit van de pagina kunt u het venster beheren, het instellen op FullScreen of CompactOverlay, en wordt er ook geluisterd naar AppWindow.Changed-gebeurtenissen om informatie over het venster weer te geven. Als u deze API's wilt aanroepen, AppWindowPage moet u verwijzen naar het AppWindow-exemplaar dat als host fungeert.
Als dat alles is wat u nodig hebt, kunt u een eigenschap maken in AppWindowPage en de AppWindow-instantie eraan toewijzen wanneer u deze maakt.
AppWindowPage.xaml.cs
Maak in AppWindowPageeen eigenschap voor het opslaan van de AppWindow-verwijzing.
public sealed partial class AppWindowPage : Page
{
public AppWindow MyAppWindow { get; set; }
// ...
}
MainPage.xaml.cs
Krijg in MainPage een verwijzing naar de pagina-instantie en ken de nieuw gemaakte AppWindow toe aan de eigenschap in 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;
// ...
}
App-vensters bijhouden met UIContext
Mogelijk wilt u ook toegang hebben tot de AppWindow-exemplaren vanuit andere onderdelen van uw app. Kan bijvoorbeeld MainPage een knop 'Alles sluiten' hebben waarmee alle bijgehouden exemplaren van AppWindow worden gesloten.
In dit geval moet u de UIContext unieke identifier gebruiken om de vensterinstanties in een Dictionarybij te houden.
MainPage.xaml.cs
Maak in MainPagede woordenlijst als een statische eigenschap. Voeg vervolgens de pagina toe aan de woordenlijst wanneer u deze maakt en verwijder deze wanneer de pagina is gesloten. U kunt de UIContext ophalen uit het inhoudsframe (appWindowContentFrame.UIContext) nadat u ElementCompositionPreview.SetAppWindowContent hebt aangeroepen.
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
Als u de AppWindow--instantie in uw AppWindowPage code wilt gebruiken, gebruik dan de UIContext- van de pagina om deze op te halen uit de statische Dictionary in MainPage. U moet dit doen in de Loaded gebeurtenis-handler van de pagina in plaats van in de constructor, zodat UIContext niet null is. U kunt de UIContext ophalen op de pagina: 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;
}
// ...
}
Opmerking
In HelloAppWindow het voorbeeld ziet u beide manieren om het venster in AppWindowPage te houden, maar u gebruikt meestal een van de twee, niet beide.
Venstergrootte en plaatsing aanvragen
De AppWindow-klasse heeft verschillende methoden die u kunt gebruiken om de grootte en plaatsing van het venster te bepalen. Zoals geïmpliceerd door de methodenamen, kan het systeem de aangevraagde wijzigingen al dan niet respecteren, afhankelijk van omgevingsfactoren.
Call RequestSize om een gewenste venstergrootte op te geven, zoals deze.
colorPickerAppWindow.RequestSize(new Size(300, 428));
De methoden voor het beheren van vensterplaatsing worden RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.
In dit voorbeeld verplaatst deze code het venster naar de hoofdweergave waaruit het venster is gehaald.
colorPickerAppWindow.RequestMoveAdjacentToCurrentView();
Als u informatie wilt over de huidige grootte en plaatsing van het venster, roept u GetPlacement aan. Hiermee wordt een AppWindowPlacement--object geretourneerd dat de huidige DisplayRegion-, Offseten Grootte van het venster biedt.
U kunt deze code bijvoorbeeld aanroepen om het venster naar de rechterbovenhoek van de weergave te verplaatsen. Deze code moet worden aangeroepen nadat het venster is weergegeven; anders is de venstergrootte die wordt geretourneerd door de aanroep naar GetPlacement 0,0 en is de offset onjuist.
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));
Een presentatieconfiguratie aanvragen
Met de klasse AppWindowPresenter kunt u een AppWindow weergeven met behulp van een vooraf gedefinieerde configuratie die geschikt is voor het apparaat waarop deze wordt weergegeven. U kunt een AppWindowPresentationConfiguration-waarde gebruiken om het venster in FullScreen of CompactOverlay de modus te plaatsen.
In dit voorbeeld ziet u hoe u het volgende doet:
- Gebruik de gebeurtenis AppWindow.Changed om een melding te ontvangen als de beschikbare vensterpresentaties veranderen.
- Gebruik de eigenschap AppWindow.Presenter om de huidige AppWindowPresenterte verkrijgen.
- Roep IsPresentationSupported aan om te zien of een specifiek AppWindowPresentationKind wordt ondersteund.
- Roep GetConfiguration aan om te controleren welk type configuratie momenteel wordt gebruikt.
- Roep RequestPresentation aan om de huidige configuratie te wijzigen.
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-elementen opnieuw gebruiken
Met een AppWindow kunt u meerdere XAML-structuren met dezelfde UI-thread hebben. Een XAML-element kan echter slechts eenmaal worden toegevoegd aan een XAML-structuur. Als u een deel van uw gebruikersinterface van het ene venster naar het andere wilt verplaatsen, moet u de plaatsing ervan beheren in de XAML-structuur.
In dit voorbeeld ziet u hoe u een ColorPicker controle opnieuw kunt gebruiken tijdens het verplaatsen van het hoofdvenster naar een secundair venster.
De kleurkiezer wordt gedeclareerd in de XAML voor MainPage, wat deze in de MainPage XAML-boom plaatst.
<StackPanel x:Name="colorPickerContainer" Grid.Column="1" Background="WhiteSmoke">
<Button Click="DetachColorPickerButton_Click" HorizontalAlignment="Right">
<FontIcon FontFamily="Segoe MDL2 Assets" Glyph="" />
</Button>
<ColorPicker x:Name="colorPicker" Margin="12" Width="288"
IsColorChannelTextInputVisible="False"
ColorChanged="ColorPicker_ColorChanged"/>
</StackPanel>
Wanneer de kleurkiezer wordt losgekoppeld om in een nieuwe *AppWindow* te worden geplaatst, moet u het eerst verwijderen uit de MainPage XAML-structuur door het uit de oudercontainer te halen. Hoewel dit niet vereist is, verbergt dit voorbeeld ook de oudercontainer.
colorPickerContainer.Children.Remove(colorPicker);
colorPickerContainer.Visibility = Visibility.Collapsed;
Vervolgens kunt u deze toevoegen aan de nieuwe XAML-structuur. Hier maakt u eerst een Grid dat de bovenliggende container voor de ColorPicker is en voegt u de ColorPicker als een kind van de Grid toe. (Hiermee kunt u de ColorPicker later eenvoudig uit deze XAML-structuur verwijderen.) Vervolgens stelt u het raster in als de hoofdmap van de XAML-structuur in het nieuwe venster.
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);
Wanneer de AppWindow is gesloten, keert u het proces om. Verwijder eerst de ColorPicker uit het raster en voeg deze toe als een onderliggend element van de StackPanel in 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();
}
Een dialoogvenster weergeven
Standaard worden inhoudsdialoogvensters modaal ten opzichte van de hoofdtoepassingsweergave weergegeven. Wanneer u een ContentDialog in een AppWindowgebruikt, moet u de XamlRoot van het dialoog handmatig instellen op de root van de XAML-host.
Hiervoor stelt u de eigenschap XamlRoot van ContentDialog in op dezelfde XamlRoot als een element dat al in de AppWindow aanwezig is. Deze code bevindt zich in de klik-gebeurtenishandler van een knop, zodat u de verzender (de aangeklikte knop) kunt gebruiken om de XamlRoot op te halen.
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
simpleDialog.XamlRoot = ((Button)sender).XamlRoot;
}
Als u een of meer AppWindows naast het hoofdvenster (ApplicationView) hebt geopend, kan elk venster proberen een dialoogvenster te openen, omdat het modale dialoogvenster alleen het venster blokkeert waarin het is geroot. Er kan echter slechts één ContentDialog per thread tegelijk worden geopend. Als u probeert twee ContentDialogs te openen, wordt er een exception gegenereerd, zelfs als ze proberen te openen in afzonderlijke AppWindows.
Als u dit wilt beheren, moet u ten minste het dialoogvenster in een try/catch blok openen om de uitzondering te ondervangen voor het geval er al een ander dialoogvenster is geopend.
try
{
ContentDialogResult result = await simpleDialog.ShowAsync();
}
catch (Exception)
{
// The dialog didn't open, probably because another dialog is already open.
}
Een andere manier om dialoogvensters te beheren, is het bijhouden van het dialoogvenster dat momenteel is geopend en het dialoogvenster sluiten voordat u een nieuw dialoogvenster probeert te openen. Hier maakt u een statische eigenschap in MainPage genaamd CurrentDialog voor dit doel.
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;
// ...
}
Vervolgens controleert u of er een dialoogvenster is geopend en roept u de methode Verbergen aan om het te sluiten. Wijs ten slotte het nieuwe dialoogvenster toe aan CurrentDialog en probeer het weer te geven.
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.
}
}
Als het niet wenselijk is om een dialoogvenster programmatisch te sluiten, wijst u het niet toe als de CurrentDialog. Hier toont MainPage een belangrijk dialoogvenster dat alleen moet worden gesloten wanneer de gebruiker op Okklikt. Omdat het niet is toegewezen als de CurrentDialog, wordt er geen poging gedaan om het programmatisch te sluiten.
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.
}
}
// ...
}
De volledige code
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="" />
</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));
}
}
}