.NET MAUI Blazor App - モバイル、デスクトップ、Web ハイブリッドアプリを開発


既存の Web 開発コードとスキルでクロスプラットフォームネイティブクライアントを簡単に作る

皆様、こんにちは!
Elastic テクニカルプロダクトマーケティングマネージャー/エバンジェリストの鈴木章太郎です。
.NET 6 Advent Calendar 12/11分です。
本稿では、何を書こうか悩んだ末、シンプルな内容ですが Preview でもある MAUI Blazor について書こうと思います。これ、.NET Conf 2021 でも紹介されていましたよね?既存の Web 開発コードとスキルを使ってクロスプラットフォームのネイティブクライアントを簡単に作ることができます。

.NET MAUI と Blazor

ASP.NET Core と Blazor には、.NET で最新のインタラクティブな Web アプリケーションを構築するために必要なものがすべて揃っています。しかし、時には、Web アプリケーションでできること以上のことが必要になることがあります。つまり、ネイティブなクライアントアプリを構築する必要があるわけです。
そのとき、.NET MAUI と Blazor があれば、既存の Web 開発スキルを使って、モバイルやデスクトップ向けのクロスプラットフォームのネイティブクライアントアプリを構築することができます。実際にやってみましょう。

Visual Studio 2022 Preview(17.1.0 Preview 1.1)インストール

最初の .NET MAUI の Blazor アプリを作りましょう。Visual Studio 2022 の .NET MAUI 機能を使ってみます。MAUI 機能が有効になっていれば、問題ありません。
しかし、MAUI はプレビューですので、Visual Studio 2022 Preview(17.1.0 Preview 1.1)をインストールする必要があります。このリンク(下記のページに遷移します)からインストーラーをダウンロードしてください。

インストーラーのみダウンロードしたら、このページに従いインストールします。インストール時は .NET によるモバイル開発セクションを選択し .NET MAUI(プレビュー)にチェックを入れてください。

新しいプロジェクトの作成

それでは、新しいプロジェクトを作成して、.NET MAUI Blazor App(Preview) を探して選択し、新しいプロジェクトを作成しましょう。

MauiApp1は、プロジェクトの名前としては他と被らなそうなので、このままプロジェクトを作成します。

デスクトップでもモバイルでも、Windows、Mac、Mac Catalyst、iOS、Android でも動作するアプリが用意されました。

Android 用のアプリの実行

それでは、Android で実行してみましょう。1分ほどで起動します。
※ Android Emulator をまだダウンロード、インストールしていない場合は、"初めての .NET MAUI アプリを作成する - .NET MAUI" を参考にセットアップしてください。Android で初めての .NET MAUI アプリを作成して実行する方法について説明されています。

ここでは、通常の Blazor アプリがネイティブとして動作しているように見えます。Android アプリです。Android エミュレータで実行すると、通常の Blazor テンプレートの機能をすべて備えているのがわかります。
Counter があり、Button でカウントアップすることができます。FetchData ページでは、簡単な天気予報が表示されます。これらはすべて、通常の Blazor コンポーネントを使って実装されています。Web UI コンポーネントを使用しています。

コードを探検

それでは、コードを見てみましょう。Blazor アプリのメインページの XAML ファイルです。コントロールが1つだけなのがわかると思います。

Mainpage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui"
             xmlns:local="clr-namespace:MauiApp1"
             x:Class="MauiApp1.MainPage"
             BackgroundColor="{DynamicResource PageBackgroundColor}">

    <b:BlazorWebView HostPage="wwwroot/index.html">
        <b:BlazorWebView.RootComponents>
            <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
        </b:BlazorWebView.RootComponents>
    </b:BlazorWebView>

</ContentPage>

これは Blazor Web UI コントロールで、基本的にはブラウザに埋め込まれたコントロールです。これはBlazor コンポーネントをレンダリングするためのものです。この場合、メインのコンポーネントをレンダリングします。Main.razor です。

Main.razor
<Router AppAssembly="@GetType().Assembly">
    <Found Context="routeData">
        <RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
    </Found>
    <NotFound>
        <LayoutView Layout="@typeof(MainLayout)">
            <p>Sorry, there's nothing at this address.</p>
        </LayoutView>
    </NotFound>
</Router>

これは、通常の Blazor ルーターで、ここにある場所やコンポーネントページにルーティングされます。例えば、カウンターコンポーネントは全く同じです。

