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.

Nota

AppWindow saat ini sedang 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:

  • Pisahkan kontrol dari halaman utama dan buka di jendela baru.
  • Buka salinan baru Halaman di jendela baru.
  • Atur ukuran dan posisikan jendela baru secara terprogram di aplikasi.
  • Kaitkan ContentDialog dengan jendela yang sesuai di aplikasi.

Contoh aplikasi dengan satu jendela

Contoh aplikasi dengan satu jendela

Aplikasi contoh dengan pemilih warna yang terpisah dan jendela sekunder

Aplikasi sampel dengan pemilih warna yang mengambang dan jendela sekunder

API Penting: namespace Windows.UI.WindowManagement, 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.

Jendela Aplikasi

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) dari mana mereka diciptakan, yang menyederhanakan pengembangan aplikasi multi-jendela.

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

Lingkungan Jendela

WindowingEnvironment API memberi tahu Anda tentang lingkungan tempat aplikasi Anda disajikan sehingga Anda dapat menyesuaikan aplikasi sesuai kebutuhan. Ini menjelaskan jenis jendela yang didukung 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.

Wilayah Tampilan

API DisplayRegion menjelaskan wilayah tempat tampilan dapat ditampilkan kepada pengguna pada tampilan logis; misalnya, pada PC desktop, ini adalah tampilan lengkap dikurangi area taskbar. Ini tidak selalu merupakan pemetaan 1:1 dengan area tampilan fisik monitor latar. 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.

Konteks Antarmuka Pengguna

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

UIContext penting karena API seperti Window.Current dan pola GetForCurrentView bergantung pada memiliki satu ApplicationView/CoreWindow dengan satu pohon XAML per utas untuk berfungsi. 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 yang baru

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

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

    Dengan memanggil metode ini, akan dibuat 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 melepaskan sumber daya XAML (konten AppWindow) dan referensi ke AppWindow.

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

Petunjuk / Saran

Anda harus menjaga jumlah kode pada penanganan aktivitas Closed Anda sekecil mungkin untuk menghindari masalah yang tak 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 HelloAppWindow menunjukkan beberapa cara berbeda yang biasanya Anda gunakan pada 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 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 agar dapat 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 AppWindowPage dan menetapkan instans AppWindow 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 instance jendela dalam sebuah 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 Anda, gunakan UIContext halaman untuk mengambilnya dari Kamus statis di . Anda harus melakukan ini dalam penanganan acara Loaded di halaman daripada dalam konstruktor agar UIContext tidak bernilai 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;
    }
    // ...
}

Nota

Contoh HelloAppWindow menunjukkan dua cara untuk melacak jendela di AppWindowPage, tetapi Anda biasanya akan memilih salah satu dari keduanya, bukan menggunakan keduanya sekaligus.

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 samping antarmuka utama tempat jendela dipindahkan.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

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

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

Kelas AppWindowPresenter memungkinkan Anda menampilkan AppWindow menggunakan konfigurasi yang telah ditentukan sebelumnya yang sesuai untuk perangkat tempat aplikasi ini 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 memposisikannya dalam pohon XAML MainPage.

<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 pohon XAML MainPage 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 wadah induk untuk ColorPicker, dan menambahkan ColorPicker sebagai sub-komponen 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 prosesnya. 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 bawaan, dialog konten ditampilkan secara modal relatif terhadap root ApplicationView. Saat Anda menggunakan ContentDialog di dalam AppWindow, Anda perlu mengatur XamlRoot secara manual pada dialog ke akar host XAML.

Untuk melakukannya, atur properti XamlRoot ContentDialog ke yang sama XamlRoot sebagai elemen yang sudah ada di AppWindow. Di sini, kode ini berada di dalam handler 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 untuk membuka dialog, karena dialog modal hanya akan memblokir jendela tempat dialog tersebut berakar. Namun, hanya ada satu ContentDialog terbuka per utas pada satu waktu. Mencoba membuka dua DialogKonten akan melemparkan pengecualian, meskipun mencoba membukanya di AppWindows yang 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 dalam MainPage yang disebut 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 menunjukkan dialog penting yang seharusnya hanya ditutup saat pengguna 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));
        }
    }
}