はじめに
Windows のデスクトップアプリを作るのに自分は、以前は Delphi を使っていて、仕事は WinForms+VB.NET を使っていて、趣味は Electron も使っています。新たにアプリを作り始めるのに、別の開発手段も試してみようと思いました。
.NET MAUI とは
.NET Multi-Platform App UI (. NET MAUI) は、C# と XAML を使用して、ネイティブのモバイル アプリやデスクトップ アプリを作成するための、クロスプラットフォーム フレームワークです。
(.NET MAUI とは - .NET MAUI | Microsoft Learn)
チュートリアルのソースコードの一部を見てみます。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="●●.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
<Button
x:Name="CounterBtn"
Text="Click me"
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked"
HorizontalOptions="Center" />
</VerticalStackLayout>
</ScrollView>
</ContentPage>
public partial class MainPage : ContentPage
{
int count = 0;
public MainPage()
{
InitializeComponent();
}
private void OnCounterClicked(object sender, EventArgs e)
{
count++;
if (count == 1)
CounterBtn.Text = $"Clicked {count} time";
else
CounterBtn.Text = $"Clicked {count} times";
}
}
XAML で画面の定義して C# でロジックを実装します。いわゆるウェブアプリが HTML で画面の定義して JavaScript でロジックの実装するのと似ています。
.NET MAUI を始めてみた
Visual Studio を使う
参考:Visual Studio 2022 をインストールする - .NET MAUI | Microsoft Learn
プロジェクトを新規作成する
参考:初めての .NET MAUI アプリをビルドする - .NET MAUI | Microsoft Learn
新規プロジェクトの内容を確認する
アプリのベースになるプロジェクトは簡単に作成できましたが、ファイルが幾つもあります。どのファイルを変更すればいいのか。それを知るために、プロジェクトに含まれるファイルを調べてみました。
MauiProgram.cs
エントリポイントは、MauiProgram.cs
のようです。
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>();
return builder.Build();
}
}
builder.UseMauiApp<App>();
で指定されている App
の定義を探します。
App.xaml および App.xaml.cs
App.xaml.cs
に App
というクラスの定義がありました。
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
<?xml version = "1.0" encoding = "UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:●●"
x:Class="●●.App">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Resources/Styles/Colors.xaml" />
<ResourceDictionary Source="Resources/Styles/Styles.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs
で new されている AppShell
の定義を探します。
AppShell.xaml および AppShell.xaml.cs
AppShell.xaml
と AppShell.xaml.cs
がありました。
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="●●.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:●●"
Shell.FlyoutBehavior="Disabled">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
</Shell>
ContentTemplate="{DataTemplate local:MainPage}"
および Route="MainPage"
で指定されている MainPage
の定義を探します。
MainPage.xaml および MainPage.xaml.cs
MainPage.xaml
と MainPage.xaml.cs
がありました。ようやく画面を定義しているファイルに辿り着きました。
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="●●.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25"
Padding="30,0"
VerticalOptions="Center">
(中略)
</VerticalStackLayout>
</ScrollView>
</ContentPage>
このファイルを修正すればいいようです。
このファイルを MauiProgram.cs
で指定すればいいように思いましたが、AppShell
クラスでルーティング機能つまりページ遷移を実装しています。
.NET MAUI を始めてみたが
●●.xaml.cs
は ●●.xaml
とセットになっています。WinForms+C# のアプリで ●●.cs
と ●●.Designer.cs
がセットになるのと同じでしょうか。
WinForms アプリを Visual Studio で開発するときはビジュアルデザイナが使えるので ●●.Designer.cs
は直接編集することがありませんが、.NET MAUI アプリは Visual Studio でも ●●.xaml
を直接編集しないといけないようです。
MainPage.xaml
に手を加え始めましたが、思ったように書けそうにありません。自分は以前に WPF アプリを作ろうとして、このときも XAML の編集に馴染めなくて挫折していました。
.NET MAUI の記事を読み漁っていると、Blazor で開発するという記事を見つけました。
.NET Blazor とは
Blazor は、開発者が C# と HTML を使用してウェブアプリを作成できるようにする、無料のオープンソースのフレームワークです。これは Microsoft によって開発されています。
(Blazor - Wikipedia)
チュートリアルのソースコードの一部を見てみます。
@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++;
}
}
前半は HTML そのもので、後半は C# のコードです。XAML より書きやすそうです。
.NET Blazor を始めてみた
Visual Studio を使う
参考:Blazor チュートリアル | ダウンロードしてインストールする
プロジェクトを新規作成する
参考:Blazor チュートリアル | 最初の Blazor アプリをビルドする
Blazor サーバアプリと Blazor クライアントアプリ
Blazor アプリは、
- サーバで実行されて HTML がレンダリングされるタイプ「Blazor Server アプリ」
- クライアントのブラウザ上で実行されるタイプ「Blazor WebAssembly アプリ」
参考:ASP.NET Core Blazor | Microsoft Learn
サーバサイド Blazor を始めてみた
まず、サーバサイド Blazor アプリを作ってみました。
プロジェクトの内容を確認する
アプリのベースになるプロジェクトは簡単にできましたが、ファイルが幾つもあります。どのファイルを変更すればいいのか。それを知るために、プロジェクトに含まれるファイルを調べてみました。
Program.cs
エントリポイントは、Program.cs
のようです。
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
builder.Services.AddServerSideBlazor();
var app = builder.Build();
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
app.Run();
app.MapFallbackToPage("/_Host");
で指定されている _Host
の定義を探します。
Pages/_Host.cshtml
Pages
フォルダに _Host.cshtml
がありました。
@page "/"
@using Microsoft.AspNetCore.Components.Web
@namespace ●●.Pages
@addTagHelper *, Microsoft.AspNetCore.Mvc.TagHelpers
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="~/" />
<link href="css/site.css" rel="stylesheet" />
<component type="typeof(HeadOutlet)" render-mode="ServerPrerendered" />
</head>
<body>
<component type="typeof(App)" render-mode="ServerPrerendered" />
<script src="_framework/blazor.server.js"></script>
</body>
</html>
<component type="typeof(App)"
で指定されている App
の定義を探します。
App.razor
App.razor
がありました。
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
</Found>
<NotFound>
<p>Sorry, there's nothing at this address.</p>
</NotFound>
</Router>
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)"
で指定されている MainLayout
の定義を探します。
MainLayout.razor
MainLayout.razor
がありました。
@inherits LayoutComponentBase
<main>
@Body
</main>
@Body
に何か埋込されるようです。
参考:ASP.NET Core Blazor レイアウト | Microsoft Learn
参考:ASP.NET Core の Blazor ルーティングとナビゲーション | Microsoft Learn
起動時には "/"
が指定されたページが埋込されます。
Pages/Index.razor
Pages
フォルダに Index.razor
がありました。
@page "/"
<h1>Hello, world!</h1>
このファイルを修正すればいいようです。ようやく画面を定義しているファイルに辿り着きました。
このファイルを _Host.cshtml
で指定すればいいように思いましたが、App.razor
で Router
コンポーネントを使ってルーティング機能つまりページ遷移を実装しています。
クライアントサイド Blazor を始めてみた
続いて、クライアントサイド Blazor アプリを作ってみました。
新規プロジェクトの内容を確認する
アプリのベースになるプロジェクトは簡単に作成できましたが、ファイルが幾つもあります。どのファイルを変更すればいいのか。それを知るために、プロジェクトに含まれるファイルを調べてみました。
Program.cs
エントリポイントは、Program.cs
のようです。サーバサイドのアプリと違っています。
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
builder.RootComponents.Add<App>("#app");
で指定されている #app
と App
の定義を探します。
wwwroot/index.html
wwwroot
フォルダの index.html
に <div id="app">
がありました。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<base href="/" />
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<script src="_framework/blazor.webassembly.js"></script>
</body>
</html>
<div id="app">
にコンテンツが埋込されるようです。
App.razor
App.razor
がありました。ここからサーバサイド Blazor アプリと同じです。
.NET MAUI+Blazor を始めてみた
プロジェクトを新規作成する
参考:BlazorWebView を使用して .NET MAUI アプリで Blazor Web アプリをホストする - .NET MAUI | Microsoft Learn
新規プロジェクトの内容を確認する
アプリのベースになるプロジェクトは簡単に作成できましたが、ファイルが幾つもあります。これのどこを変更すればいいのか。それを知るために、プロジェクトに含まれるファイルを調べてみました。
MauiProgram.cs
エントリポイントは、MauiProgram.cs
のようです。XAML を使った MAUI アプリと同じです。
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>();
builder.Services.AddMauiBlazorWebView();
builder.Services.AddSingleton<WeatherForecastService>();
return builder.Build();
}
}
builder.Services.AddMauiBlazorWebView();
と builder.Services.AddSingleton<WeatherForecastService>();
が加わっています。
builder.UseMauiApp<App>();
で指定されている App
の定義を探します。
App.xaml および App.xaml.cs
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new MainPage();
}
}
<?xml version="1.0" encoding="UTF-8" ?>
<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:●●"
x:Class="●●.App">
<Application.Resources>
<ResourceDictionary>
(中略)
</ResourceDictionary>
</Application.Resources>
</Application>
App.xaml.cs
で new されている MainPage
の定義を探します。
MainPage.xaml および MainPage.xaml.cs
public partial class MainPage : ContentPage
{
public MainPage()
{
InitializeComponent();
}
}
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:●●"
x:Class="●●.MainPage"
BackgroundColor="{DynamicResource PageBackgroundColor}">
<BlazorWebView HostPage="wwwroot/index.html">
<BlazorWebView.RootComponents>
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
</BlazorWebView.RootComponents>
</BlazorWebView>
</ContentPage>
XAML を使った MAUI アプリは、このファイルで画面の定義していましたが、Blazor を使った MAUI アプリは、 <BlazorWebView>
が配置されていて、wwwroot/index.html
が埋込されているようです。
<RootComponent Selector="#app" ComponentType="{x:Type local:Main}" />
で指定されている #app
と Main
の定義を探します。
wwwroot/index.html
wwwroot
フォルダに index.html
ファイルがあります。クライアントサイド Blazor アプリと同じです。
Main.razor
Blazor アプリの App.razor
と同じです。ここから Blazor アプリと同じです。App.razor
でないのは App.xaml
があるからでしょうか。
.NET MAUI+Blazor を始めてみたが
.NET MAUI+Blazor アプリは、実行ファイルを作るのは MAUI のフレームワークだが、アプリの機能を実装するのは基本的に Blazor になります。
エントリポイントから Blazor を実行するまでは、変更することはないでしょう。アプリの機能を実装するには、MainLayout.razor
あるいは Pages/Index.razor
辺りを編集します。
Blazor は、HTML+CSS+JavaScript の代わりに HTML+CSS+C# で書くので、XAML+C# を新たに覚えて使うより楽かも知れません。