Counter.razor
@page "/counter"
<h1>Counter</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code
    private int currentCount = 0;
    private void IncrementCount()
    {
        currentCount++;
    }
}

Blazor の Web アプリケーションでも、デスクトップでも同じように動作します。

Windows 用のアプリの実行

試しに Windows で動かしてみましょう。

これで Blazor アプリが Windows のデスクトップアプリとして動作するようになりました。

すべての同じ機能がこの中で働き、適用されます。モバイルやデスクトップ、さらにはクロスプラットフォームでも、Mac Catalyst や iOS でも動作します。これは素晴らしいですね。

僕は、最近は、React/React Native や Flutter などを、Elastic 連携 demo アプリ開発に使用しています。ただ僕自身、Microsoft エバンジェリスト時代の最初の頃、2006年の WPF から始まり、Silverlight、UWP、Xamarin...と一貫して XAML のエバンジェリストの一人だったので、まさにこういう後継の最新テクノロジーの登場は感慨無量です。
※ もっとも、Dart / Flutter を作った一人の Tim Sneath は、もともと WPF の Engineering Team にいた人です。だから Android Studio / Dart / Flutter での実行とデバッグは割と似たエクスペリエンスではないかと(笑)

ネイティブな UI を追加する

さて、これは .NET MAUI アプリケーションなので、ネイティブプラットフォームの機能を利用することができます。例えば、ネイティブなUI を追加することもできます。
メインページに戻りましょう。XAML です。このアプリにちょっとしたネイティブ機能を追加するために、ここにコードを追加して変更してみましょう。ネイティブのラベルが付いたグリップコントロールと、Blazor Web View Control を用意しました。

Mainpage.xaml
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:b="clr-namespace:Microsoft.AspNetCore.Components.WebView.Maui;assembly=Microsoft.AspNetCore.Components.WebView.Maui"
             xmlns:local="clr-namespace:MauiApp1"
             x:Class="MauiApp1.MainPage"
             BackgroundColor="{DynamicResource PageBackgroundColor}">
  <Grid RowDifinitions="Auto, *"> 
        <Label Text="This is soooo native" GridLayout.Row="0"></label>
        <b:BlazorWebView HostPage="wwwroot/index.html">
            <b:BlazorWebView.RootComponents>
                <b:RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
            </b:BlazorWebView.RootComponents>
        </b:BlazorWebView>
  </Grid>

</ContentPage>

では、もう一度実行してみましょう。できました!一番上にネイティブラベルがありますね。

コードからネイティブプラットフォームの機能を使う

そして、コードの中でもネイティブプラットフォームの機能を使うことができます。では、index.razor に戻ってみましょう。ここにちょっとしたコードを追加してみましょう。
ボタンに OnClick Handler を追加しましょう。これにより表示したいメッセージを取得します。
後ほど、Button を作成して確認します。ここでメッセージを定義して、GetMessage( )メソッドのコードを書きます。この中に、コードを追加していきます。
このコードで実現できるのは、ネイティブのテキストエディタを開いて、そこで文字列を編集し、保存することです。これはプラットフォーム付属のテキストエディタ(メモ帳、notepad.exe)です。

Index.razor
@page "/"
@using System.IO

<h1>Hello, Blazor MAUI!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />

<button @onClick="GetMessage">Edit</button>
<p>@message</p>

@code {
    string message ="Hello!";

    void GetMessage()
    {
        var file = Path.GetTempFileName();
        File.WriteAllText(file, "Enter Message Here");
        var p = System.Diagnostics.Process.Start("notepad", file);
        p.WaitForExit():
        message = File.ReadAllText(file);
    }
}

高度なテキストエディタの完成

この実現のために Razor エディタを使います。これで準備完了です。もう一度実行してみましょう。

メモ帳が表示されるので、"Updated! "と入力して保存して閉じます。

これで、メモ帳から取得したテキストが、ネイティブクライアントアプリケーションのファイルシステムに格納されました。これは単なる Web アプリケーションだけではできないことです。.NET MAUI と Blazor を組み合わせることでそれが可能になります。
既存の Web 開発コードとスキルを使って、クロスプラットフォームのネイティブクライアントを簡単に構築することができます。ぜひ、試してみてください。

ということで、それではまた!

鈴木章太郎
Elastic テクニカルプロダクトマーケティングマネージャー/エバンジェリスト