WinUI 3.0 Preview1 を触ってみよう
Published May 21 2020 02:45 AM 5,632 Views
Microsoft

Build 2020 のタイミングで Windows UI Library 3.0 Preview 1 が出ました。

まだまだ制限事項がたくさんありますが、Win32 アプリもサポートされている点がとっても興味深いリリースになります。

 

Windows UI ライブラリ 3.0 Preview 1 (2020 年 5 月)

 

上記のリリース ノートにもあるように現段階では実稼働のアプリでの利用は想定されていませんが、フィードバックの収集が目的の一つでもあるので、是非正式リリースされたら使ってみようと思っている方も是非試してみてフィードバックをお願いします。(GitHub のリポジトリでフィードバック可能です)

 

色々な制限事項がありますが、日本語での利用時に致命的な制限事項として IME が機能しないという制限事項があります。その点だけは注意して利用してください。完全な制限事項のリストは、リリースノートに記載してあります。

 

下準備

では、早速使ってみようと思います。Get started with WinUI 3.0 for desktop apps にセットアップ方法があります。Windows 10 のバージョン以外には Visual Studio 2019 16.7 Preview 1 と .NET 5 Preview 4 と、プロジェクトテンプレート用の Visual Studio の拡張機能が必要になります。

 

下準備が完了すると、以下のように WinUI 系のプロジェクトテンプレートが追加されます。

KazukiOta_0-1590051505677.png

Blank App, Packaged (WinUI in Desktop) を試してみようと思います。

winui1.gif

 

プロジェクトの作成と中身の確認

このプロジェクトを新規作成すると一見 WPF アプリのプロジェクトに見えるプロジェクトと、MSIX にパッケージングするための Windows アプリケーション パッケージ プロジェクトが作成されます。

KazukiOta_0-1590052218556.png

App クラスや MainWindow クラスのベースクラスも Microsoft.UI.Xaml.Application クラスや Microsoft.UI.Xaml.Window クラスなので WPF とは全く別物であることがわかります。

実行してみると、ひな型では以下のようにボタンがあるだけの非常にシンプルな画面が起動してきます。私の Windows 10 は、今ダークモードにしているのでそれが反映されてウィンドウの背景とボタンが黒っぽくなっています。

ここら辺が、何も考えなくても反映されるのはとてもありがたいと思います。

 

winui1.gif

プロジェクトファイルを確認すると、.NET 5 であることと WinExe を出力すること、あとは Microsoft.WinUI パッケージを参照していることが確認できました。

 

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>WinExe</OutputType>
    <TargetFramework>netcoreapp5.0</TargetFramework>
    <TargetPlatformVersion>10.0.18362.0</TargetPlatformVersion>
    <TargetPlatformMinVersion>10.0.17134.0</TargetPlatformMinVersion>
    <RootNamespace>HelloWorldApp</RootNamespace>

    <ApplicationManifest>app.manifest</ApplicationManifest>
    <Platforms>AnyCPU;x86;x64</Platforms>
    <SelfContained>true</SelfContained>
    <RuntimeIdentifiers>win-x86;win-x64</RuntimeIdentifiers>
    <RuntimeIdentifier>win-$(Platform)</RuntimeIdentifier>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.VCRTForwarders.140" Version="1.0.6" />
    <PackageReference Include="Microsoft.WinUI" Version="3.0.0-preview1.200515.3" />
    <Manifest Include="$(ApplicationManifest)" />
  </ItemGroup>
  <ItemGroup>
    <None Remove="App.xaml" />
    <None Remove="MainWindow.xaml" />
  </ItemGroup>
  <ItemGroup>
    <Page Update="App.xaml">
      <Generator>MSBuild:Compile</Generator>
    </Page>
    <Page Update="MainWindow.xaml">
      <Generator>MSBuild:Compile</Generator>
    </Page>
  </ItemGroup>
</Project>

 

