Aracılığıyla paylaş


AppWindow ile birden çok görünüm gösterme

AppWindow ve ilgili API'leri, her pencerede aynı kullanıcı arabirimi iş parçacığı üzerinde çalışırken uygulama içeriğinizi ikincil pencerelerde göstermenizi sağlayarak çok pencereli uygulamaların oluşturulmasını basitleştirir.

Uyarı

AppWindow şu anda önizleme aşamasındadır. Bu, AppWindow kullanan uygulamaları Mağaza'ya gönderebileceğiniz, ancak bazı platform ve çerçeve bileşenlerinin AppWindow ile çalışmadığı bilinmektedir (bkz . Sınırlamalar).

Burada, adlı HelloAppWindowörnek bir uygulamayla birden çok pencere için bazı senaryolar göstereceğiz. Örnek uygulama aşağıdaki işlevleri gösterir:

  • Ana sayfadan bir kontrol öğesini ayırın ve yeni bir pencerede açın.
  • Sayfanın yeni örneklerini yeni pencerelerde açın.
  • Uygulamadaki yeni pencereleri program aracılığıyla boyutlandırın ve konumlandırın.
  • Bir ContentDialog'unu uygulamadaki uygun pencereyle ilişkilendirin.

Tek bir pencere örnek uygulama

Tek pencere ile örnek uygulama

Yerleşik olmayan renk seçicisi ve ikincil pencere ile örnek uygulama

Sabitlenmemiş renk seçici ve ikincil pencere ile örnek uygulama

Önemli API'ler: Windows.UI.WindowManagement ad alanı, AppWindow sınıfı

API’ye genel bakış

Windows 10, sürüm 1903 'den (SDK 18362) başlayarak, WindowManagement ad alanında AppWindow sınıfı ve diğer API'ler kullanılabilir. Uygulamanız Windows 10'un önceki sürümlerini hedeflediyse , ikincil pencereler oluşturmak için ApplicationView kullanmanız gerekir. WindowManagement API'leri hala geliştirme aşamasındadır ve API başvuru belgelerinde açıklandığı gibi sınırlamalara sahiptir.

AppWindow'da içerik göstermek için kullandığınız önemli API'lerden bazıları aşağıdadır.

Uygulama Penceresi

AppWindow sınıfı, UWP uygulamasının bir bölümünü ikincil pencerede görüntülemek için kullanılabilir. Kavram olarak ApplicationView'a benzer, ancak davranış ve yaşam süresinde aynı değildir. AppWindow'un temel özelliklerinden biri, her örneğin oluşturuldukları kullanıcı arabirimi işleme iş parçacığını (olay dağıtıcısı dahil) paylaşması ve bu da çok pencereli uygulamaları basitleştirmesidir.

XAML içeriğini yalnızca AppWindow'unuza bağlayabilirsiniz; yerel DirectX veya Holographic içeriği desteklenmez. Ancak, DirectX içeriğini barındıran bir XAML SwapChainPanel gösterebilirsiniz.

Pencereleme Ortamı

WindowingEnvironment API'sinde uygulamanızın sunulduğu ortam hakkında bilgi edinebilir, böylece uygulamanızı gerektiği gibi uyarlayabilirsiniz. Ortamın desteklediği pencere türünü açıklar; örneğin, Overlapped uygulama bir bilgisayarda çalışıyorsa veya Tiled uygulama bir Xbox'ta çalışıyorsa. Ayrıca, bir uygulamanın mantıksal ekranda gösterilebileceği alanları açıklayan bir DisplayRegion nesneleri kümesi de sağlar.

Görüntüleme Bölgesi

DisplayRegion API'sinde, bir görünümün kullanıcıya mantıksal ekranda gösterilebileceği bölge açıklanır; örneğin, bir masaüstü bilgisayarda bu, görev çubuğunun alanı eksi tam ekrandır. Destekleyen monitörün fiziksel görüntüleme alanı ile birebir eşleşmesi gerekmez. Aynı monitörde birden çok görüntüleme bölgesi olabilir veya bu monitörler tüm yönleriyle homojense DisplayRegion birden çok monitöre yayılacak şekilde yapılandırılabilir.

