Open19

VSCodeでAvalonia UI ~Epoxyを添えて~

いぬいぬいぬいぬ

XAMLプレビュー方法① AvantGarde

https://github.com/kuiperzone/AvantGarde

  • AvaloniaUIのプレビューアプリ

  • クロスプラットホーム

  • VSCode+Avant GardeでXAMLのプレビューしながら開発できる!

  • ハマりポイント

    • csprojの<TargetFrameworks>に非対応。<TargetFramework>にする必要あり。
    • アプリ自体のTargetFrameworkとXAMLのTargetFrameworkを合わせないと色々不具合が...
      • EpoxyのテンプレだとUIプロジェクトがnetstandard2.0になる
    • プレビュー中 にビルドするとファイルがロックされているので失敗する
      • close solutionで一旦閉じる
    • 大きめの変更したときはdotnet restore & dotnet buildが別途必要
      • solution読み直しで動くように
いぬいぬいぬいぬ

XAMLプレビュー方法② Live.Avalonia

https://github.com/AvaloniaUI/Live.Avalonia

  • Avaloniaでhot reloadingを実現するライブラリ
  • VSCode + Live.AvaloniaでXAMLのプレビューしながら開発できる!
  • 表示だけじゃなくてアプリ自体も普通につかえる
  • ハマリポイント
    • コードに手を入れる箇所がそこそこ多い
    • axamlファイルをdotnet watch対象にcsprojで指定する必要あり
    • WindowのXAML設定がスキップされちゃうのでコードで指定する必要あり
    • dotnet runのときにターゲットフレームワークを指定する必要あり
      • アプリが複数フレームワーク向けプロジェクトで作られてる時?
  • MVUとかで作る時に向いてる

https://gist.github.com/InuInu2022/84326613378b817e4e2af29bf762d77d

いぬいぬいぬいぬ

Avalonia UIのパーツの探し方・調べ方

VSCodeじゃなくても便利。

ギャラリー・サンプルアプリを使う

WASM Playground

  • 公式のWASMサンプル
  • Windows Storeにあるものよりサンプルが多い
  • その場でいじれて便利(VSCode環境だと特にね!)
  • wasmなので動かないものもある

FluentAvalonia Samples

  • FluentAvaloniaのギャラリーアプリ
    • FluentAvaloniaを使う時用だけど、標準パーツも一部見れる
  • 自分でビルドする必要がある(でもかんたん)
  • 直接いじれないけど実際に動作する
  • 標準パーツ、追加パーツ(WinUIの移植)の両方が見れる
    • Fluentな見た目で確認できる
  • Show Definitionでプロパティとかの定義も見れる
  • たまにサンプルソースがリンク切れ
  • FluentAvalonia経由でWinUIを使う時用
  • FluentAvalonia Samplesより細かく設定変えられたりする
いぬいぬいぬいぬ

Avalonia 日本語対応 状況と対策

v0.10.xの場合

  • TextBoxなどで日本語は豆腐になる(仕様)
  • 日本語のフォントを指定すればOK
  • css風に各OSの標準日本語フォントを書けばどのプラットホームでも表示できる
FontFamily="Meiryo UI, Hiragino Sans, Noto Sans CJK JP"
  • メインWindowのxaml中でTextBoxとかにまとめてスタイルすれば全部指定される

    • Appの方がいいかも?Avant Gardeでページ単体を見る時に反映されない
  • IMEはインライン入力できない

    • Windows10+FluentAvalonia+v0.10.18だと入力できることもある
    • 逆に一切入力できなくなることもある…めっちゃ不安定
    • コピペはイケル
  • 後ろから3文字目?が消えるバグ に遭遇

    • 文字列の置き換えやフォント指定で治ったりする
    • 再発することもある

v11.xの場合

いぬいぬいぬいぬ

Avalonia対応ライブラリ・サンプル

Control

Theme & Control

MVVM

  • Epoxy
  • Mvvm.Navigation
    • NavigationのコードをSource Generatorで自動生成するライブラリ
  • Stylet.Avalonia
    • WPF/UWPのCaliburn.MicroにインスパイアされたMVVMライブラリ

MVU

Rx

SourceGenerator

l8n/i18n

Other

いぬいぬいぬいぬ

Avalonia XPFとは

https://avaloniaui.net/XPF

  • Avalonia社が提供する 企業向け商用サービス
  • 既存のWPFアプリをクロスプラットフォーム移植してくれるというもの
    • 技術的にはモバイルやWASM対応もできるけど、まずはDesktopむけ
  • すでにアプリがある会社が利用するもので個人開発者は基本的に関係ない
  • 内部的にAvaloinia UIの仕組みが使われているらしい
