Bagikan melalui


Tampilkan beberapa tampilan dengan AppWindow

AppWindow dan API terkait menyederhanakan pembuatan aplikasi multi-jendela dengan memungkinkan Anda menampilkan konten aplikasi di jendela sekunder sambil masih mengerjakan utas UI yang sama di setiap jendela.

Catatan

AppWindow saat ini dalam pratinjau. Ini berarti Anda dapat mengirimkan aplikasi yang menggunakan AppWindow ke Store, tetapi beberapa platform dan komponen kerangka kerja diketahui tidak berfungsi dengan AppWindow (lihat Batasan).

Di sini, kami menunjukkan beberapa skenario untuk beberapa jendela dengan aplikasi sampel yang disebut HelloAppWindow. Aplikasi sampel menunjukkan fungsionalitas berikut:

  • Lepaskan-dok kontrol dari halaman utama dan buka di jendela baru.
  • Buka instans baru Halaman di jendela baru.
  • Ukuran terprogram dan posisikan jendela baru di aplikasi.
  • Kaitkan ContentDialog dengan jendela yang sesuai di aplikasi.

Contoh aplikasi dengan satu jendela

Contoh aplikasi dengan satu jendela

Contoh aplikasi dengan pemilih warna yang tidak ditampar dan jendela sekunder

Contoh aplikasi dengan pemilih warna yang tidak ditampar dan jendela sekunder

API Penting: Windows.UI.WindowManagement namespace, kelas AppWindow

Ringkasan API

Kelas AppWindow dan API lainnya di namespace WindowManagement tersedia mulai dari Windows 10, versi 1903 (SDK 18362). Jika aplikasi Anda menargetkan versi Windows 10 yang lebih lama, Anda harus menggunakan ApplicationView untuk membuat jendela sekunder. WINDOWManagement API masih dalam pengembangan dan memiliki batasan seperti yang dijelaskan dalam dokumen referensi API.

Berikut adalah beberapa API penting yang Anda gunakan untuk menampilkan konten di AppWindow.

AppWindow

Kelas AppWindow dapat digunakan untuk menampilkan sebagian aplikasi UWP di jendela sekunder. Ini mirip dalam konsep dengan ApplicationView, tetapi tidak sama dalam perilaku dan masa pakai. Fitur utama AppWindow adalah bahwa setiap instans berbagi utas pemrosesan UI yang sama (termasuk dispatcher peristiwa) tempat instans dibuat, yang menyederhanakan aplikasi multi-jendela.

Anda hanya dapat menghubungkan konten XAML ke AppWindow Anda, tidak ada dukungan untuk konten DirectX atau Holografik asli. Namun, Anda dapat menampilkan XAML SwapChainPanel yang menghosting konten DirectX.

WindowingEnvironment

WindowingEnvironment API memberi tahu Anda tentang lingkungan tempat aplikasi Anda disajikan sehingga Anda dapat menyesuaikan aplikasi sesuai kebutuhan. Ini menjelaskan jenis jendela dukungan lingkungan; misalnya, Overlapped jika aplikasi berjalan di PC, atau Tiled jika aplikasi berjalan di Xbox. Ini juga menyediakan sekumpulan objek DisplayRegion yang menjelaskan area di mana aplikasi dapat ditampilkan pada tampilan logis.

DisplayRegion

API DisplayRegion menjelaskan wilayah di mana tampilan dapat ditampilkan kepada pengguna pada tampilan logis; misalnya, pada PC desktop, ini adalah tampilan lengkap dikurangi area taskbar. Ini belum tentu pemetaan 1:1 dengan area tampilan fisik monitor backing. Mungkin ada beberapa wilayah tampilan dalam monitor yang sama, atau DisplayRegion dapat dikonfigurasi untuk menjangkau beberapa monitor jika monitor tersebut homogen di semua aspek.

AppWindowPresenter

API AppWindowPresenter memungkinkan Anda dengan mudah mengalihkan jendela ke konfigurasi yang telah ditentukan sebelumnya seperti FullScreen atau CompactOverlay. Konfigurasi ini memberi pengguna pengalaman yang konsisten di semua perangkat yang mendukung konfigurasi.

