XAML 構文用語
更新 : 2007 年 11 月
ここでは、Extensible Application Markup Language (XAML) 構文の要素を説明するために使用される用語を定義します。これらの用語は、このソフトウェア開発キット (SDK) の残りの部分を通じて頻繁に使用されます。このトピックの内容は、「XAML の概要」で紹介した基本的な用語の詳細な説明になります。
このトピックには次のセクションが含まれています。
- XAML 構文用語の起源
- オブジェクト要素の構文
- 属性構文
- プロパティ要素の構文
- XAML コンテンツ構文
- 添付プロパティ
- 接続されたイベント
- XML 名前空間
- マークアップ拡張
- 推奨されないオプションの XAML 使用方法
- 関連トピック
XAML 構文用語の起源
ここで定義されている XAML 構文用語は、XAML 言語仕様の中でも定義または参照されています。XAML は XML に基づく言語であり、XML の構造の規則に従っています。ここで紹介する用語の中には、XML 言語や XML ドキュメント オブジェクト モデル (DOM) の説明によく使用される用語と共通の用語や、それらに基づいている用語もあります。
オブジェクト要素の構文
オブジェクト要素構文は、XML 要素を宣言することによって共通言語ランタイム (CLR) のクラスや構造体をインスタンス化する XAML マークアップ構文です。この構文は、HTML などの他のマークアップ言語の要素構文に似ています。オブジェクト要素構文は、始め山かっこ (<) で始まり、インスタンス化するクラスや構造体の型名がその後に続きます。型名の後には 0 個以上の空白を含めることができます。また、オブジェクト要素で 0 個以上の属性を宣言することもできます。各属性の 名前="値" のペアは、1 つ以上の空白で区切ります。最後に、次のいずれかが満たされている必要があります。
要素とタグは、スラッシュ (/) とそれに続く終わり山かっこ (>) で終了している必要があります。
開始タグは、終わり山かっこ (>) で終了している必要があります。開始タグの後には、他のオブジェクト要素、プロパティ要素、または内部テキストを含めることができます。実際にここに含めることができる内容は、通常、要素のオブジェクト モデルによって制限されます。詳細については、このトピックの「XAML コンテンツ構文」を参照してください。そのほか、オブジェクト要素の対応する終了タグが、他の開始タグ/終了タグのペアとの入れ子の関係やバランスが正しい状態で存在している必要もあります。
たとえば、次の例は、Button クラスの新しいインスタンスを作成するオブジェクト要素構文です。Name 属性と、この属性の値も指定されています。
<Button Name="CheckoutButton"/>
次の例のオブジェクト要素構文には、Extensible Application Markup Language (XAML) コンテンツ プロパティ構文も含まれています。中に含まれている内部テキストは、TextBox の Extensible Application Markup Language (XAML) コンテンツ プロパティである Text を設定するために使用されます。
<TextBox>This is a Text Box</TextBox>
属性構文
属性構文は、要素の属性を宣言することによってプロパティの値の設定やイベントのイベント ハンドラの指定を行うことができる XAML マークアップ構文です。要素は常にオブジェクト要素構文によって宣言されます。属性名は、プロパティまたはイベントの CLR メンバ名と一致している必要があります。属性名の後には、代入演算子 (=) が続きます。属性値は、2 つの引用符 (") で囲まれた文字列である必要があります。
属性構文で設定するプロパティは、パブリックの読み書き可能なプロパティである必要があります。また、プロパティ値は、XAML プロセッサによるインスタンス化または参照が可能な型である必要があります。イベントの場合は、パブリック デリゲートを持つパブリック イベントである必要があります。プロパティやイベントは、格納オブジェクト要素によってインスタンス化されるクラスまたは構造体のメンバである必要があります。
属性値は、次のいずれかの方法で、次の処理順序を使用して設定されます。
XAML プロセッサで中かっこ (MarkupExtension から派生しているオブジェクト要素) が検出された場合は、属性値を文字列として処理する代わりに、参照されているマークアップ拡張機能が先に評価されて、そのマークアップ拡張機能によって返されたオブジェクトが使用されます。マークアップ拡張機能によって返されるオブジェクトは、多くの場合、既存オブジェクトへの参照か、実行時にならないと評価されない式であり、新しいオブジェクトではありません。
プロパティの宣言で TypeConverter が指定されている場合や、そのプロパティの値型の宣言で TypeConverter が割り当てられている場合は、属性の文字列値が変換の入力としてその型コンバータに送られて、コンバータによって新しいオブジェクト インスタンスが返されます。
TypeConverter がない場合は、プロパティ型への直接変換が試行されます。この最後のレベルは、プリミティブ型間の直接変換か、列挙型の名前のチェックになります (一致する値が返されます)。
たとえば、前と同じマークアップを使用した次の例では、Name プロパティに文字列値を割り当てるために属性構文が使用されています。
<Button Name="CheckoutButton"/>
Name プロパティは、Button クラスのメンバ テーブルのメンバです。Button は、Name を定義している FrameworkElement クラスの派生クラスです。
属性値の処理
始まりと終わりの引用符で囲まれた文字列値は XAML プロセッサによって処理されます。プロパティに対する既定の処理動作は、基になる CLR プロパティの型によって決まります。プロパティがプリミティブ型の場合は、文字列から適切なプリミティブ型への暗黙の型変換に基づいて属性値が割り当てられます。プロパティが列挙型の場合は、その列挙型で定義されている名前として文字列が扱われ、列挙型の一致する値が返されます。プロパティがプリミティブ型でも列挙型でもない場合は、プロパティ自体または変換先の型で宣言されている型コンバータによって、属性値が処理される必要があります。その型コンバータが提供する変換では、文字列を受け取って、基になる CLR プロパティの型のインスタンスを返す必要があります。この変換のステップは、マークアップ拡張機能によって延期することもできます。
列挙体の属性値
XAML の列挙値は、Enum 構造体のネイティブ メソッドによって組み込み処理されます。
フラグではない列挙値については、属性値の文字列を処理して、いずれかの列挙値に解決するというのがネイティブな動作です。列挙体を指定する方法は、コードで使用するような Enumeration.Value という形式ではありません。Value のみを指定します。Enumeration は、設定するプロパティの型に基づいて推論されます。属性を Enumeration.Value という形式で指定した場合、正しく解決されません。
フラグ列挙体については、Enum.Parse メソッドに基づく動作になります。フラグ列挙体に対しては、コンマ区切りで複数の値を指定できます。一方、フラグ列挙体でない場合は、複数の列挙値を組み合わせることはできません。たとえば、コンマ構文を次のように使用して、フラグでない列挙体の複数の条件に対処する Trigger を作成することはできません。
<!--This will not compile, because Visibility is not a flagwise enumeration.-->
...
<Trigger Property="Visibility" Value="Collapsed,Hidden">
<Setter ... />
</Trigger>
...
XAML で設定できる属性をサポートするフラグ列挙体は、WPF にはあまりありません。しかし、そんな列挙体の一例が StyleSimulations です。たとえば、コンマ区切りのフラグ属性の構文を使用して、Glyphs クラスの「解説」で示した例を修正することも可能です。その場合、StyleSimulations = "BoldSimulation" が StyleSimulations = "BoldSimulation,ItalicSimulation" のようになります。また、KeyBinding.Modifiers も、複数の列挙値を指定できるプロパティです。ただし、このプロパティは特殊なケースです。ModifierKeys 列挙体は独自の型コンバータをサポートしているためです。この変換キー用の型コンバータでは、コンマ (,) ではなく正符号 (+) を区切り記号として使用します。このため、キーの組み合わせを表すときに慣習的に用いられる構文 ("Ctrl+Alt" など) がマークアップでサポートされています。
プロパティおよびイベントのメンバ名の参照
属性を指定するときには、格納オブジェクト要素のためにインスタンス化した CLR 型のメンバとして存在する任意のプロパティやイベントを参照できます。
また、格納オブジェクト要素とは関係なく、添付プロパティや添付イベントを参照することもできます。
その他、typeName.event 部分修飾名を使用して、既定の名前空間からアクセスできる任意のオブジェクトの任意のイベントを指定することもできます。この構文では、ルーティング イベントのハンドラをアタッチできます。これにより、子要素からルーティングされたイベントが親要素のメンバ テーブルにもなかった場合に、そのイベントを処理できます。この構文は添付イベントの構文に似ていますが、この場合のイベントは本当の添付イベントではありません。この場合は、イベントを修飾名で参照しています。詳細については、「ルーティング イベントの概要」を参照してください。
属性名としてではなく属性の値としてプロパティ名が指定される場合もあります。そのプロパティ名に修飾子を含めることもできます (ownerType.dependencyPropertyName の形式で指定されるプロパティなど)。これは、XAML でスタイルやテンプレートを作成するときの一般的なシナリオです。属性値として指定したプロパティ名にはまた別の処理規則が適用され、設定するプロパティの型やコンテキストの要因 (スタイルやテンプレートに対象の型があるかどうかなど) によって制御されます。詳細については、「スタイルとテンプレート」を参照してください。
そのほか、プロパティ名は、属性値でプロパティ間のリレーションシップを記述する場合にも使用されます。この機能は、データ バインディングやストーリーボード ターゲットのために使用されるもので、PropertyPath クラスとその型コンバータによって実現されます。検索セマンティクスの詳細については、「PropertyPath の XAML 構文」を参照してください。
プロパティ要素の構文
プロパティ要素構文は、基本的な XML 構文からやや逸脱した構文です。XML では、属性の値は事実上の文字列であり、変更できるのは使用する文字列エンコードの形式だけです。XAML では、他のオブジェクト要素をプロパティの値として割り当てることができます。これを実現するのがプロパティ要素構文です。プロパティを要素タグ内の属性として指定する代わりに、elementTypeName.propertyName という形式の開始要素タグを使用して指定します。後は、プロパティの値を指定して、最後にプロパティ要素を閉じます。
具体的に言うと、この構文は始め山かっこ (<) で始まり、プロパティ要素構文を含むクラスまたは構造体の型名がその後に続きます。その後、1 つのドット (.)、プロパティの名前 (指定した型のメンバ テーブル内に存在する必要があります)、終わり山かっこ (>) が続きます。プロパティに割り当てられる値は、プロパティ要素内に格納されます。プロパティ要素構文はオブジェクトを値として指定するシナリオで使用するものなので、この値は通常、1 つ以上のオブジェクト要素として指定されます。最後に、同じ elementTypeName.propertyName の組み合わせの対応する終了タグを、他の要素タグとの入れ子の関係やバランスが正しい状態で指定する必要があります。たとえば、次の例は、Button の ContextMenu プロパティのプロパティ要素構文です。
<Button>
<Button.ContextMenu>
<ContextMenu>
<MenuItem Header="1">First item</MenuItem>
<MenuItem Header="2">Second item</MenuItem>
</ContextMenu>
</Button.ContextMenu>
Right-click me!</Button>
プロパティ要素内の値を内部テキストとして指定することもできます。ただし、その場合は、指定されているプロパティ型がプリミティブ型 (String など) か、名前が指定されている列挙型である必要があります。この 2 つの使用方法は属性構文でもサポートされているため、一般的ではありません。プロパティ要素に文字列を設定するシナリオとしては、XAML コンテンツ プロパティ以外のプロパティを UI テキストの表示のために使用する場合に、その UI テキスト内にラインフィードなどの特殊な空白要素が含まれる場合などが考えられます。属性構文ではラインフィードは保持できませんが、プロパティ要素構文では保持できます。ただし、重要な空白の保持がアクティブになっている必要があります (詳細については、「XAML での空白の処理」を参照してください)。
プロパティ要素は、論理ツリーには表示されません。プロパティ要素は、プロパティを設定するための単なる構文であり、対応するインスタンスまたはオブジェクトを持つ要素ではありません。
コレクション型のプロパティ要素構文
XAML 仕様では、値型がコレクションのプロパティを XAML プロセッサの実装で識別できる必要があります。WPF の実装はマネージ コードに基づいているため、その XAML プロセッサは、次のいずれかの方法でコレクション型を識別します。
IList を実装します。
IDictionary を実装します。
Array から派生します (XAML の配列の詳細については、「x:Array のマークアップ拡張機能」を参照してください)。
プロパティの型がコレクションの場合、推定のコレクション型をマークアップで指定する必要はありません。代わりに、コレクション内の項目となる要素を、コレクション型プロパティ要素の 1 つ以上の子要素として指定します。それらの各項目が読み込み時にオブジェクトへと評価され、暗黙的なコレクションの Add メソッドの呼び出しによってコレクションに追加されます。たとえば、Style の Triggers プロパティは、特化されたコレクション型である TriggerCollection を受け取ります。しかし、TriggerCollection をマークアップでインスタンス化する必要はありません。代わりに、1 つ以上の Trigger 項目を Style.Triggers プロパティ要素内の要素として指定します。Trigger (または派生クラス) は、厳密に型指定された暗黙的な TriggerCollection の項目の型として想定されている型です。
<Style x:Key="SpecialButton" TargetType="{x:Type Button}">
<Style.Triggers>
<Trigger Property="Button.IsMouseOver" Value="true">
<Setter Property = "Background" Value="Red"/>
</Trigger>
<Trigger Property="Button.IsPressed" Value="true">
<Setter Property = "Foreground" Value="Green"/>
</Trigger>
</Style.Triggers>
</Style>
コレクション型のプロパティが、その型と派生型の XAML コンテンツ プロパティでもある場合もあります。
暗黙的なコレクション要素は、マークアップには要素として含まれませんが、論理ツリーのメンバは作成されます。通常は、所有する型のコンストラクタによって、そのプロパティの 1 つであるコレクションがインスタンス化されて、ツリーにコレクションが追加されます。
メモ : |
---|
ジェネリック リスト インターフェイスおよびジェネリック ディクショナリ インターフェイス (IList<T> および IDictionary<TKey, TValue>) は、WPF XAML プロセッサによるコレクション検出ではサポートされていません。一方、List<T> クラスおよび Dictionary<TKey, TValue> クラスを基本クラスとして使用することはできます。それぞれ、IList と IDictionary を直接実装しているためです。 |
XAML コンテンツ構文
XAML コンテンツ構文は、クラス宣言の一部として ContentPropertyAttribute が指定されているクラスでのみ有効な構文です。ContentPropertyAttribute は、その型の要素 (派生クラスを含む) のコンテンツ プロパティとして定義されるプロパティを名前で指定するパラメータを必要とします。このようにして指定されたプロパティが、要素の XAML コンテンツ プロパティになります。XAML プロセッサによる処理の際には、要素の開始タグと終了タグの間で検出されたすべての子要素や内部テキストが、その XAML コンテンツ プロパティの値として割り当てられます。必要に応じて、コンテンツ プロパティのプロパティ要素を指定し、そのマークアップを明示的にすることができます。この方法は、マークアップをわかりやすくするために、またはマークアップのスタイルとして有効な場合もあります。しかし通常、コンテンツ プロパティの目的は、マークアップを簡素化して、直感的に親子として関連付けられる要素を直接入れ子にできるようにすることです。要素に設定された他のプロパティのプロパティ要素タグは、"コンテンツ" として割り当てられることなく、パーサー ワークフローであらかじめ処理され、"コンテンツ" として認識されません。
他のプロパティと同様に、オブジェクトの XAML コンテンツ プロパティは特定の型を持ちます。その型を Object 型にすることもできます。コンテンツ プロパティの型は、オブジェクトのコンテンツ モデルを定義するうえで役に立ちます。たとえば、Object 型は、任意のオブジェクトがコンテンツになる可能性があるという意味で厳密ではありませんが、このように厳密でない型指定の場合でも、コンテンツは単一のオブジェクトに限定されます。その単一のオブジェクトがコレクション オブジェクトである可能性もありますが、その場合も、コンテンツに割り当てることのできるコレクション オブジェクトは 1 つだけです。
WPF のマニュアルでは、特定の型のコンテンツ モデルについて、その型のクラス ページで説明しています。型のグループの概念についてのトピックが個別にある場合もあります。その場合は、関連する各型のリファレンスにトピックへのリンクが含まれています。
コレクション型のコンテンツ構文
複数のオブジェクト要素 (または内部テキスト) をコンテンツとして受け入れるためには、コンテンツ プロパティの型はコレクション型であることが必要です。コレクション型のプロパティ要素構文の場合と同様に、XAML プロセッサによってコレクション型の型が識別される必要があります。要素に XAML コンテンツ プロパティがあり、その XAML コンテンツ プロパティの型がコレクションの場合、暗黙的なコレクション型はマークアップでオブジェクト要素として指定されている必要はなく、XAML コンテンツ プロパティもプロパティ要素として指定されている必要はありません。このため、マークアップの外見上のコンテンツ モデルでは、複数の子要素をコンテンツとして割り当てられるようになります。以下は、Panel 派生クラスのコンテンツ構文です。すべての Panel 派生クラスでは、XAML コンテンツ プロパティが Children として設定されています。Children は、UIElementCollection 型の値を必要とします。
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
>
<StackPanel>
<Button>Button 1</Button>
<Button>Button 2</Button>
<Button>Button 3</Button>
</StackPanel>
</Page>
Children のプロパティ要素も UIElementCollection の要素も、マークアップでは必要ないことに注意してください。これは、XAML のデザイン機能です。これにより、UI を定義する要素が再帰的に含まれる場合に、それらの要素を、不要なプロパティ要素タグやコレクション オブジェクトを間にはさまずに、直接の親子のリレーションシップを持つ入れ子になった要素のツリーとして、より直感的に表すことができます。実際、UIElementCollection をマークアップでオブジェクト要素として指定することは設計上できません。UIElementCollection は、暗黙的なコレクションとしてのみ使用されるものであるため、既定のパブリック コンストラクタは公開されていません。したがって、オブジェクト要素としてインスタンス化することはできません。
コンテンツ プロパティを持つオブジェクトでのプロパティ要素とオブジェクト要素の混合
XAML 仕様では、オブジェクト要素内の XAML コンテンツ プロパティを設定するために使用されるオブジェクト要素が、混合せずに連続するように XAML プロセッサで強制できることになっています。WPF XAML プロセッサでは、このプロパティ要素とコンテンツの混合に対する制限が適用されます。
子オブジェクト要素をオブジェクト要素内の最初の直接のマークアップにして、その後にプロパティ要素を導入することができます。また、1 つ以上のプロパティ要素を指定し、コンテンツを指定した後に、さらにプロパティ要素を指定することもできます。ただし、いったんコンテンツの後にプロパティ要素を指定したら、その後さらにコンテンツを導入することはできません。その後に追加できるのはプロパティ要素だけです。
このコンテンツとプロパティ要素の順序の要件は、コンテンツとして使用される内部テキストには適用されません。ただし、マークアップ スタイルの観点からは、内部テキストを連続した状態に保つことをお勧めします。内部テキストの中にプロパティ要素が混在していると、マークアップ内の重要な空白がわかりにくくなります。
添付プロパティ
添付プロパティは、XAML で導入されたプログラミング概念です。添付プロパティを使用すると、特定の型で所有および定義されているプロパティを、任意の要素で設定できます。添付プロパティは主に、要素ツリー内の子要素が、すべての要素の間で広範に共有されているオブジェクト モデルを使用しなくても、親要素に情報を報告できるようにすることを目的としています。逆に、親要素が子要素に情報を報告するために添付プロパティを使用することもできます。添付プロパティの目的と、独自の添付プロパティの作成方法の詳細については、「添付プロパティの概要」を参照してください。
添付プロパティの構文は、typeName.propertyName の組み合わせを指定するという点で、一見プロパティ要素構文に似ています。ただし、次の 2 つの重要な違いがあります。
属性構文で添付プロパティを設定するときにも typeName.propertyName の組み合わせを使用できます。属性構文でプロパティ名を修飾する必要があるのは添付プロパティの場合だけです。
添付プロパティに対してプロパティ要素構文を使用することもできます。ただし、一般的なプロパティ要素構文で指定する typeName は、プロパティ要素を含むオブジェクト要素ですが、添付プロパティを参照する場合は、typeName は、添付プロパティを含むオブジェクト要素ではなく、添付プロパティを定義しているクラスです。
接続されたイベント
添付イベントもまた、XAML で導入されたプログラミング概念です。添付イベントでは、イベントを特定の型で定義して、ハンドラを任意のオブジェクトにアタッチすることができます。添付イベントを定義する型は多くの場合、サービスを定義する静的な型です。それらの添付イベントが、サービスを公開する型でルーティング イベント エイリアスによって公開される場合もあります。添付イベントのハンドラは属性構文で指定します。添付プロパティの場合と同様に、添付イベントでは属性構文が拡張されて、typeName.eventName という使用方法が許可されます。typeName は、添付イベント インフラストラクチャの Add および Remove のイベント ハンドラ アクセサを提供するクラスです。eventName はイベントの名前です。
XML 名前空間
これまでに見てきた構文の例では、既定の名前空間以外の名前空間は指定されていません。一般的な WPF アプリケーションでは、既定の名前空間は WPF 名前空間に指定されます。既定の名前空間以外の名前空間を指定することもできます。その場合も、基本的に同じ種類の構文を使用できます。ただし、既定の名前空間ではアクセスできないクラスを指定する際には、クラス名の前に、対応する CLR 名前空間をマップするために使用された XML 名前空間のプレフィックスを付ける必要があります。たとえば、<custom:MyElement/> は、MyElement クラスのインスタンスを作成するためのオブジェクト要素構文ですが、このクラスを含む CLR 名前空間 (および、おそらくはその名前空間を含む外部アセンブリ) は、以前に custom プレフィックスにマップされています。
XML 名前空間と XAML の詳細については、「XAML 名前空間および名前空間の割り当て」を参照してください。
マークアップ拡張
XAML では、マークアップ拡張機能というプログラミング エンティティが定義されています。マークアップ拡張機能を使用すると、XAML プロセッサによる標準の処理を逃れて、対応するクラスに属性やオブジェクト要素の処理を委ねることができます。XAML プロセッサの WPF 実装では、WPF でサポートされているすべてのマークアップ拡張機能の基礎として、MarkupExtension 抽象クラスが使用されています。マークアップ拡張機能は属性構文で、終わり中かっこ (}) 以外の文字が後に続く始め中かっこ ({) によって XAML プロセッサに識別されます。始め中かっこに続く最初の文字列は、特定の拡張動作を提供するクラスを参照している必要があります。その参照では、部分文字列 "Extension" が実際のクラス名の一部になっている場合にはその部分文字列を省略できます。その後、間に 1 つの空白をはさんで、拡張機能の実装で入力として使用される文字を含めることができます。一連の文字の最後に、終わり中かっこを指定します。WPF のマークアップ拡張機能の主な目的は、属性構文を使用する際に、他の既存のオブジェクトを参照する手段を提供することと、実行時に評価されるオブジェクトの遅延参照を実現することです。たとえば、特定のプロパティが通常受け取る値型の代わりに {Binding} マークアップ拡張機能を指定することによって、単純なデータ バインディングを実現することができます。多くのマークアップ拡張機能は、通常なら属性構文を利用できないプロパティで属性構文を利用できるようにします。たとえば、Style オブジェクトは、それぞれがプリミティブ型ではなく byref オブジェクトを受け取る他の複数のプロパティを含む比較的複雑な参照型です。ただし、スタイルは通常リソースとして作成され、リソースを要求する 2 つのマークアップ拡張機能のいずれかを通じて参照されます。この拡張機能は、プロパティ値の評価をリソース ルックアップまで遅らせます。これにより、Style 型を受け取る Style プロパティの値を次のように属性構文で指定できるようになります。
<Button Style="{StaticResource MyStyle}">My button</Button>
ここで StaticResource は、マークアップ拡張機能の実装を提供する StaticResourceExtension クラスを識別します。次の文字列 MyStyle は、既定ではない StaticResourceExtension コンストラクタの入力として使用されます。拡張機能の文字列から受け取るこのパラメータは、要求された ResourceKey を宣言します。MyStyle は、リソースとして定義された Style の x:Key 属性 値として想定されます。StaticResource のマークアップ拡張機能の使用方法では、読み込み時の静的リソース ルックアップのロジックによって Style プロパティ値を指定するにはリソースを使用する必要があります。
マークアップ拡張機能の詳細については、「マークアップ拡張機能と XAML」を参照してください。マークアップ拡張機能およびその他の XAML プログラミング機能のリファレンス情報については、「XAML 名前空間 (x:) 言語機能」および「WPF 名前空間の XAML 拡張機能」を参照してください。
推奨されないオプションの XAML 使用方法
オプションのプロパティ要素使用方法
オプションのプロパティ要素使用方法として、XAML プロセッサで暗黙的と見なされる要素のコンテンツ プロパティを明示的に指定することができます。たとえば、Menu のコンテンツを宣言するときに、XAML プロセッサの暗黙的な動作 (Menu のすべての子要素は MenuItem であり、Items コレクション内に配置される) を利用する代わりに、Menu の Items コレクションを <Menu.Items> プロパティ要素タグとして明示的に宣言して、各 MenuItem を <Menu.Items> 内に配置することができます。この使用方法によって、マークアップで表現されるオブジェクトの構造が見た目にわかりやすくなる場合があります。また、技術的には可能であっても見た目にわかりにくいマークアップ (属性値内に入れ子になったマークアップ拡張機能など) を避けることができる場合もあります。
typeName.memberName で完全に修飾された属性
typeName.memberName という属性の形式は、実際にはルーティング イベントの場合だけでなく、より汎用的に使用することができます。ただし、他の用途ではこの形式を使用する必要はありません。マークアップ スタイルや読みやすさのためだけに使用することもないようにしてください。次の例に示す Background 属性の 3 つの参照は完全に同等です。
<Button Background="Blue">Background</Button>
<Button Button.Background="Blue">Button.Background</Button>
<Button Control.Background="Blue">Control.Background</Button>
Button.Background が有効なのは、このプロパティの修飾されたルックアップが Button で成功し (Background は Control から継承されています)、Button はオブジェクト要素のクラス (基本クラス) であるからです。Control.Background が有効なのは、Background は実際に Control クラスで定義されていて、Control は Button の基本クラスであるからです。
ただし、次の例の typeName.memberName 形式は有効ではありません。この例には、そのことを示すコメントが含まれています。
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label も Control の派生クラスです。Label.Background を Label オブジェクト要素内で指定した場合は有効になります。しかし、Label は Button のクラスでも基本クラスでもないため、XAML プロセッサの規定の動作により、Label.Background は添付プロパティとして処理されます。Label.Background は添付プロパティではないため、この使用方法は失敗します。
baseTypeName.memberName プロパティ要素
属性構文で typeName.memberName 形式を使用できるのと同じような形で、プロパティ要素構文で baseTypeName.memberName 構文を使用できます。たとえば、次の構文を使用できます。
<Button>Control.Background PE
<Control.Background>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Control.Background>
</Button>
ここでは、プロパティ要素が Button に含まれているにもかかわらず Control.Background として指定されています。
ただし、属性の typeName.memberName 形式と同様に、baseTypeName.memberName はマークアップ スタイルとして適切ではありません。スタイルの問題を考慮して、使用しないようにしてください。