愚痴のような駄文、失礼しました。後日、API騒動で再びTwitterユーザー間で再燃しているMastodon関連についての記事も書きます。a32kitaXAMLはWPFアプリケーションの開発において、UIのデザインや複数のコントロールなどで利用する背景デザインなどをまとめたResourceDictionaryを記述す際に利用するマークアップ言語です。本記事では、通常、クラスライブラリには追加できないResourceDictionaryなどのXAML定義ファイルを追加し、またこれをUserControlのXAMLから利用したり、C#のコード上でResourceDictionaryをロードする方法を紹介致します。Studioでプロジェクトを作成する際、クラスライブラリを選択すると追加項目の一覧に「ResourceDictionary」の項目が表示されません。クラスライブラリで追加可能なWPF関連項目クラスライブラリとして作成したプロジェクトとは別に「WPFアプリ」としてソリューションを作成し、その中で作成したResourceDictionaryのXAMLファイルをコピーする方法などもあるかと思います。本記事では、テキストファイルとしてプロジェクトに追加した項目をResourceDictionaryなどを定義可能なXAMLの項目へ変更する方法をご紹介致します。(1)参照の追加ResourceDictionary型をはじめとするWPF関連の型が定義されているアセンブリや、XAMLを扱う上で必要になる各種機能を提供してくれるアセンブリを参照に追加する必要があります。以下の項目をプロジェクトの参照に追加して下さい。テキストファイルの追加まず、クラスライブラリのプロジェクトへ「テキストファイル」を追加します。その際、ファイル名を「***.xaml」という形で拡張子を「xaml」にします。無効なマークアップ追加すると、「無効なマークアップ」というエラーがデザイン画面に表示されます。拡張子を「txt」のまま追加した場合、通常のテキストエディタモードでファイルが開かれてしまいます。その際は、拡張子を修正した後、項目のプロパティを以下に示した図のように変更して下さい。Studioで編集する際は,XAML専用のモードで開かれ,また,ビルド時にはXAMLの定義データとして正しくビルドされるようになります.(4)XAMLの記述あとは、通常通りResourceDictionaryを定義していきます。図4に示したとおり、XAMLファイルのビルドアクションは「Page」に設定する必要があります。このPageについて解説をば。XAMLの記述によって定義されたデータは、ビルド時に特殊な処理が行われます。XAMLの扱いXAMLファイルは通常のC#コードとは違い、ILコードには変換されません。出力されたアセンブリをildasmで定義したResourceDictionaryなどを探してみると、クラスとして扱われていないのがわかるかと思います。※UserControlやWindowなどのXAML定義はロード用・コード記述用のクラスが作成されます。XAMLはビルド時に「BAML」というXAMLを読み込みやすくバイナリデータ化したものに変換され、出力されるアセンブリに格納されます。その際変換元となったXAMLファイルに基づき、BAMLデータにも識別名が振られるようです。これは実行時にBAMLからインスタンスを作成する際に利用しますが、詳細については後述します。その「BAMLへ変換,並びにBAMLデータのアセンブリへの埋め込み」という指示を表しているのがビルドアクション「Page」のようです。余談ですが、XAMLとBAML、実行時に生成されるインスタンスは次のような処理関係になります。XAML、BAML、インスタンスの関係XAMLデータをファイルなどのStreamから読み込んでインスタンスを生成する「XamlReader」というクラスが実は存在しております.しかし後でも触れますが,XAMLなどをはじめとするXMLデータのパース及びロードには実行コストが発生します.ビルド時に予め,XAMLを読み込みやすいBAMLに変換することで,実行時に余計なロードコストが発生することを防いでいるようです.XAMLをC#コードに変換して,そのあとに通常のコードと一緒にILにコンパイルするような仕組みを取っていると思っていたのですが,そうではなかったんですね...XAMLを利用する(XAML)UserControlなどのXAMLで、定義したResourceDictionaryを利用する場合は図7のように記述します。ResourceDictionaryの参照ResourceDictionaryのプロパティ「Source」にXAMLのUriを指定することで参照することが可能です。XAMLのUriについては、後述の「XAMLを参照する際のUriについて」をご覧ください。ソリューションをビルドするまでは、ResourceDictionaryの定義内容がUserControlのデザイナに反映されない場合がございます。UserControl内で定義したResourceDictionaryと合わせて利用したい場合は、新しくResourceDictionaryを作成し、MergedDictionariesで追加してあげると良いでしょう。UserControlで定義したResourceDictionaryと合わせて利用するXAMLを利用する(C#コード)XAMLで定義したResourceDictionaryなどをC#のコード上で利用したい場合は、まずロードしてインスタンスを作成する必要があります。メソッドを利用します。UriKind.Relative));LoadComponentメソッドは指定したUriのXAMLをロードしてインスタンス化してくれるメソッドです。戻り値はObject型になっておりますが、例えば、ResourceDictionaryを定義したXAMLをロードした場合は、そのままResourceDictionaryにキャストすることが可能です。このとき指定するUriについては、後述の「XAMLを参照する際のUriについて」をご覧ください。【解説】XAMLを参照する際のUriについてXAMLの定義を利用するためには、XAMLのUriを指定して、ロードする必要があります。Uriは通常Web上のコンテンツやローカルファイルのパスなどを指定する際に用いる型ですが、どうもWPFではアセンブリ内に格納された特殊なリソースを参照する際にも利用可能なようです。その際のUriは文字列から初期化しますが、構文は次のとおり。[アセンブリ名];component/[プロジェクト内でのパス(すべて小文字で)]アセンブリ名は、恐らく出力アセンブリファイル名かプロジェクト名がこれに該当するのですが、通常はこの2つは一致するため、どちらが正解かは未検証です。プロジェクト内でのパスも実際のcsprojファイルからの相対パスになるのか、あるいはcsproj内での論理パスになるのかは未検証です。既存のXAMLファイルをリンクで取り込んだ際は注意が必要です。前述のサンプル「SampleClassLibrary」ではプロジェクトのルートに「SampleResources.xaml」を追加しました。これを参照する際のUriはSampleClassLibrary;component/sampleresources.xamlになります。プロジェクト内で「SampleDir」というディレクトリを作成し、その中に「Hoge.xaml」を定義した場合のUriはSampleClassLibrary;component/sampledir/hoge.xamlになります。この辺は、通常のUserControlに対してVisualStudioが自動生成したラッパクラスの中身を見ただけなので、もっと深く調べる必要がありそうですね。余談「ControlTemplateをXAMLで定義してみた」コードから参照して利用する場合、ResourceDictionary以外でもXAMLに定義することが可能です。ControlTemplateを定義してみた例ControlTemplateは、XAMLで記述する場合、XAMLからのロードの都合もあり、通常はResourceDictionary内で定義しますが、ControlTemplateをコードから呼び出して利用したい状況が発生しましたので、ResourceDictionaryを省略して直接定義してみました。正攻法とは言えないでしょうが、ControlTemplateを直接XAMLで定義すると、デザイナが仕事をしてくれるんですね。便利かも(?)ちなみに、サンプルイメージの配色がTheドイツ国旗って感じですが、実験用にわかりやすい配色がないか考えたら偶然ドイツ国旗が頭をよぎっただけです。ドイツ国旗シンプルでかっこいいですけど、それをイカしたUIに活用するだけのデザイン力は僕にはありません。あ、ちなみにドイツ国旗の3色のうち一番下の部分って黄色じゃなくて正確には金色みたいですね。余談「Application.LoadComponentとXamlReader」ぶっちゃけ頑張ってBAMLとしてアセンブリに挿入させることにこだわらずとも、リソースとしてぶちこんだXAMLファイルを実行時にXamlReaderでLoadしちゃうなんて手もなくはないです。いうか、この方法を思いつかなかった時は、そうしていました。通常のリソースとしてXAMLデータを添付した場合、若干ちゃんとBAMLに変換させたときよりも時間がかかるようです。BAMLってのはビルド時にXAMLを読み込んで最適化した結果なのですから。あとファイルサイズが変わります。BAMLのほうがファイルサイズ小さいです。リソースとしてXAMLファイルを取り込むとXAMLのソースがそのまま出力ファイル内に取り込まれます。テキストエディタでバイナリを眺めるという意味不明な習性を持っている僕と致しましては、圧倒的にBAMLのほうがかっこいいバイナリになります(意味不明)では。Viewerのバージョン0.9.3.31を公開しました。取得したハンドル情報、プロセス情報をデスクトップのプレビュー情報とともにファイルへ保存する機能、またはこれをファイルからロードする機能を実装しました。0と1の世界の見習い探検家http://www.a32kita.tk/software/winhandlevw/では。