AppWindowPresenter

AppWindowPresenter API'si, pencereleri veya FullScreengibi CompactOverlay önceden tanımlanmış yapılandırmalara kolayca geçiş yapmanıza olanak tanır. Bu yapılandırmalar, kullanıcıya yapılandırmayı destekleyen tüm cihazlarda tutarlı bir deneyim sağlar.

UIContext

UIContext , uygulama penceresi veya görünümü için benzersiz bir tanımlayıcıdır. Otomatik olarak oluşturulur ve UIElement.UIContext özelliğini kullanarak UIContext'i alabilirsiniz. XAML ağacındaki her UIElement aynı UIContext'e sahiptir.

Window.Current ve GetForCurrentView desen gibi API'ler üzerinde çalışmak için iş parçacığı başına tek bir XAML ağacına sahip tek bir ApplicationView/CoreWindow'a sahip olmak gerektiğinden UIContext önemlidir. AppWindow kullanırken bu durum geçerli değildir, bu nedenle bunun yerine belirli bir pencereyi tanımlamak için UIContext kullanırsınız.

XamlRoot

XamlRoot sınıfı bir XAML öğesi ağacı tutar, bunu pencere konak nesnesine (örneğin AppWindow veya ApplicationView) bağlar ve boyut ve görünürlük gibi bilgiler sağlar. Doğrudan bir XamlRoot nesnesi oluşturmazsınız. Bunun yerine, bir AppWindow'a XAML öğesi eklediğinizde bir öğe oluşturulur. Daha sonra XamlRoot'ı almak için UIElement.XamlRoot özelliğini kullanabilirsiniz.

UIContext ve XamlRoot hakkında daha fazla bilgi için bkz. Kodun pencere barındırıcıları arasında taşınabilir olmasını sağlama.

Yeni bir pencere göster

Şimdi yeni bir AppWindow'da içerik gösterme adımlarına göz atalım.

Yeni bir pencere göstermek için

  1. Yeni bir AppWindow oluşturmak için statik AppWindow.TryCreateAsync yöntemini çağırın.

    AppWindow appWindow = await AppWindow.TryCreateAsync();
    
  2. Pencere içeriğini oluşturun.

    Genellikle bir XAML Frameoluşturur, ardından uygulama içeriğinizi tanımladığınız bir XAML Sayfası'ya Frame'i yönlendirirsiniz. Çerçeveler ve sayfalar hakkında daha fazla bilgi için iki sayfa arasında eşler arası gezinmekısmına bakınız.

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

    Ancak, yalnızca bir Çerçeve ve Sayfa değil, AppWindow'da herhangi bir XAML içeriğini de gösterebilirsiniz. Örneğin, ColorPicker gibi tek bir denetimi gösterebilir veya DirectX içeriğini barındıran bir SwapChainPanel gösterebilirsiniz.

  3. XAML içeriğini AppWindow'a eklemek için ElementCompositionPreview.SetAppWindowContent yöntemini çağırın.

    ElementCompositionPreview.SetAppWindowContent(appWindow, appWindowContentFrame);
    

    Bu yöntem çağrısı bir XamlRoot nesnesi oluşturur ve bunu belirtilen UIElement için XamlRoot özelliği olarak ayarlar.

    Bu yöntemi AppWindow örneği başına yalnızca bir kez çağırabilirsiniz. İçerik ayarlandıktan sonra, bu AppWindow örneği için yapılacak SetAppWindowContent çağrıları başarısız olacaktır. Ayrıca, bir null UIElement nesnesi geçirerek AppWindow içeriğinin bağlantısını kesmeye çalışırsanız, çağrı başarısız olur.

  4. Yeni pencereyi göstermek için AppWindow.TryShowAsync yöntemini çağırın.

    await appWindow.TryShowAsync();
    

Bir pencere kapatıldığında kaynakları serbest bırakma

XAML kaynaklarını (AppWindow içeriği) ve AppWindow başvurularını yayınlamak için her zaman AppWindow.Closed olayını işlemeniz gerekir.

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