コードの方を少しいじってみようと思います。手前味噌ではありますが、ReactiveProperty を追加して、ViewModel クラスを使って ReactiveProperty を使った入力に対して少し遅れて大文字に変換して画面に表示するものを試してみたいと思います。

 

NuGet から ReactiveProperty v7.0.1 を追加して、MainWindowViewModel クラスを追加して以下のように書いてみました。

 

using Reactive.Bindings;
using System;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Reactive.Linq;

namespace HelloWorldApp
{
    public class MainWindowViewModel
    {
        [Required(ErrorMessage = "{0} is required.")]
        public ReactiveProperty<string> Input { get; }
        public ReadOnlyReactiveProperty<string> InputErrorMessage { get; }
        public ReadOnlyReactiveProperty<string> Output { get; }

        public ReactiveCommand ResetCommand { get; }

        public MainWindowViewModel()
        {
            Input = new ReactiveProperty<string>("", 
                ReactivePropertyMode.Default | ReactivePropertyMode.IgnoreInitialValidationError)
                .SetValidateAttribute(() => Input);
            InputErrorMessage = Input.ObserveValidationErrorMessage()
                .ToReadOnlyReactiveProperty();

            Output = Input.Delay(TimeSpan.FromSeconds(2))
                .Select(x => x.ToUpper())
                .ToReadOnlyReactiveProperty();

            ResetCommand = Input.Select(x => !string.IsNullOrEmpty(x))
                .ToReactiveCommand()
                .WithSubscribe(() => Input.Value = "");
        }
    }
}

 

そして、MainWindow に、これをバインドします。バインドは、Preview 1 の段階ではコンパイル時データバインディングのみになっているようです。今後もそうなのかは不明ですが、DataContext プロパティが Window になくてびっくりしました。

というか新規に作るならコンパイル時データバインディングだけでも困ることは、ほとんどないのでいいですよね。

 

ということで MainWindow.xaml を以下のようにします。あわせて MainWindow.xaml.cs から、デフォルトのボタンクリックイベントハンドラも消して ViewModel のプロパティを追加します。

 

<Window
  x:Class="HelloWorldApp.MainWindow"
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  xmlns:local="using:HelloWorldApp"
  xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
  mc:Ignorable="d">
    <StackPanel>
        <TextBox Text="{x:Bind ViewModel.Input.Value, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
        <TextBlock Text="{x:Bind ViewModel.InputErrorMessage.Value, Mode=OneWay}" Foreground="Red" />
        <Button Content="Reset" Command="{x:Bind ViewModel.ResetCommand}" />
        <TextBlock Text="{x:Bind ViewModel.Output.Value, Mode=OneWay}" />
    </StackPanel>
</Window>

 

 

 

using Microsoft.UI.Xaml;

// The Blank Window item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409

namespace HelloWorldApp
{
    /// <summary>
    /// An empty window that can be used on its own or navigated to within a Frame.
    /// </summary>
    public sealed partial class MainWindow : Window
    {
        private MainWindowViewModel ViewModel { get; } = new MainWindowViewModel();
        public MainWindow()
        {
            this.InitializeComponent();
        }
    }
}

 

 出来たので実行してみましょう。

winui2.gif

ちゃんと 2 秒遅れて大文字になって表示されてますね。

 

まとめ

ということで、Windows UI Library 3.0 Preview 1 が出たので、その中の Win 32 アプリのプロジェクトテンプレートを試してみました。

かなりシームレスに Win UI Library がアプリ内で使えることがわかりました。今回の Preview 1 ではサポートされていませんが、XAML Islands の機能が追加されると WPF などの従来のアプリに組み込むことも出来ると思います。ViewModel をきちんと作ってるアプリであれば View だけ移植するのも、そこまで大変じゃないかもしれないという淡い期待が持てそうだと思います。

 

ReactiveProperty も普通に動いてバリデーションもちゃんと動いていました。

 

是非、皆さんも面白そうだなと思ったらインストールして試してみてください。

Version history
Last update:
‎May 21 2020 02:55 AM
Updated by: