Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
AppWindow e le API correlate semplificano la creazione di app con più finestre. Permettono di mostrare i contenuti dell'app nelle finestre secondarie mantenendo lo stesso thread dell'interfaccia utente su ogni finestra.
Annotazioni
AppWindow è attualmente in anteprima. Ciò significa che puoi inviare app che usano AppWindow allo Store, ma alcuni componenti della piattaforma e del framework non funzionano con AppWindow (vedi Limitazioni).
Di seguito vengono illustrati alcuni scenari per più finestre con un'app di esempio denominata HelloAppWindow
. L'app di esempio illustra le funzionalità seguenti:
- Annullare l'ancoraggio di un controllo dalla pagina principale e aprirlo in una nuova finestra.
- Aprire nuove istanze di una pagina in nuove finestre.
- Programmando le dimensioni e la posizione delle nuove finestre nell'app.
- Associare il ContentDialog con la finestra appropriata nell'app.
'app di esempio con una singola finestra
App di esempio con selettore dei colori non ancorato e finestra secondaria
API importanti: spazio dei nomi Windows.UI.WindowManagement, classe AppWindow
Panoramica delle API
La classe AppWindow e altre API nello spazio dei nomi WindowManagement sono disponibili a partire da Windows 10 versione 1903 (SDK 18362). Se l'app è destinata a versioni precedenti di Windows 10, devi usare ApplicationView per creare finestre secondarie. Le API WindowManagement sono ancora in fase di sviluppo e presentano limitazioni , come descritto nella documentazione di riferimento sulle API.
Ecco alcune delle API importanti usate per visualizzare il contenuto in un'appWindow.
Finestra dell'app
La classe AppWindow può essere usata per visualizzare una parte di un'app UWP in una finestra secondaria. È simile al concetto di ApplicationView, ma non lo stesso nel comportamento e nella durata. Una funzionalità principale di AppWindow è che ogni istanza condivide lo stesso thread di elaborazione dell'interfaccia utente (incluso il dispatcher eventi) da cui è stata creata, semplificando le app con più finestre.
È possibile connettere il contenuto XAML solo a AppWindow, non è disponibile alcun supporto per il contenuto DirectX nativo o Holographic. Tuttavia, è possibile mostrare un SwapChainPanel XAML che ospita contenuti DirectX.
Ambiente di gestione delle finestre
L'API WindowingEnvironment consente di conoscere l'ambiente in cui viene presentata l'app in modo da poter adattare l'app in base alle esigenze. Descrive il tipo di finestra supportata dall'ambiente; ad esempio, Overlapped
se l'app è in esecuzione in un PC o Tiled
se l'app è in esecuzione su una Xbox. Fornisce inoltre un set di oggetti DisplayRegion che descrivono le aree in cui un'app può essere visualizzata in una visualizzazione logica.
Regione di Visualizzazione
L'API DisplayRegion descrive l'area in cui è possibile mostrare all'utente un contenuto su un display logico; ad esempio, su un PC desktop, si tratta del display completo meno l'area della barra delle applicazioni. Non è necessariamente una corrispondenza 1:1 con l'area di visualizzazione fisica del monitor posteriore. Possono essere presenti più aree di visualizzazione all'interno dello stesso monitor oppure un displayRegion può essere configurato per estendersi su più monitor se tali monitor sono omogenei in tutti gli aspetti.
AppWindowPresenter
L'API AppWindowPresenter consente di cambiare facilmente le finestre in configurazioni predefinite come FullScreen
o CompactOverlay
. Queste configurazioni offrono all'utente un'esperienza coerente in qualsiasi dispositivo che supporta la configurazione.
Contexto dell'interfaccia utente (UIContext)
UIContext è un identificatore univoco per una finestra o una visualizzazione dell'app. Viene creato automaticamente ed è possibile usare la proprietà UIElement.UIContext per recuperare uiContext . Ogni UIElement nell'albero XAML ha lo stesso UIContext.
UIContext è importante perché le API come Window.Current e il GetForCurrentView
pattern si basano sulla presenza di un singolo oggetto ApplicationView/CoreWindow con un singolo albero XAML per thread con cui possano lavorare. Questo non avviene quando si usa un'appWindow, quindi si usa UIContext per identificare una determinata finestra.
XamlRoot
La classe XamlRoot contiene un albero degli elementi XAML, lo connette all'oggetto host della finestra (ad esempio, AppWindow o ApplicationView) e fornisce informazioni come dimensioni e visibilità. Non crei direttamente un oggetto XamlRoot. Al contrario, ne viene creato uno quando si collega un elemento XAML a un'AppWindow. Puoi quindi usare la proprietà UIElement.XamlRoot per recuperare XamlRoot.
Per ulteriori informazioni su UIContext e XamlRoot, consulta Rendere il codice portabile tra ambienti di gestione delle finestre.
Mostra una nuova finestra
Esaminiamo i passaggi per visualizzare il contenuto in una nuova AppWindow.
Per visualizzare una nuova finestra
Chiamare il metodo statico AppWindow.TryCreateAsync per creare una nuova AppWindow.
AppWindow appWindow = await AppWindow.TryCreateAsync();
Creare il contenuto della finestra.
In genere, crei un FRAME XAML, quindi passa a Frame a un PAGINA XAML in cui hai definito il contenuto dell'app. Per ulteriori informazioni su frame e pagine, consulta la navigazione peer-to-peer tra due pagine .
Frame appWindowContentFrame = new Frame(); appWindowContentFrame.Navigate(typeof(AppWindowMainPage));
Tuttavia, puoi visualizzare qualsiasi contenuto XAML in AppWindow, non solo un frame e una pagina. Ad esempio, puoi mostrare solo un singolo controllo, ad esempio ColorPicker, oppure puoi mostrare un controllo SwapChainPanel che ospita contenuto DirectX.
Chiamare il metodo ElementCompositionPreview.SetAppWindowContent per associare il contenuto XAML ad AppWindow.
ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
La chiamata a questo metodo crea un oggetto XamlRoot e lo imposta come proprietà XamlRoot per l'oggetto UIElement specificato.
È possibile chiamare questo metodo una sola volta per ogni istanza di AppWindow. Dopo aver impostato il contenuto, le chiamate a SetAppWindowContent per questa istanza di AppWindow avranno esito negativo. Inoltre, se si tenta di disconnettere il contenuto di AppWindow passando un oggetto UIElement null, la chiamata avrà esito negativo.
Chiamare il metodo AppWindow.TryShowAsync per visualizzare la nuova finestra.
await appWindow.TryShowAsync();
Rilasciare le risorse quando una finestra viene chiusa
Devi sempre gestire l'evento AppWindow.Closed per rilasciare le risorse XAML (il contenuto di AppWindow) e i riferimenti ad AppWindow.
appWindow.Closed += delegate
{
appWindowContentFrame.Content = null;
appWindow = null;
};
Suggerimento
È consigliabile mantenere la quantità di codice nel Closed
gestore eventi al minimo possibile per evitare problemi imprevisti.
Tenere traccia delle istanze di AppWindow
A seconda di come usi più finestre nella tua app, potresti o meno dover tenere traccia delle istanze di AppWindow che crei. L'esempio HelloAppWindow
mostra alcuni modi diversi in cui solitamente potresti utilizzare un AppWindow. In questo caso, esamineremo il motivo per cui queste finestre devono essere monitorate e come eseguire questa operazione.
Tracciamento semplice
La finestra selezione colori ospita un singolo controllo XAML e il codice per interagire con la selezione colori risiede tutti nel MainPage.xaml.cs
file. La finestra selezione colori consente solo una singola istanza ed è essenzialmente un'estensione di MainWindow
. Per assicurarsi che venga creata una sola istanza, la finestra di selezione dei colori viene tracciata con una variabile a livello di pagina. Prima di creare una nuova finestra di selezione colori, verifica se esiste già un'istanza e, in caso affermativo, salta i passaggi per la creazione di una nuova finestra e chiama semplicemente TryShowAsync sulla finestra esistente.
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();
}
Tenere traccia di un'istanza di AppWindow nel contenuto che ospita
La AppWindowPage
finestra ospita una pagina XAML completa e il codice per interagire con la pagina si trova in AppWindowPage.xaml.cs
. Consente più istanze, ognuna delle quali funziona in modo indipendente.
La funzionalità della pagina permette di modificare la finestra, impostandola su FullScreen
o CompactOverlay
, e inoltre monitora gli eventi AppWindow.Changed per visualizzare informazioni sulla finestra. Per chiamare queste API, AppWindowPage
è necessario un riferimento all'istanza di AppWindow che lo ospita.
Se è tutto ciò di cui hai bisogno, puoi creare una proprietà in AppWindowPage
e assegnarle l'istanza di AppWindow quando la crei.
AppWindowPage.xaml.cs
In AppWindowPage
creare una proprietà per contenere il riferimento a AppWindow.
public sealed partial class AppWindowPage : Page
{
public AppWindow MyAppWindow { get; set; }
// ...
}
MainPage.xaml.cs
In MainPage
, ottieni un riferimento all'istanza della pagina e assegna l'AppWindow appena creata alla proprietà 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;
// ...
}
Rilevamento delle finestre dell'app con UIContext
Potresti anche voler avere accesso alle istanze di AppWindow da altre parti dell'app. Ad esempio, MainPage
potrebbe avere un pulsante "Chiudi tutto" che chiude tutte le istanze rilevate di AppWindow.
In questo caso, è consigliabile usare il UIContext identificatore univoco per tenere traccia delle istanze della finestra in un Dictionary.
MainPage.xaml.cs
In MainPage
, creare il dizionario come proprietà statica. Aggiungere quindi la pagina al dizionario quando viene creata e rimuoverla quando la pagina viene chiusa. È possibile ottenere il UIContext dal Frame di contenuto (appWindowContentFrame.UIContext
) dopo aver chiamato 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
Per usare l'istanza di 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;
}
// ...
}
Annotazioni
L'esempio HelloAppWindow
mostra entrambi i modi per tenere traccia della finestra in AppWindowPage
, ma in genere si userà una o l'altra, non entrambe.
Dimensioni e posizionamento della finestra della richiesta
La classe AppWindow include diversi metodi che è possibile usare per controllare le dimensioni e il posizionamento della finestra. Come implicito nei nomi dei metodi, il sistema può o meno rispettare le modifiche richieste a seconda dei fattori ambientali.
Chiamare RequestSize per specificare le dimensioni della finestra desiderate, come illustrato di seguito.
colorPickerAppWindow.RequestSize(new Size(300, 428));
I metodi per gestire il posizionamento delle finestre sono denominati RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.
In questo esempio, questo codice sposta la finestra accanto alla vista principale da cui viene generata.
colorPickerAppWindow.RequestMoveAdjacentToCurrentView();
Per ottenere informazioni sulle dimensioni correnti e sul posizionamento della finestra, chiamare GetPlacement. Un oggetto AppWindowPlacement viene restituito che fornisce la DisplayRegion corrente, l'Offsete la Size della finestra.
Ad esempio, è possibile chiamare questo codice per spostare la finestra nell'angolo superiore destro dello schermo. Questo codice deve essere chiamato dopo la visualizzazione della finestra; in caso contrario, la dimensione della finestra restituita dalla chiamata a GetPlacement sarà 0,0 e l'offset non sarà corretto.
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));
Richiedere una configurazione di presentazione
La classe AppWindowPresenter consente di visualizzare un'appWindow usando una configurazione predefinita appropriata per il dispositivo in cui è visualizzata. È possibile usare un valore AppWindowPresentationConfiguration per posizionare la finestra in FullScreen
modalità o CompactOverlay
.
In questo esempio viene illustrato come eseguire le operazioni seguenti:
- Usa l'evento AppWindow.Changed per ricevere una notifica se le presentazioni della finestra disponibili cambiano.
- Usare la proprietà AppWindow.Presenter per ottenere il corrente AppWindowPresenter.
- Chiamare IsPresentationSupported per verificare se è supportato un specifico AppWindowPresentationKind.
- Chiamare GetConfiguration per verificare il tipo di configurazione attualmente usato.
- Chiamare RequestPresentation per modificare la configurazione corrente.
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);
}
}
Riutilizzare gli elementi XAML
AppWindow consente di avere più alberi XAML con lo stesso thread dell'interfaccia utente. Tuttavia, un elemento XAML può essere aggiunto solo una volta a un albero XAML. Se vuoi spostare una parte dell'interfaccia utente da una finestra a un'altra, devi gestirla nell'albero XAML.
In questo esempio viene illustrato come riutilizzare un controllo ColorPicker durante lo spostamento tra la finestra principale e una finestra secondaria.
Il selettore dei colori è dichiarato in XAML per MainPage
, che lo colloca nell'albero XAML di MainPage
.
<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>
Quando il selettore di colore viene scollegato per essere inserito in una nuova AppWindow, devi prima rimuoverlo dall'albero XAML MainPage
rimuovendolo dal contenitore genitore. Anche se non è richiesto, questo esempio nasconde il contenitore padre.
colorPickerContainer.Children.Remove(colorPicker);
colorPickerContainer.Visibility = Visibility.Collapsed;
È quindi possibile aggiungerlo alla nuova struttura ad albero XAML. In questo caso, si crea prima di tutto una Grid che sarà il contenitore padre per il ColorPicker, e si aggiunge il ColorPicker come elemento figlio della Grid. In questo modo è possibile rimuovere facilmente ColorPicker dall'albero XAML in un secondo momento. Impostare quindi Grid come radice dell'albero XAML nella nuova finestra.
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);
Quando l'AppWindow viene chiusa, si può invertire il processo. Per prima cosa, rimuovi il ColorPicker dalla Grid, quindi aggiungilo come elemento figlio del 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();
}
Mostra una finestra di dialogo
Per impostazione predefinita, le finestre di dialogo del contenuto vengono visualizzate modalmente rispetto alla radice ApplicationView. Quando usi un ContentDialog all'interno di un AppWindow, devi settare manualmente XamlRoot nella finestra di dialogo sulla radice dell'host XAML.
Per farlo, imposta la proprietà XamlRoot di ContentDialog sullo stesso XamlRoot di un elemento già presente in un'AppWindow. In questo caso, questo codice si trova all'interno dell'
if (ApiInformation.IsApiContractPresent("Windows.Foundation.UniversalApiContract", 8))
{
simpleDialog.XamlRoot = ((Button)sender).XamlRoot;
}
Se si dispone di una o più finestre app aperte oltre alla finestra principale (ApplicationView), ogni finestra può tentare di aprire una finestra di dialogo, perché la finestra di dialogo modale bloccherà solo la finestra in cui è radicata. Tuttavia, può esistere un solo ContentDialog aperto per ogni thread alla volta. Provare ad aprire due ContentDialogs genererà un'eccezione, anche se si sta tentando di aprirli in una finestra App separata.
Per gestire questa situazione, è necessario aprire al minimo la finestra di dialogo in un blocco try/catch
per intercettare l'eccezione se un'altra finestra di dialogo è già aperta.
try
{
ContentDialogResult result = await simpleDialog.ShowAsync();
}
catch (Exception)
{
// The dialog didn't open, probably because another dialog is already open.
}
Un altro modo per gestire i dialoghi consiste nel tenere traccia della finestra di dialogo attualmente aperta e chiuderla prima di tentare di aprire una nuova finestra di dialogo. In questo caso si crea una proprietà statica in MainPage
chiamata CurrentDialog
a questo scopo.
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;
// ...
}
Verificare quindi se è presente una finestra di dialogo attualmente aperta e, in caso affermativo, chiamare il metodo Hide per chiuderlo. Assegnare infine il nuovo dialogo a CurrentDialog
e provare a visualizzarlo.
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.
}
}
Se non è consigliabile avere una finestra di dialogo chiusa a livello di codice, non assegnarla come CurrentDialog
. Qui, MainPage
mostra una finestra di dialogo importante che dovrebbe essere chiusa solo quando l'utente fa clic su Ok
. Poiché non è assegnato come CurrentDialog
, non viene effettuato alcun tentativo di chiuderlo a livello di codice.
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.
}
}
// ...
}
Codice completo
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));
}
}
}