Avalonia UI Avalonia XPF
これはなに UIフレームワーク サービス
価格 無料 有料
誰向け 誰でも 企業のみ
いぬいぬいぬいぬ

Avalonia v11情報

v11.1 beta

https://github.com/AvaloniaUI/Avalonia/discussions/14922

  • HyperLinkButton control が追加
  • XAML中でWPFにもあるUpdateSourceTriggerが使えるように
  • tvOS/AndroidTV/TizenTVのサポート。リモコン操作できるように

v11.0 Released!

  • 2023-07-05リリース

Avalonia for Visual Studio Code (Early Access)

  • ついに公式のVSCode向け拡張が発表
    • XAML補完
    • プレビューワ
  • 支援者むけに先行公開中
    • 普通につかえるようになった
    • https://github.com/AvaloniaUI/AvaloniaVSCode
    • ただし、v11.0.2以前じゃないとうまく動かないらしい
    • 他にも初回の反映に時間がかかるなど色々と細かい使い勝手が良くない問題あり

対応ライブラリ

  • Epoxy
    • Epoxy.Avalonia11 というのがリリースされた(v0.10系以前とは別に分かれた)
  • FluentAvalonia
    • v2.0.0がリリース
    • 以前なかった新しいControlも追加されている模様
  • NP.Ava.UniDock
    • NP.Avalonia.UniDockのv11対応版
    • 2023年末にやっと出た
いぬいぬいぬいぬ

migration to v11 memo

Porting guide

https://github.com/AvaloniaUI/Avalonia/wiki/Avalonia-11-Porting-Guide