Tavsiye

Beklenmeyen sorunlardan kaçınmak için olay işleyicinizdeki Closed kod miktarını mümkün olan en düşük miktarda tutmalısınız.

AppWindow örneklerini izleme

Uygulamanızda birden çok pencereyi nasıl kullandığınıza bağlı olarak, oluşturduğunuz AppWindow örneklerini izlemeniz gerekebilir veya gerekmeyebilir. Örnek, genellikle bir HelloAppWindow kullanmanın bazı farklı yollarını gösterir. Burada, bu pencerelerin neden izlenmesi gerektiğini ve nasıl yapılacağını inceleyeceğiz.

Basit izleme

Renk seçici penceresi tek bir XAML denetimini barındırıyor ve renk seçiciyle etkileşime yönelik kodun tümü dosyada MainPage.xaml.cs yer alır. Renk seçici penceresi yalnızca tek bir örneğe izin verir ve temelde uzantısıdır MainWindow. Yalnızca bir örneğin oluşturulduğundan emin olmak için, renk seçici penceresi bir sayfa düzeyi değişkeniyle izlenir. Yeni bir renk seçici penceresi oluşturmadan önce bir örneğin var olup olmadığını denetlersiniz ve varsa yeni bir pencere oluşturma adımlarını atlar ve var olan pencerede TryShowAsync'i çağırmanız gerekir.

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

Barındırıldığı içerikte bir AppWindow örneğini takip etme

Pencere AppWindowPage tam bir XAML sayfasını barındırıyor ve sayfayla etkileşime yönelik kod içinde AppWindowPage.xaml.csyer alır. Her biri bağımsız olarak işlev gösteren birden çok örneğe izin verir.

Sayfanın işlevselliği, pencereyi kontrol etmenize, FullScreen veya CompactOverlayolarak ayarlamanıza olanak tanır ve ayrıca pencere hakkındaki bilgileri göstermek için AppWindow.Changed olaylarını dinler. Bu API'leri çağırmak için, AppWindowPage'nin bağlı olduğu AppWindow örneğine bir referans gerekir.

İhtiyacınız olan tek şey buysa içinde bir özellik AppWindowPage oluşturabilir ve appwindow örneğini oluştururken bu özelliğe atayabilirsiniz.

AppWindowPage.xaml.cs

AppWindowPage'da AppWindow referansını tutmak için bir özellik oluşturun.

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

    // ...
}

MainPage.xaml.cs

MainPage'da, sayfa örneğine referans alın ve yeni oluşturulan AppWindow'ı AppWindowPageiçindeki özelliğe atayın.

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;

    // ...
}

UIContext kullanarak uygulama pencerelerini izleme

Uygulamanızın diğer bölümlerinden AppWindow örneklerine de erişmek isteyebilirsiniz. Örneğin, MainPage, AppWindow'un tüm izlenen örneklerini kapatan bir 'tümünü kapat' düğmesine sahip olabilir.

Bu durumda, pencere örneklerini izlemek için UIContext benzersiz tanımlayıcısını Sözlükiçinde kullanmanız gerekir.

MainPage.xaml.cs

içinde MainPage, Sözlüğü statik bir özellik olarak oluşturun. Ardından, sayfayı oluştururken Sözlüğe ekleyin ve sayfa kapatıldığında kaldırın. ElementCompositionPreview.SetAppWindowContentçağrısını yaptıktan sonra UIContext'i içerikten appWindowContentFrame.UIContext () alabilirsiniz.

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

kodunuzda AppWindowPage örneğini kullanmak için, sayfanın UIContext'ünü kullanarak, onu MainPageiçindeki statik Sözlükten alın. UiContext'in null olmaması için bunu oluşturucu yerine sayfanın Yüklü olay işleyicisinde yapmanız gerekir. UIContext'i Şu Sayfadan alabilirsiniz: 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;
    }
    // ...
}

Uyarı