UIContext

UIContext adalah pengidentifikasi unik untuk jendela atau tampilan aplikasi. Ini dibuat secara otomatis, dan Anda dapat menggunakan properti UIElement.UIContext untuk mengambil UIContext. Setiap UIElement di pohon XAML memiliki UIContext yang sama.

UIContext penting karena API seperti Window.Current dan GetForCurrentView pola mengandalkan memiliki satu ApplicationView/CoreWindow dengan satu pohon XAML per utas untuk dikerjakan. Ini tidak terjadi saat Anda menggunakan AppWindow, jadi Anda menggunakan UIContext untuk mengidentifikasi jendela tertentu sebagai gantinya.

XamlRoot

Kelas XamlRoot memegang pohon elemen XAML, menghubungkannya ke objek host jendela (misalnya, AppWindow atau ApplicationView), dan menyediakan info seperti ukuran dan visibilitas. Anda tidak membuat objek XamlRoot secara langsung. Sebagai gantinya, satu dibuat saat Anda melampirkan elemen XAML ke AppWindow. Anda kemudian dapat menggunakan properti UIElement.XamlRoot untuk mengambil XamlRoot.

Untuk informasi selengkapnya tentang UIContext dan XamlRoot, lihat Membuat kode portabel di seluruh host windowing.

Perlihatkan jendela baru

Mari kita lihat langkah-langkah untuk menampilkan konten di AppWindow baru.

Untuk menampilkan jendela baru

  1. Panggil metode AppWindow.TryCreateAsync statis untuk membuat AppWindow baru.

    AppWindow appWindow = await AppWindow.TryCreateAsync();
    
  2. Buat konten jendela.

    Biasanya, Anda membuat Bingkai XAML, lalu menavigasi Bingkai ke Halaman XAML tempat Anda menentukan konten aplikasi. Untuk informasi selengkapnya tentang bingkai dan halaman, lihat Navigasi peer-to-peer antara dua halaman.

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

    Namun, Anda dapat menampilkan konten XAML apa pun di AppWindow, bukan hanya Bingkai dan Halaman. Misalnya, Anda hanya dapat menampilkan satu kontrol, seperti ColorPicker, atau Anda dapat menampilkan SwapChainPanel yang menghosting konten DirectX.

  3. Panggil metode ElementCompositionPreview.SetAppWindowContent untuk melampirkan konten XAML ke AppWindow.

    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
    

    Panggilan ke metode ini membuat objek XamlRoot dan mengaturnya sebagai properti XamlRoot untuk UIElement yang ditentukan.

    Anda hanya dapat memanggil metode ini sekali per instans AppWindow. Setelah konten diatur, panggilan lebih lanjut ke SetAppWindowContent untuk instans AppWindow ini akan gagal. Selain itu, jika Anda mencoba memutuskan sambungan konten AppWindow dengan meneruskan objek UIElement null, panggilan akan gagal.

  4. Panggil metode AppWindow.TryShowAsync untuk menampilkan jendela baru.

    await appWindow.TryShowAsync();
    

Melepaskan sumber daya saat jendela ditutup

Anda harus selalu menangani peristiwa AppWindow.Closed untuk merilis sumber daya XAML (konten AppWindow) dan referensi ke AppWindow.

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

Tip

Anda harus menyimpan jumlah kode dalam penanganan aktivitas Anda Closed hingga jumlah minimum yang mungkin untuk menghindari masalah yang tidak terduga.

Melacak instans AppWindow

Bergantung pada cara Anda menggunakan beberapa jendela di aplikasi, Anda mungkin atau mungkin tidak perlu melacak instans AppWindow yang Anda buat. Contoh menunjukkan HelloAppWindow beberapa cara berbeda yang biasanya Anda gunakan appWindow. Di sini, kita akan melihat mengapa jendela ini harus dilacak, dan cara melakukannya.

Pelacakan sederhana

