XAML 構文の詳細

ここでは、XAML 構文の要素を説明するために使用される用語を定義します。 これらの用語は、特に WPF ドキュメント、および System.Xaml レベルでの XAML 言語のサポートによって有効になる XAML または XAML の基本概念を使用する他のフレームワークについて、このドキュメントの残りの部分全体で頻繁に使用されます。 このトピックの内容は、「XAML の概要 (WPF)」で紹介した基本的な用語の詳細な説明になります。

このトピックは、次のセクションで構成されています。

  • XAML 言語仕様
  • XAML と CLR
  • オブジェクト要素の構文
  • オブジェクト要素のプロパティ
  • 属性構文 (プロパティ)
  • プロパティ要素の構文
  • コレクションの構文
  • XAML コンテンツ プロパティ
  • コンテンツ プロパティとコレクション構文の組み合わせ
  • XAML 名前空間
  • マークアップ拡張
  • 添付プロパティ
  • 接続されたイベント
  • XAML ルート要素の構造
  • 推奨されないオプションの XAML 使用方法
  • 関連トピック

XAML 言語仕様

ここで定義されている XAML 構文用語は、XAML 言語仕様の中でも定義または参照されています。 XAML は XML に基づく言語で、XML 構造の規則に従っており、かつ XML 構造の規則を拡張したものです。 ここで紹介する用語の中には、XML 言語や XML ドキュメント オブジェクト モデルの説明によく使用される用語と共通の用語や、それらに基づいている用語もあります。

XAML 言語仕様の詳細については、Microsoft ダウンロード センターから [MS-XAML] をダウンロードしてください。

XAML と CLR

XAML はマークアップ言語です。 common language runtime (CLR) は、名前が示しているように、ランタイム実行を有効にします。 XAML 自体は、CLR ランタイムで直接使用される共通言語の 1 つではありません。 XAML は、独自の型システムをサポートしていると考えることができます。 WPF で使用される特定の XAML 解析システムは、CLR および CLR 型システムに基づいています。 XAML 型は CLR 型にマップされ、WPF の XAML の解析時にランタイム表現がインスタンス化されます。 このため、このドキュメントに後述する構文の説明には CLR 型システムへの参照が含まれますが、この参照は XAML 言語仕様の同等の構文の説明には含まれていません (XAML 言語仕様レベルごとに、XAML 型をその他の型システムにマップできます。この型システムは CLR である必要はありませんが、別の XAML パーサーを作成および使用する必要があります)。

型のメンバーとクラスの継承

多くの場合、WPF 型の XAML メンバーとして使用されるプロパティとイベントは、基本型から継承されます。 次に <Button Background="Blue" .../> の例を示します。 Background プロパティは、クラス定義や反映される結果、またはドキュメントを見ればわかるように、Button クラスで直接宣言されているプロパティではありません。 実際には、Background は基本 Control クラスから継承されます。

WPF XAML 要素のこのクラス継承動作は、XAML マークアップのスキーマによる解釈と著しく異なる点の 1 つです。 クラスの継承は複雑になる可能性があります (特に、中間の基本クラスが抽象クラスである場合、またはインターフェイスが必要な場合)。 これは、XAML の要素一式およびその使用可能属性を、DTD 形式や XSD 形式などの XML プログラミングで通常使用されるスキーマ型を使用して正確かつ完全に表現することが困難である原因の 1 つです。 もう 1 つの理由は、XAML 言語自体の機能拡張および型マッピング機能によって、使用可能な型とメンバーのすべての固定表現の完全性が排除されることです。

オブジェクト要素の構文