Örnekte HelloAppWindow , içinde AppWindowPagepencereyi izlemenin her iki yolu da gösterilir, ancak normalde ikisini birden değil birini veya diğerini kullanırsınız.

İstek penceresi boyutu ve yerleşimi

AppWindow sınıfı, pencerenin boyutunu ve yerleşimini denetlemek için kullanabileceğiniz çeşitli yöntemlere sahiptir. Yöntem adlarında da belirtildiği gibi sistem, çevresel faktörlere bağlı olarak istenen değişiklikleri kabul edebilir veya kabul etmeyebilir.

İstenen pencere boyutunu belirtmek için RequestSize çağrısı yapın.

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

Pencere yerleştirmeyi yönetme yöntemleri RequestMove*: RequestMoveAdjacentToCurrentView, RequestMoveAdjacentToWindow, RequestMoveRelativeToDisplayRegion, RequestMoveToDisplayRegion olarak adlandırılır.

Bu örnekte, bu kod pencereyi pencerenin oluşturulacağı ana görünümün yanında olacak şekilde taşır.

colorPickerAppWindow.RequestMoveAdjacentToCurrentView();

Pencerenin geçerli boyutu ve yerleşimi hakkında bilgi almak için GetPlacementçağrısı yapın. Bu, geçerli DisplayRegion, Uzaklıkve pencerenin Boyutu sağlayan bir AppWindowPlacement nesnesi döndürür.

Örneğin, pencereyi ekranın sağ üst köşesine taşımak için bu kodu çağırabilirsiniz. Pencere görüntülendikten sonra bu kodun çağrılmış olması gerekir; aksi takdirde, GetPlacement çağrısı tarafından döndürülen pencere Boyutu 0,0 olur ve uzaklık yanlış olur.

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

Sunu yapılandırması isteme

AppWindowPresenter sınıfı, gösterildiği cihaza uygun önceden tanımlanmış bir yapılandırma kullanarak bir AppWindow göstermenizi sağlar. Pencereyi veya FullScreen moduna yerleştirmek için bir CompactOverlay değeri kullanabilirsiniz.

Bu örnekte aşağıdakilerin nasıl yapılacağını gösterilmektedir:

private void Window_Changed(AppWindow sender, AppWindowChangedEventArgs args)
{
    if (args.DidAvailableWindowPresentationsChange)
    {
        EnablePresentationButtons(sender);
    }

    if (args.DidWindowPresentationChange)
    {
        ConfigText.Text = window.Presenter.GetConfiguration().Kind.ToString();
    }

    if (args.DidSizeChange)
    {
        SizeText.Text = window.GetPlacement().Size.ToString();
    }
}

private void EnablePresentationButtons(AppWindow window)
{
    // Check whether the current AppWindowPresenter supports CompactOverlay.
    if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.CompactOverlay))
    {
        // Show the CompactOverlay button...
        compactOverlayButton.Visibility = Visibility.Visible;
    }
    else
    {
        // Hide the CompactOverlay button...
        compactOverlayButton.Visibility = Visibility.Collapsed;
    }

    // Check whether the current AppWindowPresenter supports FullScreen?
    if (window.Presenter.IsPresentationSupported(AppWindowPresentationKind.FullScreen))
    {
        // Show the FullScreen button...
        fullScreenButton.Visibility = Visibility.Visible;
    }
    else
    {
        // Hide the FullScreen button...
        fullScreenButton.Visibility = Visibility.Collapsed;
    }
}

private void CompactOverlayButton_Click(object sender, RoutedEventArgs e)
{
    if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.CompactOverlay)
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.CompactOverlay);
        fullScreenButton.IsChecked = false;
    }
    else
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
    }
}

private void FullScreenButton_Click(object sender, RoutedEventArgs e)
{
    if (window.Presenter.GetConfiguration().Kind != AppWindowPresentationKind.FullScreen)
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.FullScreen);
        compactOverlayButton.IsChecked = false;
    }
    else
    {
        window.Presenter.RequestPresentation(AppWindowPresentationKind.Default);
    }
}

XAML öğelerini yeniden kullanma