Jendela pemilih warna menghosting satu kontrol XAML, dan kode untuk berinteraksi dengan pemilih warna semuanya berada dalam MainPage.xaml.cs file. Jendela pemilih warna hanya memungkinkan satu instans dan pada dasarnya merupakan ekstensi dari MainWindow. Untuk memastikan bahwa hanya satu instans yang dibuat, jendela pemilih warna dilacak dengan variabel tingkat halaman. Sebelum membuat jendela pemilih warna baru, Anda memeriksa apakah instans ada, dan jika ada, lewati langkah-langkah untuk membuat jendela baru dan cukup panggil TryShowAsync di jendela yang ada.

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

Melacak instans AppWindow dalam konten yang dihosting

Jendela AppWindowPage menghosting halaman XAML lengkap, dan kode untuk berinteraksi dengan halaman berada di AppWindowPage.xaml.cs. Ini memungkinkan beberapa instans, yang masing-masing berfungsi secara independen.

Fungsionalitas halaman memungkinkan Anda memanipulasi jendela, mengaturnya ke FullScreen atau CompactOverlay, dan juga mendengarkan peristiwa AppWindow.Changed untuk menampilkan informasi tentang jendela. Untuk memanggil API ini, AppWindowPage perlu referensi ke instans AppWindow yang menghostingnya.

Jika itu saja yang Anda butuhkan, Anda dapat membuat properti di dan menetapkan instans AppWindow ke dalamnya AppWindowPage saat Anda membuatnya.

AppWindowPage.xaml.cs

Di AppWindowPage, buat properti untuk menyimpan referensi AppWindow.

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

    // ...
}

MainPage.xaml.cs

Di MainPage, dapatkan referensi ke instans halaman dan tetapkan AppWindow yang baru dibuat ke properti di 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;

    // ...
}

Melacak jendela aplikasi menggunakan UIContext

Anda mungkin juga ingin memiliki akses ke instans AppWindow dari bagian lain aplikasi Anda. Misalnya, MainPage dapat memiliki tombol 'tutup semua' yang menutup semua instans AppWindow yang dilacak.

Dalam hal ini, Anda harus menggunakan pengidentifikasi unik UIContext untuk melacak instans jendela dalam Kamus.

MainPage.xaml.cs

Di MainPage, buat Kamus sebagai properti statis. Kemudian, tambahkan halaman ke Kamus saat Anda membuatnya, dan hapus saat halaman ditutup. Anda bisa mendapatkan UIContext dari Bingkai konten (appWindowContentFrame.UIContext) setelah Anda memanggil 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

Untuk menggunakan instans AppWindow dalam kode AndaAppWindowPage, gunakan UIContext halaman untuk mengambilnya dari Kamus statis di MainPage. Anda harus melakukan ini di penanganan aktivitas Yang dimuat halaman daripada di konstruktor sehingga UIContext tidak null. Anda bisa mendapatkan UIContext dari Halaman: 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;
    }
    // ...
}

Catatan

Contoh menunjukkan HelloAppWindow kedua cara untuk melacak jendela di AppWindowPage, tetapi Anda biasanya akan menggunakan satu atau yang lain, bukan keduanya.

Meminta ukuran dan penempatan jendela

Kelas AppWindow memiliki beberapa metode yang dapat Anda gunakan untuk mengontrol ukuran dan penempatan jendela. Seperti yang disiratkan oleh nama metode, sistem mungkin atau mungkin tidak menghormati perubahan yang diminta tergantung pada faktor lingkungan.

Panggil RequestSize untuk menentukan ukuran jendela yang diinginkan, seperti ini.

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

Metode untuk mengelola penempatan jendela diberi nama RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion.

Dalam contoh ini, kode ini memindahkan jendela ke di samping tampilan utama tempat jendela ditelurkan.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

Untuk mendapatkan informasi tentang ukuran dan penempatan jendela saat ini, panggil GetPlacement. Ini mengembalikan objek AppWindowPlacement yang menyediakan DisplayRegion, Offset, dan Ukuran jendela saat ini.

Misalnya, Anda dapat memanggil kode ini untuk memindahkan jendela ke sudut kanan atas tampilan. Kode ini harus dipanggil setelah jendela ditampilkan; jika tidak, ukuran jendela yang dikembalikan oleh panggilan ke GetPlacement akan menjadi 0,0 dan offset akan salah.

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

Meminta konfigurasi presentasi