オブジェクト要素構文は、XML 要素を宣言することによって CLR のクラスや構造体をインスタンス化する XAML マークアップ構文です。 この構文は、HTML などの他のマークアップ言語の要素構文に似ています。 オブジェクト要素構文は、始め山かっこ (<) で始まり、インスタンス化するクラスや構造体の型名がその後に続きます。 型名の後には 0 個以上の空白を含めることができます。また、オブジェクト要素で 0 個以上の属性を宣言することもできます。各属性の 名前="値" のペアは、1 つ以上の空白で区切ります。 最後に、次のいずれかが満たされている必要があります。

  • 要素とタグは、スラッシュ (/) とそれに続く終わり山かっこ (>) で終了している必要があります。

  • 開始タグは、終わり山かっこ (>) で終了している必要があります。 開始タグの後には、他のオブジェクト要素、プロパティ要素、または内部テキストを含めることができます。 実際にここに含めることができる内容は、通常、要素のオブジェクト モデルによって制限されます。 そのほか、オブジェクト要素の対応する終了タグが、他の開始タグ/終了タグのペアとの入れ子の関係やバランスが正しい状態で存在している必要もあります。

.NET によって実装される XAML には、オブジェクト要素を型に、属性をプロパティやイベントに、XAML 名前空間を CLR 名前空間とアセンブリにそれぞれマップする一連の規則があります。 WPF および .NET Framework では、XAML オブジェクト要素は、参照先のアセンブリで定義されている Microsoft .NET 型にマップされ、属性はそれらの型のメンバーにマップされます。 XAML の CLR 型を参照する場合、その型の継承されたメンバーにもアクセスできます。

たとえば、次の例は、Button クラスの新しいインスタンスを作成するオブジェクト要素構文です。Name 属性と、この属性の値も指定されています。

<Button Name="CheckoutButton"/>

次の例のオブジェクト要素構文には、XAML コンテンツ プロパティ構文も含まれています。 中に含まれている内部テキストは、TextBox の XAML コンテンツ プロパティである Text を設定するために使用されます。

<TextBox>This is a Text Box</TextBox>

コンテンツ モデル

あるクラスが構文の点で XAML オブジェクト要素として使用できても、その要素がアプリケーションやページで正しく機能するためには、全体的なコンテンツ モデルや要素ツリーの適切な位置に配置されている必要があります。 たとえば、MenuItem は、通常、MenuBase 派生クラス (Menu など) の子としてのみ配置されている必要があります。 特定の要素のコンテンツ モデルについては、XAML 要素として使用できるコントロールやその他の WPF クラスのクラス ページの解説を参照してください。

オブジェクト要素のプロパティ

XAML のプロパティは、さまざまな構文によって設定されます。 特定のプロパティに対して使用できる構文は、設定するプロパティの基になる型システムの特性によって異なります。

プロパティの値を設定すると、実行時オブジェクト グラフに存在するオブジェクトに機能や特性が追加されます。 オブジェクト要素から作成されるオブジェクトの初期状態は、既定のコンストラクターの動作に基づきます。 通常、アプリケーションでは当該オブジェクトの既定のインスタンスをそのままの状態では使用しません。

属性構文 (プロパティ)

属性構文は、既存のオブジェクト要素の属性を宣言することによってプロパティの値を設定する XAML マークアップ構文です。 属性名は、関連するオブジェクト要素をサポートするクラスのプロパティの CLR メンバー名と一致している必要があります。 属性名の後には、代入演算子 (=) が続きます。 属性値は、引用符で囲まれた文字列である必要があります。

メモメモ

代替の引用符を使用すると、属性内にリテラルの引用符を配置できます。たとえば、二重引用符文字を含む文字列を宣言する手段として、単一引用符を使用できます。単一引用符と二重引用符のどちらを使用する場合も、属性値文字列の先頭と末尾には一致するペアを使用する必要があります。また、エスケープ シーケンスや、特定の XAML 構文によって適用される文字の制限に対処するために使用できる他の技法もあります。「XML 文字エンティティと XAML」を参照してください。

属性構文で設定するプロパティは、パブリックの書き込み可能なプロパティである必要があります。 バッキング型システム内のプロパティの値は、値の型、または関連するバッキング型へのアクセス時に XAML プロセッサによるインスタンス化または参照が可能な参照型である必要があります。

WPF XAML イベントの場合、属性名として参照されるイベントはパブリック デリゲートを持つパブリック イベントである必要があります。

プロパティやイベントは、格納オブジェクト要素によってインスタンス化されるクラスまたは構造体のメンバーである必要があります。

