.xaml.cs
ファイルには、コンパイル済みのXAMLファイルをサポートするクラスがpartial
クラスとしてマークされていることがあります。 XAMLビルドタスクは、IComponentConnector.InitializeComponent()
メソッドの実装を含む別の部分クラスセクションを含む2番目の.cs
ファイルを生成します。これはコードの背後にあるデフォルトのコンストラクタによって呼び出されます。このメソッドは、XAMLソースから新しいオブジェクトを作成するのではなく、新しく作成されたオブジェクトを「修正する」ために、基本的にはXAML(現時点ではBAML形式です)を使用して実行されます。オブジェクトをロードまたは解析するためにXamlReader
を使用しました。
したがって、コンパイル済みの新しいXAMLオブジェクト(たとえば、UserControl
)をインスタンス化すると、コンストラクタ内のInitializeComponent()
への呼び出しに先行するコードが実行されます。次に、XAMLファイルに設定されているすべてのプロパティとイベントハンドラは、InitializeComponent()
の呼び出し中に処理されます。その後、コンストラクタが再開されます。これは、XAMLファイルが処理される前または後に特定のプロパティが設定されるようにするために便利です。
XAMLがどのように解析されるかは、サービスによって順番にプロパティ割り当て、オブジェクト宣言などを表すXAMLノードのストリームとして読み取られます(System.Xaml
)。このノードストリームは、BAMLストリーム、XML文書(緩い.xaml
ファイルなど)、別のオブジェクトインスタンスなどから構築された共通オブジェクトモデルに基づいています.BAMLはXMLベースの形式よりもコンパクトです一般に解析する方が高速です。
補遺:あなたは追加の例では、あなたはパーサがButton
オブジェクトを作成する必要があることを認識し、Margin
セット方法を尋ねます。短い答えは:それは依存しています。具体的には、XAMLストリームの読み込みに使用されるスキーマコンテキストに依存します。
XAMLパーサーは、少なくとも2つの実装があり、そのうちの独自のタイプのシステムを使用する:
- 反射及び
System.ComponentModel
に基づく標準CLR型システムは、
- 依存関係のプロパティとルーティングされたイベントを特別にサポートすることで#1を拡張するWPFタイプのシステム。
これは、XAML言語仕様の私の記憶に基づいて、おおよそ何が起こる、次のとおりです。
- をXAMLパーサーは、(標準WPF名前空間のマッピングのために)これ、
Button
タイプにStartObject
ノードに遭遇System.Windows.Controls.Button
に解決されます。これはパーサーに、Button
オブジェクトのインスタンスを作成する必要があることを伝えます。これは、リフレクションによってデフォルトのコンストラクタを呼び出すことによって行われます。
- ストリームの次のノードは
StartMember
ノードであり、メンバー名はMargin
です。 WPFスキーマコンテキストの型モデルは、これをMargin
依存プロパティに解決します。
Value
ノードが次に来ます。これは、パーサーに"10"
(文字列)の値を設定するように指示します。パーサは、プロパティタイプThickness
が文字列値と互換性がないことを確認します。文字列の変換に使用できるMargin
プロパティに[ValueSerializer]
属性が存在するかどうかを調べるために型システムを調べます。そのような属性は存在しません。プロパティーで[TypeConverter]
属性をチェックします。もう一度、それは何も見つけません。これは、タイプ自体の[TypeConverter]
属性を検索し、ThicknessConverter
を使用して文字列値をThickness
に変換するよう指示します。そうです。 Margin
は依存関係プロパティであるため、SetValue()
APIを使用してプロパティ値を設定します。 CLRプロパティの場合は、リフレクションまたはPropertyDescriptor
を使用します。
EndMember
ノードは、プロパティの割り当てを終了するようにパーサに指示します。
- パーサーは
"OK"
という内容のValue
ノードを検出します。パーサーは複合オブジェクトを構成していることを知っているので、コンテンツはオブジェクト全体を表すことができません。 Button
とそのスーパータイプの[ContentProperty]
属性を探します。 ContentControl
にある値を見つけます。これは、Content
プロパティ(対応する依存関係プロパティに解決されます)を設定するために値を使用する必要があることを示します。 Content
はobject
であるため、string
の値が直接割り当てられます(再びSetValue()
を使用)。
- 次のノードは
EndObject
です。これは、パーサーにButton
オブジェクトの処理を終了したことを通知します。
私は事を単純化するために "パーサー"という用語を使用しました。実際には、解析の段階でこのようなことは起こりません(「解析」段階が存在する場合でも)。 「解析」段階と考えることができるのは、XAMLノードのストリームの構築だけです。宣言されたオブジェクトの作成および/または作成は、そのストリームをXamlObjectWriter
に入力することによって実際に発生します。XamlWriter
の実装は、(XMLドキュメントまたはBAMLストリームではなく)オブジェクトにXAMLノードを書き込みます。高レベルでは、起こるのは2つだけです:
XamlReader
何かがXAMLノードのストリームに変換されます。
XamlWriter
は、XAMLノードのストリームを何かに変換します。 compled XAMLリソースの場合
、コンパイル時ビルドタスクパイプBamlWriter
にXamlXmlReader
の出力は、XAMLを「コンパイル」します。実行時にBamlReader
の入力はXamlObjectWriter
にパイプされ、ルートオブジェクトを作成または修正します。
これを理解したら、UIを構築するための単なる言語ではなく、強力なシリアライズと永続化形式としてXAMLを認識することができます。
マイク、ありがとうございました。あなたの補遺は私が必要としたものです。そのため、WPFエンジンでオブジェクトツリーを構築するには、Buttonオブジェクトを作成し、使用するTypeConverterを見つけ出し、TypeConverterを構築し、Marginが依存関係プロパティであることなどを確認してください。 – WpfNewbie
はい、XAMLタイプのシステムでは、多くのことが反映されています。 –
偉大な答え! – nawfal