Kelas AppWindowPresenter memungkinkan Anda menampilkan AppWindow menggunakan konfigurasi yang telah ditentukan sebelumnya yang sesuai untuk perangkat tempatnya ditampilkan. Anda dapat menggunakan nilai AppWindowPresentationConfiguration untuk menempatkan jendela dalam FullScreen mode atau CompactOverlay .

Contoh ini menunjukkan cara melakukan hal berikut:

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

Menggunakan kembali elemen XAML

AppWindow memungkinkan Anda memiliki beberapa pohon XAML dengan utas UI yang sama. Namun, elemen XAML hanya dapat ditambahkan ke pohon XAML sekali. Jika Anda ingin memindahkan bagian UI Anda dari satu jendela ke jendela lain, Anda harus mengelola penempatannya di pohon XAML.

Contoh ini menunjukkan cara menggunakan kembali kontrol ColorPicker saat memindahkannya antara jendela utama dan jendela sekunder.

Pemilih warna dideklarasikan dalam XAML untuk MainPage, yang menempatkannya di MainPage pohon XAML.

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

Ketika pemilih warna dilepas untuk ditempatkan di AppWindow baru, Anda harus terlebih dahulu menghapusnya dari MainPage pohon XAML dengan menghapusnya dari kontainer induknya. Meskipun tidak diperlukan, contoh ini juga menyembunyikan kontainer induk.

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

Kemudian Anda dapat menambahkannya ke pohon XAML baru. Di sini, Anda terlebih dahulu membuat Grid yang akan menjadi kontainer induk untuk ColorPicker, dan menambahkan ColorPicker sebagai anak dari Grid. (Ini memungkinkan Anda dengan mudah menghapus ColorPicker dari pohon XAML ini nanti.) Anda kemudian mengatur Grid sebagai akar pohon XAML di jendela baru.

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

Saat AppWindow ditutup, Anda membalikkan proses. Pertama, hapus ColorPicker dari Grid, lalu tambahkan sebagai anak dari StackPanel di 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();
}

Perlihatkan kotak dialog

Secara default, dialog konten ditampilkan secara modal relatif terhadap ApplicationView akar. Saat Anda menggunakan ContentDialog di dalam AppWindow, Anda perlu mengatur XamlRoot secara manual pada dialog ke akar host XAML.

Untuk melakukannya, atur properti ContentDialog XamlRoot ke XamlRoot yang sama dengan elemen yang sudah ada di AppWindow. Di sini, kode ini berada di dalam penanganan aktivitas Klik tombol, sehingga Anda dapat menggunakan pengirim (Tombol yang diklik) untuk mendapatkan XamlRoot.

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

Jika Anda membuka satu atau beberapa AppWindows selain jendela utama (ApplicationView), setiap jendela dapat mencoba membuka dialog, karena dialog modal hanya akan memblokir jendela tempat jendela di-root. Namun, hanya ada satu ContentDialog yang terbuka per utas pada satu waktu. Mencoba membuka dua ContentDialogs akan melemparkan pengecualian, bahkan jika mereka mencoba membuka di AppWindows terpisah.

Untuk mengelola ini, Anda setidaknya harus membuka dialog dalam try/catch blok untuk menangkap pengecualian jika dialog lain sudah terbuka.

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

Cara lain untuk mengelola dialog adalah dengan melacak dialog yang saat ini terbuka, dan menutupnya sebelum mencoba membuka dialog baru. Di sini, Anda membuat properti statis di yang dipanggil MainPage CurrentDialog untuk tujuan ini.

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;

   // ...
}

Kemudian, Anda memeriksa apakah ada dialog yang saat ini dibuka, dan jika ada, panggil metode Sembunyikan untuk menutupnya. Terakhir, tetapkan dialog baru ke CurrentDialog, dan coba tampilkan.

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

Jika tidak diinginkan untuk menutup dialog secara terprogram, jangan tetapkan sebagai CurrentDialog. Di sini, MainPage memperlihatkan dialog penting yang seharusnya hanya diberhentikan saat penggunaan mengklik Ok. Karena tidak ditetapkan sebagai CurrentDialog, tidak ada upaya yang dilakukan untuk menutupnya secara terprogram.

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

Kode lengkap

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