属性値の処理

始まりと終わりの引用符で囲まれた文字列値は XAML プロセッサによって処理されます。 プロパティに対する既定の処理動作は、基になる CLR プロパティの型によって決まります。

属性値は、次のいずれかの方法で、次の処理順序を使用して設定されます。

  1. XAML プロセッサで中かっこ (MarkupExtension から派生しているオブジェクト要素) が検出された場合は、値を文字列として処理する代わりに、参照されているマークアップ拡張機能が先に評価されて、そのマークアップ拡張機能によって返されたオブジェクトが値として使用されます。 マークアップ拡張機能によって返されるオブジェクトは、多くの場合、既存オブジェクトへの参照か、実行時にならないと評価されない式であり、新しくインスタンス化されたオブジェクトではありません。

  2. プロパティの宣言で TypeConverter 属性が指定されている場合や、そのプロパティの値型の宣言で TypeConverter 属性が指定されている場合は、属性の文字列値が変換の入力としてその型コンバーターに送られて、コンバーターによって新しいオブジェクト インスタンスが返されます。

  3. TypeConverter がない場合は、プロパティ型への直接変換が試行されます。 この最後のレベルは、XAML 言語プリミティブ型間のパーサー ネイティブ値での直接変換、または列挙型の名前付き定数の名前のチェック (その後、パーサーは一致する値にアクセスします) になります。

列挙体の属性値

XAML の列挙体は XAML パーサーによって組み込み処理されます。また、列挙体のメンバーを指定するには、列挙体の名前付き定数の 1 つの文字列名を指定する必要があります。

フラグではない列挙値については、属性値の文字列を処理して、いずれかの列挙値に解決するというのがネイティブな動作です。 列挙体を指定する方法は、コードで使用するような 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 列挙体は独自の型コンバーターをサポートしているためです。 修飾子の型コンバーターは、区切り記号としてコンマ (,) ではなく、正符号 (+) を使用します。 この変換では、Microsoft Windows プログラミングでキーの組み合わせを表すときに慣習的に用いられる構文 ("Ctrl + Alt" など) がサポートされます。

プロパティおよびイベントのメンバー名の参照

属性を指定するときには、格納オブジェクト要素のためにインスタンス化した CLR 型のメンバーとして存在する任意のプロパティやイベントを参照できます。

また、格納オブジェクト要素とは関係なく、添付プロパティや添付イベントを参照することもできます。 (添付プロパティについては後のセクションで説明します。)

その他、typeName.event 部分修飾名を使用して、既定の名前空間からアクセスできる任意のオブジェクトの任意のイベントを指定することもできます。この構文では、ルーティング イベントのハンドラーをアタッチできます。これにより、子要素からルーティングされたイベントが親要素のメンバー テーブルにもなかった場合に、そのイベントを処理できます。 この構文は添付イベントの構文に似ていますが、この場合のイベントは本当の添付イベントではありません。 この場合は、イベントを修飾名で参照しています。 詳細については、「ルーティング イベントの概要」を参照してください。

一部のシナリオでは、属性名としてではなく属性の値としてプロパティ名が指定される場合もあります。 そのプロパティ名に修飾子を含めることもできます (ownerType.dependencyPropertyName の形式で指定されるプロパティなど)。 これは、XAML でスタイルやテンプレートを作成するときの一般的なシナリオです。 属性値として指定したプロパティ名にはまた別の処理規則が適用され、設定するプロパティの型や特定の WPF サブシステムの動作によって制御されます。 詳細については、「スタイルとテンプレート」を参照してください。

そのほか、プロパティ名は、属性値でプロパティ間のリレーションシップを記述する場合にも使用されます。 この機能は、データ バインディングやストーリーボード ターゲットのために使用されるもので、PropertyPath クラスとその型コンバーターによって実現されます。 検索セマンティクスの詳細については、「PropertyPath の XAML 構文」を参照してください。

プロパティ要素の構文

