2021年11月

XAML を動的に読み込むサンプルプログラム 【C#/WPF/MVVM】

Runプログラム実行時に XAML を読み込んで UI コントロールを生成する方法のまとめ。

「タブを増やす」ボタンをクリックするたびにタブが増えていく。

サンプルプログラムは GitHub にて:
Visual Studio 2022 / .NET 6 で動作確認。

大まかな手順

STEP 1:XAML 作成

UserControl動的に生成したいコントロール(DynamicTabItem.xaml)をユーザーコントロールとして作成する。

以下の 3 つの作業を行う。

[A]
UmekomiDynamicTabItem.xaml ファイルのプロパティーでビルドアクションを「埋め込みリソース」にする。

[B]
csDynamicTabItem.xaml に紐付いている DynamicTabItem.xaml.cs を削除する。

[C]
xClassDynamicTabItem.xaml の先頭に記述されている x:Class の記述を削除する。

STEP 2:動的読み込み

リソースから DynamicTabItem.xaml を読み込み、XamlReader でコントロール化する。ButtonAddTabItemClicked() 参照。

注意点

動的に読み込む XAML 内の名前空間は、アセンブリを指定する必要がある。指定が無いと XamlReader が例外を吐く。

例えば、ビューモデルの名前空間は
xmlns:vm="clr-namespace:TestXamlReader.ViewModels"
ではなく
xmlns:vm="clr-namespace:TestXamlReader.ViewModels;assembly=TestXamlReader"
とする。

(補足)
別のプロジェクトで、assembly を指定するとビルド時に MC3074 エラー「タグ 'XXX' は、XML 名前空間 'clr-namespace:YYY;assembly=ZZZ' にありません。」が発生したことがあった。
対処方法が分からず、xaml 上では assembly を指定せず、実行時に文字列置換で assembly 指定を追加することで凌いだことがある。

サードパーティーの名前空間を使いたい時も同様で、サンプルプログラムでは GongSolutions.WPF.DragDrop の添付プロパティーを使っているが、
xmlns:dd="urn:gong-wpf-dragdrop"
ではなく
xmlns:dd="clr-namespace:GongSolutions.Wpf.DragDrop;assembly=GongSolutions.Wpf.DragDrop"
とする。


ちょちょいと自動更新 2 Ver 1.03 公開

CUpdater2_Ask開発者向けツール「ちょちょいと自動更新 2」を新たに公開。

初代ちょちょいと自動更新の後継となるツールで、アプリケーションの最新情報の取得や自動更新を行える。初代は .NET Framework を使用していたが、2 では .NET 6 となった。また、外観もモダンになっている。
なお、ゆかりすたー NEBULA の更新ツールは既に初代から 2 に移行済。

async / await の実行タイミングを追う 【C#】

C# のお手軽非同期プログラミング、async / await。

概念なり捉え方なりについては Taskを極めろ!async/await完全攻略を初めとした親切丁寧な記事があって、ふむふむなんて思っていたのだが、たまに、async / await してるのに妙に UI がフリーズしてないか、みたいな時があった。

そこで、async / await の実行タイミングを追うためのテストプログラムを作ってみた。
async な関数の中でさらに async な関数を呼びだして、それをいくつかのパターンでやってみた結果、たぶん実行タイミングのイメージは以下のような感じなのかなと。
Matome


SomeAsync() の中では Task.Run() しているわけではないので、直ちに非同期処理になるわけではなく、Code P~R は順次実行される。ここが重いと UI がフリーズする。

await に到達した段階で、それ以降 Code U までをタスクとして返す。仮に AnotherAsync() の中で Task.Run() していると、その部分は非同期に処理されるので、重くても UI はフリーズしない(テストプログラムでは Web から文字列を読み込む部分が非同期に処理される)。

メインルーチンに注目すると、よくあるのは
await SomeAsync();
で直ちに await するパターンだが、上図のように await を後ろまで引っ張ると、await まではすぐに実行される。await に到達した段階で、Code U までのタスクが終了するのを待つ。

~Async() の中ではひたすら Task.Run() すれば UI はフリーズしないが、他の async を呼ぶために async にしている場合は、その他のコードが重くないか考える必要がある。

ちなみに Code S~U が重い場合は、メインルーチンで await task している時に UI がフリーズする。

……っていう感じで合っているだろうか?

ゆかりすたー NEBULA Ver 4.60 公開

460ゆかりすたー NEBULA Ver 4.60 を公開しました。

ゆかりすたー NEBULA(ネビュラ)はカラオケ動画ファイルを整理し、ゆかり(持ち込みカラオケ用のブラウザリクエストツール)から検索できるようにするツールです。データベースを活用することにより、タイアップしている番組名や歌手名などの付加情報を含めて整理します。

詳細については、ファンクラブサイト「Fantia」内の記事をご覧ください
月別アーカイブ
記事検索
最新コメント
  • ライブドアブログ