single.php

C# WinUI3 で別画面をモードレス表示させる手順

C# WinUI 3アプリを作っていく途中で、調べたことを忘録的に投稿します。今回はWinUI3プロジェクトで、別のXamlで用意した画面をモードレス表示する場合の手順です。

MainWindowに別画面をモードレス表示

WinUI3プロジェクトを作成した際に、自動で作成される[MainWindow.xaml]で構成される画面に、こんな感じで別画面をモードレス表示する機能を実装してみます。

モードレス表示は、別画面が表示されている間でもメイン画面の操作が可能な表示方法です。

今回は[WinUI 3 Gallery]の[Multiple windows]サンプルで利用されている[WindowHelper.cs]クラスを利用してウィンドウ表示をしています。

WinUI 3 Gallery]は、WinUI3の各コントロールの動作を確認できるので、よく使っています。

https://github.com/microsoft/WinUI-Gallery/blob/main/WinUIGallery/Helpers/WindowHelper.cs

//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using Microsoft.UI;
using Microsoft.UI.Windowing;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Media;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Windows.Storage;
using WinRT.Interop;

namespace WinUIGallery.Helpers;

// Helper class to allow the app to find the Window that contains an
// arbitrary UIElement (GetWindowForElement).  To do this, we keep track
// of all active Windows.  The app code must call WindowHelper.CreateWindow
// rather than "new Window" so we can keep track of all the relevant
// windows.  In the future, we would like to support this in platform APIs.
public class WindowHelper
{
  static public Window CreateWindow()
  {
    Window newWindow = new Window
    {
      SystemBackdrop = new MicaBackdrop()
    };
    TrackWindow(newWindow);
    return newWindow;
  }

  static public void TrackWindow(Window window)
  {
    window.Closed += (sender,args) => {
        _activeWindows.Remove(window);
    };
    _activeWindows.Add(window);
  }

  static public AppWindow GetAppWindow(Window window)
  {
    IntPtr hWnd = WindowNative.GetWindowHandle(window);
    WindowId wndId = Win32Interop.GetWindowIdFromWindow(hWnd);
    return AppWindow.GetFromWindowId(wndId);
  }

  static public Window GetWindowForElement(UIElement element)
  {
    if (element.XamlRoot != null)
    {
      foreach (Window window in _activeWindows)
      {
        if (element.XamlRoot == window.Content.XamlRoot)
        {
          return window;
        }
      }
    }
    return null;
  }
  // get dpi for an element
  static public double GetRasterizationScaleForElement(UIElement element)
  {
    if (element.XamlRoot != null)
    {
      foreach (Window window in _activeWindows)
      {
        if (element.XamlRoot == window.Content.XamlRoot)
        {
          return element.XamlRoot.RasterizationScale;
        }
      }
    }
    return 0.0;
  }

  static public List<Window> ActiveWindows { get { return _activeWindows; }}

  static private List<Window> _activeWindows = new List<Window>();

  static public StorageFolder GetAppLocalFolder()
  {
    StorageFolder localFolder;
    if (!NativeHelper.IsAppPackaged)
    {
      localFolder = Task.Run(async () => await StorageFolder.GetFolderFromPathAsync(System.AppContext.BaseDirectory)).Result;
    }
    else
    {
      localFolder = ApplicationData.Current.LocalFolder;
    }
    return localFolder;
  }
}

別画面を追加

準備として、表示する別画面をプロジェクトに追加します。

1.[ソリューション エクスプローラー]でプロジェクトのアイコンを右クリックして表示されたポップアップメニューで[追加|新しい項目]を選択します。

2. 表示された[新しい項目の追加]画面で[空白のページ(WinUI3)]を選択して名前を付けて[追加]をクリックします。

3. プロジェクトに新しく[.xaml]と[.xaml.cs]が追加されます。

追加された[.xaml]に画面にコントロールを配置します。

<Page
    x:Class="WindowingApp.PopupPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WindowingApp"
    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 VerticalAlignment="Center" HorizontalAlignment="Center">
        <TextBlock Text="PopupPage.xaml" FontSize="14"/>
    </Grid>
</Page>

新しい画面を[PopupPage]クラスとして表示するコードを[MainWindow]に追加します。

private void showWindow_Click(object sender, RoutedEventArgs e)
{
  var newWindow = WindowHelper.CreateWindow();
  var popupPage = new PopupPage();
  newWindow.Content = popupPage;
  newWindow.AppWindow.Resize(new SizeInt32(640, 360));
  newWindow.Activate();
}

実行すると、こんな感じで[PopupPage]クラスで作成した別画面が表示されます。

別画面が表示されている画面は独立しているので[MainWindow]画面も操作が可能な状態です。

まとめ

今回は短い記事ですが、Visual StudioのWinUI3プロジェクトで、別で追加した[.xaml]画面を、モードレス状態の別ウィンドウで表示する手順について紹介しました。

追加した[.xaml]画面`を[WinUI 3 Gallery]のサンプルで用意されている[WindowHelper]クラスを利用して別画面でモードレス表示が可能です。

WinUI 3アプリで[.xaml]画面を別画面としてモードレス表示したい人の参考になれば幸いです。

スポンサーリンク

最後までご覧いただき、ありがとうございます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です