プロパティ要素構文は、要素の基本的な XML 構文規則からやや逸脱した構文です。 XML では、属性の値は事実上の文字列であり、変更できるのは使用する文字列エンコードの形式だけです。 XAML では、他のオブジェクト要素をプロパティの値として割り当てることができます。 これを実現するのがプロパティ要素構文です。 プロパティを要素タグ内の属性として指定する代わりに、elementTypeName.propertyName という形式の開始要素タグを使用して指定します。後は、プロパティの値を指定して、最後にプロパティ要素を閉じます。

具体的に言うと、この構文は始め山かっこ (<) で始まり、プロパティ要素構文を含むクラスまたは構造体の型名がその後に続きます。 その後、1 つのドット (.)、プロパティの名前、終わり山かっこ (>) が続きます。 属性構文と同様に、そのプロパティは指定された型の宣言されたパブリック メンバー内に存在する必要があります。 プロパティに割り当てられる値は、プロパティ要素内に格納されます。 プロパティ要素構文はオブジェクトを値として指定するシナリオで使用するものなので、この値は通常、1 つ以上のオブジェクト要素として指定されます。 最後に、同じ elementTypeName.propertyName の組み合わせの対応する終了タグを、他の要素タグとの入れ子の関係やバランスが正しい状態で指定する必要があります。

たとえば、次の例は、ButtonContextMenu プロパティのプロパティ要素構文です。

<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 での空白の処理」を参照してください)。 もう 1 つのシナリオでは、x:Uid ディレクティブ をプロパティ要素に適用し、値を WPF 出力 BAML または他の技法でローカライズが必要な値としてマークします。

プロパティ要素は、WPF 論理ツリーには表示されません。 プロパティ要素は、プロパティを設定するための単なる構文であり、対応するインスタンスまたはオブジェクトを持つ要素ではありません。 論理ツリーの概念の詳細については、「WPF のツリー」を参照してください。

属性構文とプロパティ要素構文の両方がサポートされているプロパティでは、空白の処理などの細かい点で多少の違いが生じることはありますが、原則として、どちらの構文を使用しても同じ結果になります。

コレクションの構文

XAML 仕様では、値型がコレクションのプロパティを XAML プロセッサの実装で識別する必要があります。 .NET の一般的な XAML プロセッサの実装はマネージ コードおよび CLR に基づいているため、このようなプロセッサは、次のいずれかの方法でコレクション型を識別します。

プロパティの型がコレクションの場合、推定のコレクション型をオブジェクト要素としてマークアップで指定する必要はありません。 代わりに、コレクション内の項目となる要素を、プロパティ要素の 1 つ以上の子要素として指定します。 それらの各項目が読み込み時にオブジェクトへと評価され、暗黙的なコレクションの Add メソッドの呼び出しによってコレクションに追加されます。 たとえば、StyleTriggers プロパティは、特化されたコレクション型である TriggerCollection を受け取ります。このコレクション型は、IList を実装します。 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>) は、コレクション検出ではサポートされていません。一方、List<T> クラスおよび Dictionary<TKey, TValue> クラスを基本クラスとして使用することはできます。それぞれ、IListIDictionary を直接実装しているためです。

コレクション型の .NET リファレンス ページでは、このようにコレクションのオブジェクト要素を意図的に省略する構文が "暗黙的なコレクション構文" として XAML 構文セクションに示されている場合があります。

ルート要素は別として、XAML ファイル内で他の要素の子要素として入れ子になっているすべてのオブジェクト要素は、実際には、その親要素の暗黙的なコレクション プロパティのメンバーか、親要素の XAML コンテンツ プロパティ (XAML コンテンツ プロパティについては後で説明します) の値を指定する要素か、またはその両方です。 つまり、マークアップ ページ内の親要素と子要素の関係は、実際にはルートにある単一のオブジェクトであり、ルートの下のすべてのオブジェクト要素は、親のプロパティ値を指定する単一のインスタンスか、親のコレクション型のプロパティ値でもあるコレクション内の項目の 1 つです。 この単一ルートの概念は XML では一般的で、Load などの XAML を読み込む API の動作が強化されることがよくあります。

コレクション (GradientStopCollection) のオブジェクト要素を明示的に指定した構文を次の例に示します。