porting guideに無い箇所

  • file選択/saveダイアログ系は新apiに変更されている
  • With(new Win32PlatformOptions… は不要の様子
  • drag and drop処理は以前のままだと System.ObjectDisposedException 出ることがある
    • Dispatcher.UIThread.InvokeAsync 経由でVMの処理を呼んでいた箇所
    • そのままVMのメソッドを呼べば動くように
await vm.DropFileEventAsync(e)
	.ConfigureAwait(false);
  • Bindingのランタイムエラーがよく出るように
    • どうもこういうものらしい(仕組み上しかたないとのこと)

ライブラリ

  • Epoxy
    • CommandFactory -> Command.Factory
  • FluentAvalonia
    • SymbolIconのsymbol指定文字列が一部無くなっている(*Fill系)
      • symbol指定文字列はv2.0.0のサンプルアプリで検索できる
    • ui:SplitButtonに対するスタイル指定がエラーに
      • そもそも使っていなかったので消したらエラー無くなった
いぬいぬいぬいぬ

XAMLプレビュー方法③:Avalonia for Visual Studio Code

https://github.com/AvaloniaUI/AvaloniaVSCode

公式のVSCode拡張。

  • プレビュー可能な公式VSCode拡張

    • XAML補完とかもある
  • 現時点の問題点

    • v11.0.2以下でないとプレビューがうまくいかない
    • 初回表示までにとても時間がかかる
    • クリック操作などは機能しない (一部直ってた)

プレビュー機能だけで言うと①や②の方が現時点では実用的。

いぬいぬいぬいぬ

XAMLプレビュー方法④ HotAvalonia

HotReloadを実現するライブラリ。

https://github.com/Kir-Antipov/HotAvalonia

ドキュメントを読む限り、Live.Avaloniaより使いやすそう。

  • dotnet watch 不要 (普通にビルドしても有効になる)
    • ただし.NET 7以降はデバッガー接続起動かwatch推奨らしい
  • 手を入れる行数少ない
いぬいぬいぬいぬ

Dock.Avalonia 関連

不穏な雰囲気

  • 一瞬ライセンスがAGPLに変わってすぐにMITに戻った
    • OSSでつかってほしいのかな?
  • github issuesが消えた
    • サポートしない方針?

描画系

  • プレビュー系と相性が悪い
    • HotAvalonia, AvantGardeともに更新がエラーになる
    • 生産性は良くない
  • 公式DevToolでツリーが追えない
    • Dockの中に隠されてしまう

FluentAvalonia + Dock.Avalonia

  • そのままだと見えなくなる
  • RGBのColorを指定すればとりあえず見えるようにはなる
  • RGBAのBrushを指定できない
    • なのでテーマ(Dark/Light)の切替は手動
      • Converterで持ってきたい所…
App.axaml
    <Application.Resources>
      <idcr:ControlRecycling x:Key="ControlRecyclingKey" TryToUseIdAsKey="True" />
      <Color x:Key="RegionColor">Transparent</Color>

      <SolidColorBrush x:Key="DockApplicationAccentBrushLow">#007ACC</SolidColorBrush>
      <SolidColorBrush x:Key="DockApplicationAccentBrushMed">#1C97EA</SolidColorBrush>
      <SolidColorBrush x:Key="DockApplicationAccentBrushHigh">#52B0EF</SolidColorBrush>
      <SolidColorBrush x:Key="DockApplicationAccentForegroundBrush">#F0F0F0</SolidColorBrush>
      <SolidColorBrush x:Key="DockApplicationAccentBrushIndicator">#007ACC</SolidColorBrush>

      <SolidColorBrush x:Key="DockThemeBorderLowBrush" Color="#808080" />
      <SolidColorBrush x:Key="DockThemeBackgroundBrush" Color="#F0F0F0" />
      <SolidColorBrush x:Key="DockThemeAccentBrush" Color="#FF8888" />
      <SolidColorBrush x:Key="DockThemeForegroundBrush" Color="#FEFEFE" />
      <SolidColorBrush x:Key="DockThemeControlBackgroundBrush" Color="#0000F0" />
    </Application.Resources>
いぬいぬいぬいぬ

UniDock関連

  • NP.Ava.UniDock の方でv11対応版出た
    • NP.Avalonia.UniDockはv0.10以前

サンプルコード

  • なぜかgit submoduleで必要ライブラリが全部落としてこれない…
  • Releaseビルドだと動いた
    • Debugビルドでもnugetに上がってるライブラリだけで動くようにcsproj書き換えちゃってもいいかも
いぬいぬいぬいぬ

Avalonia XAML Tips

Bindingで親要素は$parent

  • さらにその親は $parent[n]でどんどん階層を上がって行ける
    • $parent=$parent[0]; 一つ目の親が0
  • 詳細:Binding to an Ancestor
  • 親要素のWindow: $parent[Window]

Bindingで祖先のcontrolは $parent[ControlName]

  • $parent[Window]でウィンドウ参照できる
  • もっと上は $parent[ControlName; n]でどんどん階層を上がって行ける

Bindingで別のコントロールのViewModelを参照するにはキャスト&再ビルド

  • ((vm:MyUserControlViewModel)DataContext)とする
  • ホットリロードだとエラーになる。要再ビルド
<Button Command="{Binding $parent[ItemsRepeater].((vm:MyUserControlViewModel)DataContext).DoItCommand}"
                CommandParameter="{Binding ItemId}"/>

https://docs.avaloniaui.net/docs/basics/data/data-binding/compiled-bindings#type-casting

Bindingで否定は!

<Element IsEnabled = "{Binding !#someElem.IsEnabled}" />

非同期Bind(Task<T>にbind)

  • Task<T>を返す非同期処理にBindできる
<TextBlock Text="{Binding MyAsyncText^, FallbackValue='Wait a second'}" />

親要素と同じ幅を指定するのは "{Binding $parent.Bounds.Width}"

  • $parent.Width だとダメ。Bounds経由で。
いぬいぬいぬいぬ

Epoxy + Avalonia でCommandのバインドがうまくいかない時

  • EpoxyにはEventBinderというCommandがバインドできなくてもバインドできる便利機能がある
axaml
<NoCommandControl>
  <epoxy:EventBinder.Events>
      <epoxy:Event EventName="TargetEvent" Command="{Binding MyCommand}" />
  </epoxy:EventBinder.Events>
</NoCommandControl>
  • でもAvaloniaだとEventBinderが使えないことがちょくちょくある
    • SliderとかのPointWheelEvent
    • DragDrop.DropEvent
  • ランタイムエラー: 'Epoxy.Event'.'Command': 'Null value in expression '{empty}' at ''.'(Event #nnnnnnnn)
    • なんもわからん
  • WPF版Epoxyだともう少し色々できたような…

解決策1: Ancher/Pileを使う

  • VMでWindow.LoadedにバインドしたReadyコマンドの中とかで、piledControl.SomeEventChanged += MyCommand()する
  • HotAvaloniaのhotreloadと相性悪い場合にも使える

解決策2: あきらめてコードビハインド

  • DragDrop.DropEventはPile/Anchor使っても上手くいかなかった
    • 正直よく使うから何とかしたい…
  • HotAvaloniaのhotreloadと相性悪い?
いぬいぬいぬいぬ

CodingSeb.Localization for Avalonia v11

  • nuget v1.3.0 MethodMissingのランタイムエラー
  • AvaloniaSample
    • v11.0.*ではビルドが通らない
    • Fork
  • CodingSeb.Localization.Locが見つからないビルドエラー
    • nugetのCodingSeb.Localizationではなく、git submoduleなどでCodingSeb.Localizationに参照するとうまくゆく
  • readme.md の xmlns が正しくない(WPFでも問題あり)
readme.md
xmlns:loc="clr-namespace:Localization;assembly=Localization"
rewrite
xmlns:loc="clr-namespace:CodingSeb.Localization;assembly=CodingSeb.Localization"