【NXUI】C#でワンライナー・クロスプラットホームデスクトップアプリ【AvaloniaUI】
NXUI
NXUIというライブラリを使うとワンライナーでデスクトップアプリが作れます。
Run(() => Window().Content(Label().Content("NXUI")),"NXUI", args);
クロスプラットフォーム(Win/Mac/Linux/Web[1])で動きます。
macOS |
Run(
() => Window().Content(Label().Content("NXUI")),
"NXUI",
args);
WPFとかの、よくあるC#のデスクトップアプリの記述量を考えると怖いくらい短いです…!
いやいや、どうせカラクリあるんでしょ?
「🤔 C#コード以外に色々ファイルがあるんでしょ?XAMLとか…」と思うかもしれませんが、
アプリ本体の.cs
ファイルと、ビルド設定を記載した.csproj
の 2つ だけです。
「🤔わかった、csprojに色々記載があるんでしょ!」と思うかもしれませんが、csprojはこんな感じです。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Using Include="NXUI.Desktop.NXUI" Static="true" />
<PackageReference Include="NXUI.Desktop" Version="11.0.0" />
</ItemGroup>
</Project>
dotnet new console
したテンプレートから、
-
OutputType
をWinExe
に -
NXUI.Desktop.NXUI
をusing include - ライブラリのNXUIを参照
しただけです。
※しかもusing includeしているところは,なくてもRun(...)
がNXUI.Desktop.NXUI.Run(...)
になるだけなのであんまり短くなってないという…
いやいや、実用性ないじゃん
ハイ。
さすがにワンライナーで1行で書くとちょっとつらいですね…。
ただ、「1ファイル」に制限を広げれば簡単なデスクトップアプリは十分作れます。
メモアプリをつくってみる
こういうメモ帳的なやつを作ってみます。
UIをつくる
まずは改行OKにして、テキスト入力欄とボタンがあるウィンドウを作ります。
Run(
() => Window()
.Width(500).Height(300).Title("NXUI memo app sample")
.Content(
StackPanel()
.Children(
TextBox(out var tbox)
.MinHeight(200)
.AcceptsReturn(true)
.Watermark("文字入力ボックス"),
Button()
.Content("ボタン")
)
),
"memo app", args);
.Width(500).Height(300).Title("NXUI memo app sample")
の行は、ウィンドウの幅と高さ、ウィンドウ名を指定しています。
Content
の中にStackPanel
を置いて、そのChildren
にTextBox
とButton
を配置してます。
NXUIはこういう感じでメソッドチェーンで書いてUIを設定できます。
メモ帳的なやーつにしたいので、TextBox
には改行可能にしたり、高さを指定したり、文字入力されてないときのウォーターマーク表示を指定したりしてます。
TextBox(out var tbox)
.MinHeight(200)
.AcceptsReturn(true)
.Watermark("文字入力ボックス"),
TextBox(out var tbox)
の引数でout-varで変数tbox
を宣言してますが、これは後で使います。
ボタンを押したときの保存処理を作る
次に、ボタンを押した時に保存ダイアログが出てファイルを保存できるようにします。
やり方は色々ありますが、
いちばん簡単なButton
にOnClickHandler()
をつなげてやる方法はこんな感じです。
Button()
.Content("ボタン")
.OnClickHandler( async (b, a) => {
var top = TopLevel.GetTopLevel(b);
if (top is null) return;
var file = await top
.StorageProvider
.SaveFilePickerAsync(new() {Title = "テキストの保存"});
if(file is not null){
await using var str = await file.OpenWriteAsync();
using var stw = new StreamWriter(str);
await stw.WriteAsync(tbox.Text);
}
})
TextBox(out var tbox)
で宣言したtbox
のText
プロパティから文字列を取得して保存してます。
保存ダイアログいらないなら、もっと短くもできますね…!
完成
とりあえずこれで完成です…!
フルソース
Run(
() => Window()
.Width(500).Height(300).Title("NXUI memo app sample")
.Content(
StackPanel()
.Children(
TextBox(out var tbox)
.MinHeight(200)
.AcceptsReturn(true)
.Watermark("文字入力ボックス"),
Button()
.Content("ボタン")
.OnClickHandler( async (b, a) => {
var top = TopLevel.GetTopLevel(b);
if (top is null) return;
var file = await top
.StorageProvider
.SaveFilePickerAsync(new() {Title = "テキストの保存"});
if(file is not null){
await using var str = await file.OpenWriteAsync();
using var stw = new StreamWriter(str);
await stw.WriteAsync(tbox.Text);
}
})
)
),
"memo app", args);
これくらいなら1ファイルで完成します。
ちょっとしたボタンが数個、みたいなUIがあるだけのツールにめっちゃいいのでは!?
NXUIのカラクリ
ここからは、NXUIのカラクリを説明します!
NXUIはAvalonia UIのライブラリ
NXUIは実はAvalonia UIというUIフレームワークのライブラリです。
NXUI (nex-ui), next-gen UI - Create minimal Avalonia applications using C# 10 and .NET 6, 7 & 8
Avalonia UIは、WPFやXamarinやらMAUIみたいに普通はUIの記述にXMLの一種のXAMLを使うんですが、C#だけでも書くことができます。ただ、そのままだと冗長だったりファイルが多くなったりします。
NXUIはC#のコードだけでAvalonia UIを書きやすくしたライブラリになります。
似たようなライブラリには「Avalonia.Markup.Declarative」とかF#むけの「Avalonia.FuncUI」とかもありますが、
それと比べても記述量が少ないです。
開発者の方はAvalonia UI本体の開発者(Wiesław Šoltésさん)でもあるので"ほぼ公式"と言ってもいいと思います。
機能的にはAvalonia UIのものが使えます。
ドキュメントはほとんどない!
Avalonia UIも日本語ドキュメントはほとんどないですが、NXUI自体のドキュメントは公式のReadmeとサンプルだけでほぼありません…。
とはいえ、Avalonia UIをXAMLを使わないでC#やF#だけで書いているようなものなので、Avalonia UIのAPIリファレンスが使えます。
普通はXAMLでやるところを全部C#やF#でやってるので、Avalonia UIの公式のサンプルコードだけだとツライですね。
あんまり凝ったことには向いてないかな?と思います。
いぬいぬは個人的にはAvalonia UIのライブラリ「FluentAvalonia」のサンプルアプリ、「FAControlGallery」の機能でAPIを調べることが多いです。
入門記事としては、英語ですけどこういう記事があります。
Avalonia UIに関しては、Scrapにちょっとまとめてます。
NXUIできること・できないこと
基本的にはAvalonia UIでできることはできますが、一部できないのがあります!
XAML関係は当たり前ですけど難しいですね。
凝ったことも難しいと思いますので、やっぱりUIのパーツが数個、みたいなミニツールとかに使うのがいいかなと思います。
できる
- クロスプラットフォーム(除くモバイル)
- シングルファイルアプリ
- .NETの機能
できない
- プレビュー
- XAMLがないので、Avalonia UI向けのプレビュー拡張やツールは使えないみたいです
- モバイル対応
- Avalonia UIとは違ってモバイルむけには対応してなさそうです
- NXUIが省略してかけるようにしているところを全部自分で書けばできるかもしれません…
- Avalonia UIとは違ってモバイルむけには対応してなさそうです
- HotReload
- 公式にはサポートしてないみたいです
- Avalonia UIにはLive.AvaloniaやHotAvaloniaというライブラリがありますが…
- HotAvalonia:XAML前提なのでむりそう
- Live.Avalonia:FuncUI向けのものを対応すればできる可能性ある?
不明
- ネイティブバイナリ書き出し
- できそうな気もするけど…
- ヘッドレステスト
-
Run()
関数じゃなくてAppBuilder
でUseHeadless
すればできそう?
-
-
最新版だとうまく動かない模様 ↩︎
Discussion