XAML 構文の詳細
このトピックでは、XAML 構文の要素を記述するために使用される用語を定義します。 これらの用語は、このドキュメントの残りの部分で頻繁に使用されます。これは、特に WPF ドキュメントと、System.Xaml レベルでの XAML 言語サポートによって有効になる XAML または基本的な XAML 概念を使用する他のフレームワークの両方に使用されます。 このトピックでは、WPFの XAML
XAML 言語仕様
ここで定義されている XAML 構文の用語も、XAML 言語仕様内で定義または参照されています。 XAML は XML に基づく言語であり、XML 構造規則に従うか拡張します。 用語の一部は、XML 言語または XML ドキュメント オブジェクト モデルを記述するときに一般的に使用される用語から共有されるか、または用語に基づいています。
XAML 言語仕様の詳細については、Microsoft ダウンロード センターから [MS-XAML] をダウンロードしてください。
XAML と CLR
XAML はマークアップ言語です。 共通言語ランタイム (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 要素のクラス継承動作は、スキーマによって適用される XML マークアップの解釈から大きく逸脱しています。 クラスの継承は、特に中間基底クラスが抽象である場合、またはインターフェイスが関係する場合に複雑になる可能性があります。 これは、一連の XAML 要素とその許容される属性が、DTD や XSD 形式などの XML プログラミングに通常使用されるスキーマ型を使用して正確かつ完全に表現するのが難しい理由の 1 つです。 もう 1 つの理由は、XAML 言語自体の拡張性と型マッピング機能が、許容される型とメンバーの固定表現の完全性を妨げるという点です。
オブジェクト要素の構文
オブジェクト要素構文 は、XML 要素を宣言して CLR クラスまたは構造体をインスタンス化する XAML マークアップ構文です。 この構文は、HTML などの他のマークアップ言語の要素構文に似ています。 オブジェクト要素の構文は、左山かっこ (<) で始まり、その直後にインスタンス化されるクラスまたは構造体の型名が続きます。 型名の後に 0 個以上のスペースを指定できます。また、0 個以上の属性をオブジェクト要素で宣言し、各属性 name="value" ペアを区切るスペースを 1 つ以上指定することもできます。 最後に、次のいずれかが当てはまる必要があります。
要素とタグは、スラッシュ (/) で閉じた後、直ちに右山かっこ (>) を付ける必要があります。
開始タグは、右の不等号(>>)で完了する必要があります。 他のオブジェクト要素、プロパティ要素、または内部テキストは、開始タグに従うことができます。 ここに含まれるコンテンツは、通常、要素のオブジェクト モデルによって制約されます。 オブジェクト要素の同等の終了タグも、適切な入れ子に存在し、他の開始タグと終了タグのペアとのバランスを取る必要があります。
.NET によって実装される XAML には、オブジェクト要素を型にマップし、属性をプロパティまたはイベントに、XAML 名前空間を CLR 名前空間とアセンブリにマップする一連の規則があります。 WPF および .NET の場合、XAML オブジェクト要素は参照アセンブリで定義されている .NET 型にマップされ、属性はそれらの型のメンバーにマップされます。 XAML で CLR 型を参照すると、その型の継承されたメンバーにもアクセスできます。
たとえば、次の例は、Button クラスの新しいインスタンスをインスタンス化し、Name 属性とその属性の値も指定するオブジェクト要素構文です。
<Button Name="CheckoutButton"/>
次の例は、XAML コンテンツ プロパティ構文も含むオブジェクト要素の構文です。 内に含まれる内部テキストは、TextBox XAML コンテンツ プロパティ (Text) を設定するために使用されます。
<TextBox>This is a Text Box</TextBox>
コンテンツ モデル
クラスは構文の観点から XAML オブジェクト要素としての使用をサポートしている場合がありますが、その要素は、コンテンツ モデルまたは要素ツリー全体の予想される位置に配置された場合にのみ、アプリケーションまたはページで適切に機能します。 たとえば、MenuItem は通常、Menuなどの MenuBase 派生クラスの子としてのみ配置する必要があります。 特定の要素のコンテンツ モデルは、XAML 要素として使用できるコントロールやその他の WPF クラスのクラス ページの注釈の一部として文書化されています。
オブジェクト要素のプロパティ
XAML のプロパティは、さまざまな構文によって設定されます。 特定のプロパティに使用できる構文は、設定するプロパティの基になる型システム特性によって異なります。
プロパティの値を設定することで、実行時オブジェクト グラフに存在するフィーチャまたは特性をオブジェクトに追加します。 オブジェクト要素から作成されたオブジェクトの初期状態は、パラメーターなしのコンストラクターの動作に基づいています。 通常、アプリケーションでは、特定のオブジェクトの完全に既定のインスタンス以外のものを使用します。
属性構文 (プロパティ)
属性構文は、既存のオブジェクト要素で属性を宣言することによってプロパティの値を設定する XAML マークアップ構文です。 属性名は、関連するオブジェクト要素をバックするクラスのプロパティの CLR メンバー名と一致する必要があります。 属性名の後に代入演算子 (=) が続きます。 属性値は、引用符で囲まれた文字列である必要があります。
手記
代替引用符を使用して、属性内にリテラル引用符を配置できます。 たとえば、一重引用符を使用して、その中に二重引用符を含む文字列を宣言できます。 単一引用符と二重引用符のどちらを使用する場合でも、属性値文字列を開いたり閉じたりするために、一致するペアを使用する必要があります。 また、特定の XAML 構文によって課される文字制限を回避するために使用できるエスケープ シーケンスやその他の手法もあります。 「XML 文字エンティティと XAML」を参照してください。
属性構文を使用して設定するには、プロパティがパブリックであり、書き込み可能である必要があります。 バッキング型システムのプロパティの値は、値型であるか、関連するバッキング型にアクセスするときに XAML プロセッサによってインスタンス化または参照できる参照型である必要があります。
WPF XAML イベントの場合、属性名として参照されるイベントはパブリックであり、パブリック デリゲートを持っている必要があります。
プロパティまたはイベントは、含むオブジェクト要素によってインスタンス化されるクラスまたは構造体のメンバーである必要があります。
属性値の処理
開始引用符と終了引用符に含まれる文字列値は、XAML プロセッサによって処理されます。 プロパティの場合、既定の処理動作は、基になる CLR プロパティの型によって決まります。
属性値は、次のいずれかの処理順序で入力されます。
XAML プロセッサで中かっこ、または MarkupExtensionから派生したオブジェクト要素が検出された場合、参照されるマークアップ拡張は、値を文字列として処理するのではなく最初に評価され、マークアップ拡張によって返されるオブジェクトが値として使用されます。 多くの場合、マークアップ拡張によって返されるオブジェクトは、既存のオブジェクトへの参照、または実行時まで評価を延期する式であり、新しくインスタンス化されたオブジェクトではありません。
プロパティが属性付き TypeConverterで宣言されている場合、またはそのプロパティの値型が属性付き TypeConverterで宣言されている場合、属性の文字列値は変換入力として型コンバーターに送信され、コンバーターは新しいオブジェクト インスタンスを返します。
TypeConverterがない場合は、プロパティ型への直接変換が試行されます。 この最終レベルは、XAML 言語プリミティブ型間のパーサーネイティブ値での直接変換、または列挙型の名前付き定数の名前のチェックです (パーサーは一致する値にアクセスします)。
列挙属性値
XAML の列挙型は XAML パーサーによって本質的に処理されます。列挙型のメンバーは、列挙体のいずれかの名前付き定数の文字列名を指定して指定する必要があります。
フラグ以外の列挙値の場合、ネイティブな動作は属性値の文字列を処理し、列挙値のいずれかに解決することです。 列挙型をコードでの書き方のように、列挙の形式で指定しないでください。値。 代わりに、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 ではまれです。 ただし、このような列挙体の 1 つは StyleSimulationsです。 たとえば、コンマ区切りのフラグごとの属性構文を使用して、Glyphs クラスの解説に記載されている例を変更できます。StyleSimulations = "BoldSimulation"
StyleSimulations = "BoldSimulation,ItalicSimulation"
になる可能性があります。 KeyBinding.Modifiers は、複数の列挙値を指定できる別のプロパティです。 ただし、ModifierKeys 列挙型は独自の型コンバーターをサポートしているため、このプロパティは特殊なケースになります。 修飾子の型コンバーターは、コンマ (,) ではなく、区切り記号としてプラス記号 (+) を使用します。 この変換では、Microsoft Windows プログラミングでのキーの組み合わせを表す従来の構文 ("Ctrl + Alt" など) がサポートされています。
プロパティおよびイベントメンバー名の参照
属性を指定する場合は、包含オブジェクト要素に対してインスタンス化した CLR 型のメンバーとして存在する任意のプロパティまたはイベントを参照できます。
または、包含オブジェクト要素とは関係なく、添付プロパティまたは添付イベントを参照できます。 (添付プロパティについては、今後のセクションで説明します)。
typeNameを使用することで、既定の名前空間からアクセス可能な任意のオブジェクトのイベントに名前を付けることができます。イベントは部分修飾名 を用いて識別されます。この構文は、ハンドラーが子要素からルーティングされるイベントを処理することを目的としている場合に、親要素がそのメンバーテーブルにそのイベントを持たなくてもルーティングイベントのハンドラーを添付することをサポートします。 この構文は添付イベント構文に似ていますが、ここでのイベントは実際の添付イベントではありません。 代わりに、修飾名を持つイベントを参照しています。 詳細については、「ルーティング イベントの概要 を参照してください。
一部のシナリオでは、属性名ではなく、属性の値としてプロパティ名が指定される場合があります。 そのプロパティ名には、
プロパティ名のもう 1 つの使用法は、属性値がプロパティとプロパティのリレーションシップを記述する場合です。 この機能は、データ バインディングとストーリーボード ターゲットに使用され、PropertyPath クラスとその型コンバーターによって有効になります。 参照セマンティクスの詳細については、「PropertyPath XAML 構文
プロパティ エレメントの構文
Property 要素構文 は、要素の基本的な 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 つの使用法は、これらの各ケースで、より単純な属性構文を使用することもできるため、やや一般的ではありません。 プロパティ要素に文字列を入力するシナリオの 1 つは、XAML コンテンツ プロパティではないが UI テキストの表現に使用されるプロパティに対するものです。また、その UI テキストには改行などの特定の空白要素が必要です。 属性構文では改行を保持できませんが、大幅な空白の保持がアクティブである限り、プロパティ要素の構文を使用できます (詳細については、XAMLでの空白処理の
プロパティ要素は、WPF 論理ツリーでは表されません。 プロパティ要素は、プロパティを設定するための特定の構文に過ぎず、インスタンスまたはオブジェクトをバッキングする要素ではありません。 (論理ツリーの概念の詳細については、「WPFの
属性とプロパティ要素の両方の構文がサポートされているプロパティの場合、通常、2 つの構文の結果は同じですが、空白の処理などの機微は構文によって若干異なる場合があります。
コレクション構文
XAML 仕様では、値の型がコレクションであるプロパティを識別するために、XAML プロセッサの実装が必要です。 .NET での一般的な XAML プロセッサの実装は、マネージド コードと CLR に基づいており、次のいずれかを使用してコレクション型を識別します。
型は IListを実装します。
型は IDictionaryを実装します。
型は
から派生します (XAML の配列の詳細については、「x:Array Markup Extension 」を参照してください)。
プロパティの型がコレクションの場合、推論されたコレクション型をマークアップでオブジェクト要素として指定する必要はありません。 代わりに、コレクション内の項目になるように意図された要素は、プロパティ要素の 1 つ以上の子要素として指定されます。 このような各項目は、読み込み中にオブジェクトに評価され、暗黙的なコレクションの Add
メソッドを呼び出すことによってコレクションに追加されます。 たとえば、Style の Triggers プロパティは、IListを実装する特殊なコレクション型 TriggerCollectionを受け取ります。 マークアップ内の TriggerCollection オブジェクト要素をインスタンス化する必要はありません。 代わりに、Style.Triggers
プロパティ要素内の要素として 1 つ以上の Trigger 項目を指定します。ここで、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> クラスは基底クラスとして使用できます。これは、IList を直接実装するため、または基底クラスとして Dictionary<TKey,TValue> するためです。これは、IDictionary を直接実装するためです。
コレクション型の .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>
コレクションを明示的に宣言できるわけではありません。 たとえば、前に示した例で TriggerCollection を明示的に宣言しようとすると、Triggers 失敗します。 コレクションを明示的に宣言するには、コレクション クラスがパラメーターなしのコンストラクターをサポートする必要があり、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>
コンテンツプロパティとコレクション構文の組み合わせ
1 つ以上のオブジェクト要素をコンテンツとして受け入れるには、コンテンツ プロパティの型がコレクション型である必要があります。 コレクション型のプロパティ要素構文と同様に、XAML プロセッサはコレクション型である型を識別する必要があります。 要素に XAML コンテンツ プロパティがあり、XAML コンテンツ プロパティの型がコレクションである場合、暗黙的なコレクション型をマークアップでオブジェクト要素として指定する必要はありません。また、XAML コンテンツ プロパティをプロパティ要素として指定する必要はありません。 そのため、マークアップ内の見かけ上のコンテンツ モデルに、コンテンツとして複数の子要素を割り当てることができるようになりました。 Panel 派生クラスのコンテンツ構文を次に示します。 すべての Panel 派生クラスは、XAML コンテンツ プロパティを Childrenするように設定します。これには、UIElementCollection型の値が必要です。
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://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 はパラメーターなしのパブリック コンストラクターを公開しないため、オブジェクト要素としてインスタンス化することはできません。
Content プロパティを持つオブジェクトにおけるプロパティ要素とオブジェクト要素の混在
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 が特に実装するマークアップ拡張は、多くの場合、他の既存のオブジェクトを参照したり、実行時に評価されるオブジェクトへの遅延参照を行ったりするための手段を提供することを目的としています。 たとえば、単純な WPF データ バインディングは、特定のプロパティが通常受け取る値の代わりに {Binding}
マークアップ拡張を指定することによって実現されます。 WPF マークアップ拡張機能の多くは、属性構文が使用できないプロパティの属性構文を有効にします。 たとえば、Style オブジェクトは、入れ子になった一連のオブジェクトとプロパティを含む比較的複雑な型です。 WPF のスタイルは、通常、ResourceDictionaryのリソースとして定義され、リソースを要求する 2 つの WPF マークアップ拡張のいずれかを通じて参照されます。 マークアップ拡張機能は、プロパティ値の評価をリソース参照に延期し、次の例のように属性構文で型 Styleを受け取って、Style プロパティの値を指定できるようにします。
<Button Style="{StaticResource MyStyle}">My button</Button>
ここでは、StaticResource
マークアップ拡張の実装を提供する StaticResourceExtension クラスを識別します。 次の文字列 MyStyle
は、既定以外の StaticResourceExtension コンストラクターの入力として使用されます。ここで、拡張文字列から取得したパラメーターは、要求された ResourceKeyを宣言します。 MyStyle
は、リソースとして定義された Style の x:Key 値であることが期待されます。 StaticResource Markup Extension、読み込み時に静的リソース参照ロジックを使用して Style プロパティ値を提供するためにリソースを使用するように指定します。
マークアップ拡張機能の詳細については、「マークアップ拡張機能 WPF XAML」を参照してください。 一般的な .NET XAML 実装で有効になっているマークアップ拡張機能およびその他の XAML プログラミング機能のリファレンスについては、「XAML 名前空間 (x:) 言語機能を参照してください。 WPF 固有のマークアップ拡張機能については、「WPF XAML 拡張機能 」を参照してください。
添付プロパティ
添付プロパティは XAML で導入されたプログラミングの概念であり、プロパティは特定の型によって所有および定義できますが、任意の要素の属性またはプロパティ要素として設定されます。 添付プロパティが意図されている主なシナリオは、マークアップ構造の子要素が、すべての要素にわたって広く共有されるオブジェクト モデルを必要とせずに、親要素に情報を報告できるようにすることです。 逆に、添付プロパティは親要素が子要素に情報を報告するために使用できます。 添付プロパティの目的と、独自の添付プロパティを作成する方法の詳細については、「添付プロパティの概要 を参照してください。
添付プロパティでは、表面的にプロパティ要素の構文に似た構文が使用され、typeNameとpropertyName の組み合わせを指定します。 次の 2 つの重要な違いがあります。
typeNameは、属性構文を使用して添付プロパティを設定する場合でも、プロパティ名 を組み合わせて使用することができます。 プロパティ名の修飾が属性構文の要件である場合は、添付プロパティのみが該当します。
添付プロパティには、プロパティ要素の構文を使用することもできます。 ただし、一般的なプロパティ要素の構文では、指定する typeName は、プロパティ要素を含むオブジェクト要素です。 添付プロパティを参照している場合、typeName は、包含オブジェクト要素ではなく、添付プロパティを定義するクラスです。
添付イベント
添付イベントは XAML で導入されたもう 1 つのプログラミング概念であり、イベントは特定の型で定義できますが、ハンドラーは任意のオブジェクト要素にアタッチできます。 WOF 実装では、多くの場合、アタッチされたイベントを定義する型はサービスを定義する静的な型であり、それらのアタッチされたイベントは、サービスを公開する型のルーティング イベント エイリアスによって公開される場合があります。 添付イベントのハンドラーは、属性構文を使用して指定されます。 添付イベントの場合と同様に、添付イベント用の属性構文が拡張され、typeName.eventName という形式が使用可能になります。ここで、typeName は、添付イベントインフラストラクチャのための Add
および Remove
イベントハンドラーアクセサーを提供するクラスであり、eventName はイベント名です。
XAML ルート要素の構造
次の表は、ルート要素の特定の属性を示す一般的な XAML ルート要素を示しています。
属性 | 説明 |
---|---|
<Page |
ルート要素のオブジェクト要素を開く |
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" |
既定の (WPF) XAML 名前空間 |
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" |
XAML 言語の XAML 名前空間 |
x:Class="ExampleNamespace.ExampleCode" |
マークアップをいずれかのコードビハインドに接続するための部分クラス宣言 |
> |
ルートのオブジェクト要素の末尾。 要素に子要素が含まれているため、オブジェクトはまだ閉じられません |
省略可能な XAML 使用法と推奨されない XAML 使用法
次のセクションでは、XAML プロセッサによって技術的にサポートされているが、XAML ソースを含むアプリケーションを開発するときに、XAML ファイルが人間が判読できる状態を妨げる詳細性やその他の審美的な問題を生み出す XAML 使用法について説明します。
省略可能なプロパティ要素の使用法
省略可能なプロパティ要素の使用法には、XAML プロセッサが暗黙的と見なす要素コンテンツ プロパティの明示的な書き込みが含まれます。 たとえば、Menuの内容を宣言する場合は、<Menu.Items>
プロパティ要素タグとして Menu の Items コレクションを明示的に宣言し、Menu のすべての子要素が MenuItem である必要があり、Items コレクションに配置される暗黙的な XAML プロセッサ動作を使用するのではなく、各 MenuItem を <Menu.Items>
内に配置することができます。 省略可能な使用法は、マークアップで表されるオブジェクト構造を視覚的に明確にするのに役立つ場合があります。 また、明示的なプロパティ要素を使用すると、属性値内の入れ子になったマークアップ拡張など、技術的には機能するが視覚的に混乱するマークアップを回避できる場合があります。
Full 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
は、Control クラスが実際に Background を定義し、Control が Button 基底クラスであるために機能します。
ただし、次の typeName、memberName フォームの例は機能しないため、コメントアウトされています。
<!--<Button Label.Background="Blue">Does not work</Button> -->
Label は Controlの別の派生クラスであり、Label オブジェクト要素内で Label.Background
を指定した場合、この使用法は機能します。 ただし、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はマークアップのスタイルとして不適切なので、避けるべきです。
関連項目
- WPF での XAML
- XAML 名前空間 (x:) 言語機能
- WPF XAML 拡張機能
- 依存関係プロパティの概要
- TypeConverters と XAML
- WPF の XAML およびカスタムクラスに関する
.NET Desktop feedback