【.NET MAUI 】リリース候補版をインストールしてみた
[Microsoft] が 全く新しい UI Framework を公開した模様。
ここ数年、多忙のためブログの更新が止まってましたが、久々に色々いじくりまわしてみたいと思います。
2022年4月19日現在、[.NET MAUI]はようやくリリース候補版(RC版・・・Release Candidate)が公開された状況です。よって Windows で .NET MAUI を弄るには、Windows を開発者モードに変更し、Visual Studio を最新のプレビュー版に変更する必要があります。
「スタート」ボタンから「設定」→「ホーム」→「更新とセキュリティ」を選択、「開発者モード」をONに設定します。
Visual Studio 2022を起動。「ヘルプ(H)」→「更新プログラムの確認(C)」をクリックして、Visual Studio Installer を起動します。
更新チャネルを「Current」から「Preview」に変更すると、最新のプレビュー版をインストール可能になります。
4月19日現在の最新プレビュー、17.2.0 Preview 3.0 をインストールします。
Visual Studio 2022 Preview のインストールが完了したら、Visual Stuudio を起動し、「ツール」→「ツールと機能を取得(T)」をクリックします。
「.NET によるモバイル開発」のオプション「.NET MAUI(プレビュー)」をチェックし、更新します。
更新が完了したら、「新規作成」→「プロジェクト」をクリックします。.NET MAUI のテンプレートが追加されてるので、今回は「.NET MAUI アプリ(プレビュー)」でサンプルアプリを作ってみようと思います。
とりあえず既定の設定のまま、新規プロジェクトを作成します。
ソリューションの構成はこうなってる・・・
ソリューションを生成した時点で、すでにいくつかコントロールが実装されてるようです。とりあえずこのまま実行してみましょうか。「Windows Machine」で実行します。
こうなりました。「Click me」と書いてあるボタンをクリックすると、カウンターが増加します。
ここの実装は MainPage.xaml.cs に最初から記述してあります。
まずは .NET MAUI の開発環境設定からソリューションの作成・実行まで。この先はおいおい書いてく予定です。
Q128. IE ベースでない Browser コントロールは存在しないか
A.昨日のエントリでは WPF のWebBrowserコントロールについて書きました。これ IE7という非常に旧いバージョンをベースにしてるので、ページによってはレイアウトが大きく崩れます。それを回避するのがレジストリ編集な訳なんですが、標準コントロールにも関わらずそこまでしなきゃいけないのは、なんとも気持ち悪すぎます。何とかならんかということで、WebBrowser 以外の Browserコントロールを探したところ、一つ面白いのが見つかりました。
DotNetBrowser というChromium ベースのBrowserコントロールが TeamDev 社から提供されてたので、早速これを試してみたいと思います。
続きを読むQ127. WebBrowser コントロールの IE のバージョンを最新にしたい
A.WPF の WebBrowser コントロールのIEのバージョンが 7 なのは有名なようですね。現状ではレジストリを編集するしか手はないようです。以下の記事では、レジストリの編集方法を紹介されてます。
関連記事:WebBrowser コントロールで使われている Internet Explorerを最新のバージョンに変更する
関連記事:WPFのWebBrowserで使用されるIEのバージョンを最新にする
しかしレジストリをいちいち編集するのは気が重いし気持ち悪い。もうちっと何とかならんものかねぇ。。。
Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する(其の弐)
A.以前のエントリで、XamDataGrid で絞り込み表示されてるレコードのみ抽出する方法を紹介しましたが、これ一つ落とし穴がありまして、要素の描画タイミングによるのか、正常にレコードを取得できない場合があったりします。
関連記事:Q124. XamDataGrid で絞り込み表示されてるレコードのみ抽出する
例えば、XamDataGrid でフィルタリング実行時のイベント内で、絞り込まれたレコードのみ抽出したい場合、こんなコードになるかと思います。
レコード数やフィールドの少ない簡単な画面ならこれでも問題ありません。ところがレコード数が多かったり、フィールドが多いと、実際の表示と返されるレコードが異なる場合があることが判明しました。恐ろしいですね(汗
Dispatcher を使ってみる
この現象、どうやらレコードやフィールドが多すぎるか、ビューが複雑だと、フィルタリングと要素の描画更新のタイミングがずれるため発生するように思えます。そこで Dispatcher を使い、要素の描画とレコードの取得を同期するようタイミングを調整してみました。
これで、表示されてるレコード数とプログラム内で処理するレコード数の同期は取れました、ただし、状況により恐ろしい事態が発生します。フィルターのテキストボックスに文字列打ち込んでると、たまに
別のユニットが既に開いている間は、undo ユニットを再度開くことはできません。
と、InvalidOperationException 例外を吐いて、アプリケーションがクラッシュします。.NET Framework のソースコード追っかけると、UndoManager の Reopen メソッドで例外起こしてるのですが、恐ろしいですね。危険極まりないので、やみくもに Dispatcher を使うのは止めましょうw
RecordFilter.ApplyPendingFilter メソッド
そこで散々調べた結果*1、RecordFilter.ApplyPendingFilter メソッドを使えば、安全にフィルターの変更をビューに適用できることが判りました。以下、修正したコードです。
RecordFilter.ApplyPendingFilter の解説を読むと、
フィルターの保留中の変更を適用します。
としか書いてないしネットの情報も殆どないので、何のこっちゃ?と思ってたのですが、今回初めて使ってみました。果たしてこれが本来の使用方法かどうか怪しいのですが、とりあえず正常動作してるので、まあ良しといたしましょう(汗
Q126. XamDockManager のレイアウトを保存・読み込み・初期化したい
A.XamDockManager はペインを一元管理できるコントロールでして、ペインのドッキングやフローティング、タブや左右・上下の配置などを自在に配置可能なコンテナコントロールです。Visual Studio のIDE をイメージすれば判りやすいと思います。
ユーザーがペインを自由に配置できるとあれば、当然レイアウトを保存・読み込みしたいというニーズも出てきますね。XamDockManager ではレイアウトの保存・読み込みに LoadLayout・SaveLauout・というメソッドが用意されてます。
サンプルコード
以下、簡単なサンプルを用意しました。XamDockManager のレイアウトの保存・読み込み・初期化するサンプルです。以下の画面は上の画面と同一のものですが、クライアントがレイアウトを変更したものになります。
まずビューです。
お次はコードビハインドです。LoadLayout・SaveLayout の両メソッドで簡単に設定できるのが理解できると思います。レイアウトの状態をファイルに保存するには、オーバーロードされたメソッド(ストリームをパラメータで扱うバージョン)を使えば、簡単に保存できます。
初期化に関しては XamDockManager 側でメソッドが用意されてないため、ContentRendered イベントで要素が初期化されたタイミングを見て、SaveLayout メソッドで初期状態を保存。初期化ボタンクリック時に LoadLayout でXML文字列を読み込んでます。
Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の参)
A.以前、XamDataGrid でユーザーが操作した列の移動や並び替え、グループ化やソートを次回起動時用に保存したい場合、SaveCustomizations メソッドやLoadCustomizations メソッドを使えば、レイアウトの保存・読み込みが可能だという記事を公開しました。
関連記事:Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい
しかし記事の最後に書いたとおり、ClearCustomizations メソッドでフィールドを初期状態に戻そうとすると
- フィールドの表示状態を初期化できない
- フィールドの固定がリセットされてしまう
という問題が発生するため、昨日のエントリでは、その対処としてコンストラクタでフィールドの状態を保存し、ClearCustomizationsメソッド実行後、LoadCustomizations メソッドで表示と固定列を初期化する方法を紹介しました。以下、その対処法の記事になります。
関連記事:Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の弐)
カスタムXamDataGrid
上記で一見解決できたように思えましたが、複雑なUIに配置されたグリッドや、TabItem に配置され起動時に非表示になってるグリッドは、コンストラクタや 画面のContentRendered イベント、いや XamDataGrid のOnRender でもフィールドが生成されてない場合があり、列情報を取得できないことがあることが判りました。
結局、DataPresenterBase.FieldLayoutInitialized イベントの通知後でないと、フィールドの初期状態を正確に取得することはできない模様です。
そこで Window のコードビハインドでいちいちイベント書くのも煩わしいため、XamDataGrid をカスタマイズした方が早いという結論に達しました。それがこちら。
コントロールの継承って好きじゃないですが、今回のケースでは止むを得ません。以上、何かの参考になりましたら幸いです。
Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい(其の弐)
A.以前、XamDataGrid でユーザーが操作した列の移動や並び替え、グループ化やソートを次回起動時用に保存したい場合、XamDataGrid.SaveCustomizations メソッドやXamDataGrid.LoadCustomizations メソッドを使えば、レイアウトの保存・読み込みが可能だという記事を公開しました。
関連記事:Q110. XamDataGrid でユーザーが設定したレイアウトを保存したい
しかしこれ、ひとつ問題がありまして、記事の最後に書きましたが
なお上記一連のメソッドの問題点ですが、FieldLayoutSettings で HeaderPrefixAreaDisplayMode プロパティを FieldChooserButton に設定しフィールドの表示項目を選択できるようにした場合、フィールドの表示/非表示の設定を保存したり、非表示にしたフィールドを ClearCustomizations メソッドで復帰することはできません。現状、表示状態の保存は独自に実装するしかないので、この辺りもう少し何とかして欲しいところです。
また、ClearCustomizations メソッドで FieldPosition を初期化すると、FixedLocation=FixedToNearEdge にしたフィールドが FixedLocation=None になってしまうのも問題です。
という悩ましい問題が存在します。
これ、いったいどういう処理を行ってるのか、幸い Infragistics WPF はソースコードが公開されてる*1ので読んでみました。DataPresenterBase.ClearCustomizations → CustomizationsManager.ClearCustomizations → FieldLayout.ClearCustomizations と遡ってコードを追ってくと、大元の FieldLayout.ClearCustomizations で Visiblity プロパティを初期化してないため、どうにもならんという結論がでました。*2
だめだこりゃ\(^o^)/*3
FieldChooser 対応版
そこで私は考えた。画面初期化時にField の情報をメンバ変数に保持し、いったん LoadCustomizations で読み込んでから ClearCustomizations メソッドを実行すればいいのではと・・・で、以下サンプルです。
まずビュー。
お次はコードビハインドです。Reset_Click メソッドに注目してください。
LoadCustomizations で十分では?と思う向きもおられるかもしれません。しかし列の移動や段組が初期化されないため、まず全プロパティを初期化した後、表示と列固定を初期状態に戻します。これで前回の宿題は解決しましたが、これに気づくまで3年かかりましたw