AppWindow , aynı kullanıcı arabirimi iş parçacığına sahip birden çok XAML ağacına sahip olmanıza olanak tanır. Ancak, bir XAML öğesi bir XAML ağacına yalnızca bir kez eklenebilir. Kullanıcı arabiriminizin bir bölümünü bir pencereden diğerine taşımak istiyorsanız, XAML ağacındaki yerleşimini yönetmeniz gerekir.

Bu örnek, bir ColorPicker denetiminin ana pencere ve ikincil bir pencere arasında taşınırken nasıl yeniden kullanılabileceğini göstermektedir.

Renk seçici, MainPageiçin XAML'de tanımlanır ve MainPage XAML ağacına yerleştirilir.

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

Renk seçici yeni bir AppWindow'a yerleştirilecek şekilde ayrıldığında, öncelikle üst kapsayıcısından çıkararak MainPage XAML ağacından kaldırmalısınız. Gerekli olmasa da, bu örnek ebeveyn kapsayıcıyı da gizler.

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

Ardından yeni XAML ağacına ekleyebilirsiniz. Burada, önce ColorPicker için üst kapsayıcı olacak bir Grid oluşturur ve ColorPicker'ı Grid'in alt öğesi olarak eklersiniz. (Bu, ColorPicker'ı daha sonra bu XAML ağacından kolayca kaldırmanızı sağlar.) Ardından, yeni pencerede XAML ağacının kökü olarak Grid'i ayarlarsınız.

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

AppWindow kapatıldığında işlemi tersine çevirirsiniz. İlk olarak ColorPicker öğesini Grid'ten kaldırın, ardından 'da MainPage'e alt öğe olarak ekleyin.

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

İletişim kutusunu gösterme

Varsayılan olarak, içerik diyalogları kök ApplicationView'e göre modsal olarak görüntülenir. AppWindowiçinde bir ContentDialog kullandığınızda, iletişim kutusundaki XamlRoot'u XAML konağı köküne manuel olarak ayarlamanız gerekir.

Bunu yapmak için, ContentDialog'un XamlRoot özelliğini, AppWindow içindeki bir öğenin aynı XamlRoot'üne ayarlayın. Burada, bu kod, bir düğmenin Tıklama olay işleyicisi içindedir. Böylece XamlRoot'ı almak için sender (tıklanan Düğme) kullanabilirsiniz.

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

Ana pencereye (ApplicationView) ek olarak bir veya daha fazla Uygulama Penceresi açıksa, her pencere bir moda iletişim kutusu açmayı deneyebilir, çünkü moda iletişim kutusu yalnızca kök olarak eklendiği pencereyi engelleyebilir. Ancak, bir kerede iş parçacığı başına yalnızca bir ContentDialog açılabilir. İki ContentDialog'un açılmaya çalışılması, hatta bunlar ayrı AppWindows'ta açılmaya çalışılsa bile, bir istisna meydana getirir.

Bunu yönetmek için, başka bir iletişim kutusunun zaten açık olması durumunda özel durumu yakalamak için en azından iletişim kutusunu bir try/catch blokta açmanız gerekir.

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

İletişim kutularını yönetmenin bir diğer yolu da açık olan iletişim kutusunu izlemek ve yeni bir iletişim kutusu açmaya çalışmadan önce kapatmaktır. Burada bu amaçla MainPage içinde CurrentDialog adlı statik bir özellik oluşturursunuz.

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;

   // ...
}

Ardından, açık bir iletişim kutusu olup olmadığını kontrol edip varsa kapatmak için Hide yöntemini çağırın. Son olarak, yeni iletişim kutusunu CurrentDialog'a atayın ve onu göstermeyi deneyin.

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

Program aracılığıyla kapatılması istenmeyen bir iletişim kutusunu CurrentDialog olarak atamayın. Burada MainPage, yalnızca kullanıcı Ok'e tıkladığında kapatılması gereken önemli bir iletişim kutusunu gösterir. CurrentDialog olarak atanmadığı için programatik olarak kapatma girişiminde bulunulmuyor.

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

Kodu tamamlama

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