<LinearGradientBrush>
  <LinearGradientBrush.GradientStops>
    <GradientStopCollection>
      <GradientStop Offset="0.0" Color="Red" />
      <GradientStop Offset="1.0" Color="Blue" />
    </GradientStopCollection>
  </LinearGradientBrush.GradientStops>
</LinearGradientBrush>

常にコレクションを明示的に宣言できるとは限りません。 たとえば、先ほどの Triggers の例で TriggerCollection を明示的に宣言しようとすると失敗します。 コレクションを明示的に宣言するには、コレクション クラスが既定のコンストラクターをサポートし、TriggerCollection が既定のコンストラクターを持たないことが必要です。

XAML コンテンツ プロパティ

XAML コンテンツ構文は、クラス宣言の一部として ContentPropertyAttribute が指定されているクラスでのみ有効な構文です。 ContentPropertyAttribute は、その型の要素 (派生クラスを含む) のコンテンツ プロパティであるプロパティ名を参照します。 XAML プロセッサによる処理の際には、オブジェクト要素の開始タグと終了タグの間で検出されたすべての子要素や内部テキストが、そのオブジェクトの XAML コンテンツ プロパティの値として割り当てられます。 コンテンツ プロパティの明示的なプロパティ要素を指定できますが、この使用方法は、通常は .NET リファレンスの XAML 構文セクションには表示されていません。 この明示的で詳細な方法は、マークアップをわかりやすくするために、またはマークアップのスタイルとして有効な場合もあります。しかし通常、コンテンツ プロパティの目的は、マークアップを簡素化して、直感的に親子として関連付けられる要素を直接入れ子にできるようにすることです。 要素に設定された他のプロパティのプロパティ要素タグは、厳密な XAML 言語定義ごとに "コンテンツ" として割り当てられることなく、XAML パーサーの処理順序であらかじめ処理され、"コンテンツ" として認識されません。

XAML コンテンツ プロパティの値は連続している必要がある

XAML コンテンツ プロパティの値は、そのオブジェクト要素の他のすべてのプロパティ要素の前または後に指定する必要があります。 これは、XAML コンテンツ プロパティの値を文字列として指定する場合も、1 つ以上のオブジェクトとして指定する場合も同様です。 たとえば、次のマークアップは解析されません。

<Button>I am a 
  <Button.Background>Blue</Button.Background>
  blue button</Button>

これが無効なのは、コンテンツ プロパティに対してプロパティ要素構文を使用して明示的な構文にした場合、次のように、コンテンツ プロパティが 2 回設定されるためです。

<Button>
  <Button.Content>I am a </Button.Content>
  <Button.Background>Blue</Button.Background>
  <Button.Content> blue button</Button.Content>
</Button>

コンテンツ プロパティがコレクションで、子要素内にプロパティ要素が混在している場合も、同様に無効です。

<StackPanel>
  <Button>This example</Button>
  <StackPanel.Resources>
    <SolidColorBrush x:Key="BlueBrush" Color="Blue"/>
  </StackPanel.Resources>
  <Button>... is illegal XAML</Button>
</StackPanel>

コンテンツ プロパティとコレクション構文の組み合わせ

複数のオブジェクト要素をコンテンツとして受け入れるためには、コンテンツ プロパティの型はコレクション型であることが必要です。 コレクション型のプロパティ要素構文の場合と同様に、XAML プロセッサによってコレクション型の型が識別される必要があります。 要素に XAML コンテンツ プロパティがあり、その XAML コンテンツ プロパティの型がコレクションの場合、暗黙的なコレクション型はマークアップでオブジェクト要素として指定されている必要はなく、XAML コンテンツ プロパティもプロパティ要素として指定されている必要はありません。 このため、マークアップの外見上のコンテンツ モデルでは、複数の子要素をコンテンツとして割り当てられるようになります。 以下は、Panel 派生クラスのコンテンツ構文です。 すべての Panel 派生クラスでは、XAML コンテンツ プロパティが 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 名前空間

