はじめに
.NET初心者をターゲットに、「なんとなくMAUI分かったかも」と思ってもらうための記事です。
私は主にMacで作業することが多いですが、Windowsでも同様に作業が進められると思います。
動作環境
- Apple M2 Mac mini (Sonoma 14.4.1)
- .NET 8.0
まずは動かしてみる
プロジェクトの作成
Visual Studio で .NET MAUI アプリ
を選び、プロジェクト名: MauiExample
でプロジェクトを新規作成します。
VSCodeの場合は
dotnet new maui -o MauiExample
で同じことができます。
実行
Visual Studioでプロジェクトを開き、デバッグ ターゲットがWindowsの状態で実行します。
Mac+VSCodeの場合は
dotnet build -t:Run -f net8.0-maccatalyst
で実行できます。
以下の画面が起動したらOKです。
ボタンをクリックしたら何が起こるのかを確認してください。
うまく動かなかったら初めてのアプリを構築するを参考にしてください。
プロジェクトの構造について
作成されたプロジェクトのMauiExample
フォルダを開くと以下のようになっています。
MauiProgram.cs
プログラムを起動した時、最初に実行されるファイルです。
using Microsoft.Extensions.Logging;
namespace MauiExample;
public static class MauiProgram
{
public static MauiApp CreateMauiApp()
{
var builder = MauiApp.CreateBuilder();
builder
.UseMauiApp<App>()
.ConfigureFonts(fonts =>
{
fonts.AddFont("OpenSans-Regular.ttf", "OpenSansRegular");
fonts.AddFont("OpenSans-Semibold.ttf", "OpenSansSemibold");
});
#if DEBUG
builder.Logging.AddDebug();
#endif
return builder.Build();
}
}
builder
インスタンスを作り、このインスタンスに対して色々設定をしています。
この
◯◯builder
に設定をしていくパターンは、ASP.NET Coreなどの別フレームワークでも同様です。覚えておいて損はありません。
var builder = MauiApp.CreateBuilder();
「App
(App.xaml
+ App.xaml.cs
)を使いますよ」って宣言(.UseMauiApp<App>()
部分)と
使用するフォントの設定(.ConfigureFonts(...)
)をしています。
App.xaml, App.xaml.cs
App.xaml
にはアプリ全体から参照できるリソース(参考:リソース ディクショナリ
)を指定します。リソースの本体は「Resources」フォルダーに保存されています。
ここではColors.xaml
(使用する色に関する定義), Style.xaml
(使用するボタンなどのコントロールに関する定義)が指定されています。
例えば、「ボタンを全部赤色にしたい」といった場合、全ボタンに一つずつbackgroundColor="Red"
を書いていくのは面倒なので、赤色をボタンに設定するスタイルをResources」フォルダー内に作ってしてそれを各ページに適用するって感じで使います。
<?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:MauiExample"
x:Class="MauiExample.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
ではルートページとしてAppShell
(AppShell.xaml
+ AppShell.xaml.cs
)を指定しています。
MainPage
はAppの継承元であるApplication
クラスで定義されているプロパティですので、例えばRootPage
などに変更するとエラーになります。一応。
namespace MauiExample;
public partial class App : Application
{
public App()
{
InitializeComponent();
MainPage = new AppShell();
}
}
AppShell.xaml, AppShell.xaml.cs
AppShell
はナビゲーション機能などを提供するためのShellを継承したクラスです。
簡単にいうと画面の切り替えを行うためのものですが、今はMainPageしかないのであまり意味ないですね。
<?xml version="1.0" encoding="UTF-8" ?>
<Shell
x:Class="MauiExample.AppShell"
xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:MauiExample"
Shell.FlyoutBehavior="Disabled"
Title="MauiExample">
<ShellContent
Title="Home"
ContentTemplate="{DataTemplate local:MainPage}"
Route="MainPage" />
</Shell>
ナビゲーション方式はFlyout、またはTabがあります。リンク先のサンプルコードを見ればイメージが掴みやすいと思います。
AppShell.xaml.cs
の方は初期化だけで、特に何もしていません。
namespace MauiExample;
public partial class AppShell : Shell
{
public AppShell()
{
InitializeComponent();
}
}
MainPage.xaml, MainPage.xaml.cs
プログラム実行時に表示された画面のメイン部分です。
- ScrollView: スクロールを有効にする
- VerticalStackLayout: コントロールを垂直方向に並べる
- Image: 画像を表示する
- Label: テキストを表示する
- Button: ボタンを表示する
を使用して実装されています。
<?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="MauiExample.MainPage">
<ScrollView>
<VerticalStackLayout
Spacing="25" // コンポーネントとコンポーネントに 25px 隙間を設ける
Padding="30,0" // パディングを左右に30px, 上下に 0pxに設定
VerticalOptions="Center"> // 垂直方向に中央揃え
<Image
Source="dotnet_bot.png" // Resources¥Imagesにある画像ファイルを指定
SemanticProperties.Description="Cute dot net bot waving hi to you!"
HeightRequest="200" // 画像の高さを指定
HorizontalOptions="Center" /> // 水平方向に中央揃え
<Label
Text="Hello, World!" // 表示するテキスト
SemanticProperties.HeadingLevel="Level1"
FontSize="32" // テキストのフォントサイズ
HorizontalOptions="Center" /> // 水平方向に中央揃え
<Label
Text="Welcome to .NET Multi-platform App UI"
SemanticProperties.HeadingLevel="Level2"
SemanticProperties.Description="Welcome to dot net Multi platform App U I"
FontSize="18"
HorizontalOptions="Center" />
<Button
x:Name="CounterBtn" // ButtonオブジェクトをMainPage.xaml.cs内で参照するための指定
Text="Click me" // ボタンの中に表示するテキスト
SemanticProperties.Hint="Counts the number of times you click"
Clicked="OnCounterClicked" // クリックした時の処理
HorizontalOptions="Center" /> // 水平方向に中央揃え
</VerticalStackLayout>
</ScrollView>
</ContentPage>
Imageに
Source="dotnet_bot.png"
を指定していますが、不思議なことにResouces/Images
フォルダにはdotnet_bot.svg
ファイルしかありません。
MAUIにはビルド時にsvgをpngに変換する仕組みがあるのでdotnet_bot.png
をちゃんと参照できるのです。
参考: ローカル画像を読み込む
SemanticProperties
で始まるプロパティについてはセマンティック プロパティを使用してアクセス可能なアプリを構築するを参照してください。
注目すべきはButtonに指定された以下の2つです。
- x:Name="CounterBtn"
- Clicked="OnCounterClicked"
これを踏まえて、MainPage.xaml.cs
を見てみましょう
namespace MauiExample;
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";
SemanticScreenReader.Announce(CounterBtn.Text);
}
}
MainPage.xaml.cs
にはプロパティ: CounterBtn
が定義されていないのに、まるで定義済みかのようにCounterBtn.Text
でボタンのテキストを参照・変更しています。
また、OnCounterClicked
はMainPage.xaml
上でButtonのClicked
に指定されていました。
これがXaml
とC#
を組み合わせて画面+処理を実装する基本的な形になります。
XamlとC#(コードビハインド)の連携
これまで説明してきたAPP
, AppShell
, MainPage
には.xaml
と.xaml.cs
が対になって存在していました。これらの対のファイルは連携して動作します。
対応付けは
-
.xaml.cs
で定義されている名前空間+クラス名
-
.xaml
のx:Class
で指定された名前空間+クラス名
で行われます。
ファイル名やファイルパスは関係ないので、両ファイルを全く異なるパス、ファイル名で置いておくことはできますがオススメしません。同階層に
.xaml
と.xaml.cs
のペアで置いておくのが基本です。
試しにMainPage.xaml
の x:Class="MauiExample.MainPage"
を変えてみましょう。
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="MauiExample.TopPage"> // TopPageに変更
この状態でMainPage.xaml.cs
を開くと警告が出るようになります。
CounterBtn
が認識出来なくなっていますね。
逆にMainPage.xaml.cs
側のクラス名を変更しても同じ状態になります。
補足:Xamlは必須ではない
「.xaml
と.xaml.cs
のペアで動作するのが基本」と書きましたが、実は.xaml
無しでも実装はできます。
例えば、画面上にLabelを表示させる場合、.xaml.cs
内でインスタンスを作成すればXaml
内で<Label ... />
を記述したのと同等になります。
Label label = new Label { Text = "Hello world" };
// <Label Text="Hello world" /> と同等
とはいえ、UIに関するコードはXaml
、動作に関わるコードは.xaml.cs
に実装する方がコードの見通しがいいのでそちらをオススメします。
その他のフォルダについて
-
bin: ビルドの出力結果である実行可能なファイルの保存先
-
obj: ビルドの一時ファイル置き場
-
Platforms: プログラム起動時に、OSごとに異なる処理を実行させたい場合に使います(参考: マルチターゲットの構成)
-
Properties: アプリケーションの起動とデバッグの設定を構成するために使用される
launchSettings.json
置き場。launchSettings.json
では、プロファイル、環境変数、引数などを構成する。 -
Resouces: リソース ディクショナリ置き場。
今後の予定
- MVVM Toolkitを使用してMVVMにする
- CollectionViewでコレクションを表示する
- ContentPageを複数のContentViewに分割する
- Layoutのコツなど