これまでに見てきた構文の例では、既定の XAML 名前空間以外の XAML 名前空間は指定されていません。 一般的な WPF アプリケーションでは、既定の XAML 名前空間は WPF 名前空間に指定されます。 既定の XAML 名前空間以外の XAML 名前空間を指定することもできます。その場合も、同様の構文を使用できます。 ただし、既定の XAML 名前空間ではアクセスできないクラスを指定する際は、そのクラス名の前に、対応する CLR 名前空間に割り当てられる XAML 名前空間のプレフィックスを付ける必要があります。 たとえば、<custom:Example/> は、Example クラスのインスタンスを作成するためのオブジェクト要素構文ですが、このクラスを含む CLR 名前空間 (および、バッキング型を含む可能性のある外部アセンブリ情報) は、以前に custom プレフィックスに割り当てられました。

XAML 名前空間の詳細については、「XAML 名前空間および WPF XAML の名前空間の割り当て」を参照してください。

マークアップ拡張

XAML では、マークアップ拡張機能というプログラミング エンティティが定義されています。マークアップ拡張機能を使用すると、XAML プロセッサによる標準の処理を避けて、対応するクラスに文字列属性値やオブジェクト要素の処理を委ねることができます。 マークアップ拡張機能は属性構文で、終わり中かっこ (}) 以外の文字が後に続く始め中かっこ ({) によって XAML プロセッサに識別されます。 始め中かっこに続く最初の文字列は、特定の拡張動作を提供するクラスを参照している必要があります。その参照では、部分文字列 "Extension" が実際のクラス名の一部になっている場合にはその部分文字列を省略できます。 その後、間に 1 つの空白をはさんで、拡張機能の実装で入力として使用される文字を含めることができます。一連の文字の最後に、終わり中かっこを指定します。

.NET XAML 実装では、WPF でサポートされているすべてのマークアップ拡張機能、および他のフレームワークやテクノロジの基礎として、MarkupExtension 抽象クラスが使用されています。 WPF が明確に実装するマークアップ拡張機能の目的は、他の既存のオブジェクトを参照する手段を提供すること、または実行時に評価されるオブジェクトの遅延参照を実現することである場合がよくあります。 たとえば、特定のプロパティが通常受け取る値型の代わりに {Binding} マークアップ拡張機能を指定することによって、単純な WPF データ バインディングを実現できます。 多くの WPF マークアップ拡張機能は、通常なら属性構文を利用できないプロパティで属性構文を利用できるようにします。 たとえば、Style オブジェクトは、入れ子になった一連のオブジェクトとプロパティを含む比較的複雑な型です。 WPF のスタイルは通常 ResourceDictionary のリソースとして定義され、リソースを要求する 2 つの WPF マークアップ拡張機能のいずれかを通じて参照されます。 このマークアップ拡張機能は、プロパティ値の評価をリソース検索まで遅らせます。これにより、Style 型を受け取る Style プロパティの値を次の例のように属性構文で指定できるようになります。

<Button Style="{StaticResource MyStyle}">My button</Button>

ここで StaticResource は、マークアップ拡張機能の実装を提供する StaticResourceExtension クラスを識別します。 次の文字列 MyStyle は、既定ではない StaticResourceExtension コンストラクターの入力として使用されます。拡張機能の文字列から受け取るこのパラメーターは、要求された ResourceKey を宣言します。 MyStyle は、リソースとして定義された Stylex:Key 値として想定されます。 StaticResource のマークアップ拡張機能の使用方法では、読み込み時の静的リソース ルックアップのロジックによって Style プロパティ値を指定するにはリソースを使用する必要があります。

マークアップ拡張機能の詳細については、「マークアップ拡張機能と WPF XAML」を参照してください。 一般的な .NET XAML 実装で有効なマークアップ拡張機能およびその他の XAML プログラミング機能のリファレンス情報については、「XAML 名前空間 (x:) 言語機能」を参照してください。 WPF 固有のマークアップ拡張機能については、「WPF XAML 拡張機能」を参照してください。

添付プロパティ

添付プロパティは、XAML で導入されたプログラミング概念です。添付プロパティを使用すると、特定の型で所有および定義されているプロパティを、任意の要素の属性またはプロパティ要素として設定できます。 添付プロパティは主に、マークアップ構造内の子要素が、すべての要素の間で広範に共有されているオブジェクト モデルを使用しなくても、親要素に情報を報告できるようにすることを目的としています。 逆に、親要素が子要素に情報を報告するために添付プロパティを使用することもできます。 添付プロパティの目的と、独自の添付プロパティの作成方法の詳細については、「添付プロパティの概要」を参照してください。

添付プロパティの構文は、typeName.propertyName の組み合わせを指定するという点で、一見プロパティ要素構文に似ています。 ただし、次の 2 つの重要な違いがあります。

  • 属性構文で添付プロパティを設定するときにも typeName.propertyName の組み合わせを使用できます。 属性構文でプロパティ名を修飾する必要があるのは添付プロパティの場合だけです。

  • 添付プロパティに対してプロパティ要素構文を使用することもできます。 ただし、一般的なプロパティ要素構文で指定する typeName は、プロパティ要素を含むオブジェクト要素ですが、 添付プロパティを参照する場合は、typeName は、添付プロパティを含むオブジェクト要素ではなく、添付プロパティを定義しているクラスです。

接続されたイベント

添付イベントもまた、XAML で導入されたプログラミング概念です。添付イベントでは、イベントを特定の型で定義して、ハンドラーを任意のオブジェクト要素にアタッチすることができます。 WOF 実装では、添付イベントを定義する型は多くの場合、サービスを定義する静的な型です。それらの添付イベントが、サービスを公開する型でルーティング イベント エイリアスによって公開される場合もあります。 添付イベントのハンドラーは属性構文で指定します。 添付プロパティの場合と同様に、添付イベントでは属性構文が拡張されて、typeName.eventName という使用方法が許可されます。typeName は、添付イベント インフラストラクチャの Add および Remove のイベント ハンドラー アクセサーを提供するクラスです。eventName はイベントの名前です。

XAML ルート要素の構造

次の表は、一般的な XAML ルート要素の構造を示しています。ルート要素に特有の属性が含まれています。

<Page

ルート要素の開始オブジェクト要素。

xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"

既定の (WPF) XAML 名前空間。

xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"

XAML 言語の XAML 名前空間。

x:Class="ExampleNamespace.ExampleCode"

部分クラス宣言。部分クラスに定義されている分離コードにマークアップを関連付けます。

>

ルートのオブジェクト要素の終了。 要素に子要素が含まれているため、オブジェクトはまだ閉じられていません。

推奨されないオプションの XAML 使用方法

以降のセクションでは、XAML プロセッサによって技術的にサポートされますが、XAML ソースを含むアプリケーションを開発するときに人が判読できるままの状態の XAML ファイルに影響を与える、詳細や他の美的外観に関する問題を生成する、XAML の使用方法について説明します。

オプションのプロパティ要素使用方法

オプションのプロパティ要素使用方法として、XAML プロセッサで暗黙的と見なされる要素のコンテンツ プロパティを明示的に記述することができます。 たとえば、Menu のコンテンツを宣言するときに、XAML プロセッサの暗黙的な動作 (Menu のすべての子要素は MenuItem であり、Items コレクション内に配置される) を利用する代わりに、MenuItems コレクションを <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 クラスで定義されていて、ControlButton の基本クラスであるためです。

ただし、次の例の typeName.memberName 形式は有効ではありません。この例には、そのことを示すコメントが含まれています。

<!--<Button Label.Background="Blue">Does not work</Button> -->

LabelControl の派生クラスです。Label.Background を Label オブジェクト要素内で指定した場合は有効になります。 しかし、LabelButton のクラスでも基本クラスでもないため、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 はマークアップ スタイルとして適切ではないため、使用しないようにしてください。

参照

概念

XAML の概要 (WPF)

依存関係プロパティの概要

TypeConverters および XAML

WPF における XAML とカスタム クラス

その他の技術情報

XAML 名前空間 (x:) 言語機能

WPF XAML 拡張機能