マークアップ拡張機能と WPF XAMLMarkup Extensions and WPF XAML

ここでは XAML のマークアップ拡張の概念について、構文規則、目的、その基になるクラス オブジェクト モデルなどを説明します。This topic introduces the concept of markup extensions for XAML, including their syntax rules, purpose, and the class object model that underlies them. マークアップ拡張は、XAML 言語、および XAML サービスの .NET 実装の一般的な機能です。Markup extensions are a general feature of the XAML language and of the .NET implementation of XAML services. ここでは、WPF XAML で使用するマークアップ拡張について特に詳しく説明します。This topic specifically details markup extensions for use in WPF XAML.

XAML プロセッサとマークアップ拡張XAML Processors and Markup Extensions

一般に、XAML パーサーは、属性値を、プリミティブに変換できるリテラル文字列として解釈するか、何らかの方法でオブジェクトに変換することができます。Generally speaking, a XAML parser can either interpret an attribute value as a literal string that can be converted to a primitive, or convert it to an object by some means. そのような方法の 1 つは、型コンバーターを参照することです。この方法については、「TypeConverters および XAML」で説明されています。One such means is by referencing a type converter; this is documented in the topic TypeConverters and XAML. しかし、シナリオによっては、別の動作が必要な場合もあります。However, there are scenarios where different behavior is required. たとえば、XAML プロセッサに対して、ある属性値がオブジェクト グラフ内の新しいオブジェクトにならないように指示することがあります。For example, a XAML processor can be instructed that a value of an attribute should not result in a new object in the object graph. 代わりに、その属性を、オブジェクト グラフの別の部分にある既に構築されたオブジェクトに対する参照を行うオブジェクト グラフ、または静的オブジェクトにする必要があります。Instead, the attribute should result in an object graph that makes a reference to an already constructed object in another part of the graph, or a static object. 別のシナリオとして、XAML プロセッサに対して、オブジェクトのコンストラクターに既定以外の引数を渡す構文を使用するように指示する場合もあります。Another scenario is that a XAML processor can be instructed to use a syntax that provides non-default arguments to the constructor of an object. このような種類のシナリオは、マークアップ拡張によって解決できます。These are the types of scenarios where a markup extension can provide the solution.

マークアップ拡張の基本構文Basic Markup Extension Syntax

マークアップ拡張を実装すると、属性の使用でのプロパティ、プロパティ要素の使用でのプロパティ、またはその両方の値を提供できます。A markup extension can be implemented to provide values for properties in an attribute usage, properties in a property element usage, or both.

属性値を提供するために使用する場合、XAML プロセッサでマークアップ拡張シーケンスを区別する構文は、左中かっこと右中かっこ ({ と }) です。When used to provide an attribute value, the syntax that distinguishes a markup extension sequence to a XAML processor is the presence of the opening and closing curly braces ({ and }). その後、マークアップ拡張の種類は、左中かっこの直後の文字列トークンによって識別されます。The type of markup extension is then identified by the string token immediately following the opening curly brace.

プロパティ要素構文で使用する場合、マークアップ拡張は、プロパティ要素値の指定に使用するその他の要素と表示上は同じになります。つまり、山かっこ (<>) で囲まれた、マークアップ拡張クラスを要素として参照する XAML 要素宣言になります。When used in property element syntax, a markup extension is visually the same as any other element used to provide a property element value: a XAML element declaration that references the markup extension class as an element, enclosed within angle brackets (<>).

XAML で定義されたマークアップ拡張機能XAML-Defined Markup Extensions

XAML の WPF 実装に固有ではなく、言語としての XAML の組み込みまたは機能の実装であるマークアップ拡張がいくつか存在します。Several markup extensions exist that are not specific to the WPF implementation of XAML, but are instead implementations of intrinsics or features of XAML as a language. これらのマークアップ拡張は、一般的な .NET Framework XAML サービスの一部として System.Xaml アセンブリで実装され、XAML 言語の XAML 名前空間内にあります。These markup extensions are implemented in the System.Xaml assembly as part of the general .NET Framework XAML services, and are within the XAML language XAML namespace. これらのマークアップ拡張は、一般的なマークアップの使用方法では、通常、x: プレフィックスで識別できます。In terms of common markup usage, these markup extensions are typically identifiable by the x: prefix in the usage. MarkupExtension基本クラス (app.xaml でも定義されています) は、すべてのマークアップ拡張機能が xaml リーダーおよび xaml ライター (WPF xaml など) でサポートされるために使用する必要があるパターンを提供します。The MarkupExtension base class (also defined in System.Xaml) provides the pattern that all markup extensions should use in order to be supported in XAML readers and XAML writers, including in WPF XAML.

  • x:Type は、名前を指定した型の Type オブジェクトを提供します。x:Type supplies the Type object for the named type. この機能は、スタイルとテンプレートで最もよく使用されます。This facility is used most frequently in styles and templates. 詳細については、「x:Type マークアップ拡張機能」を参照してください。For details, see x:Type Markup Extension.

  • x:Static は、静的な値を生成します。x:Static produces static values. この値は、直接的にはターゲット プロパティの値の型ではなくても、その型に評価することができる値型コード エンティティから生成されます。The values come from value-type code entities that are not directly the type of a target property's value, but can be evaluated to that type. 詳細については、「x:Static マークアップ拡張機能」を参照してください。For details, see x:Static Markup Extension.

  • x:Null は、プロパティの値として null を指定し、属性またはプロパティ要素の値として使用できます。x:Null specifies null as a value for a property and can be used either for attributes or property element values. 詳細については、「x:Null マークアップ拡張機能」を参照してください。For details, see x:Null Markup Extension.

  • x:Array は、XAML 構文での一般的な配列の作成をサポートします。WPF 基本要素とコントロール モデルで提供されているコレクションのサポートをあえて使用しない場合に使用します。x:Array provides support for creation of general arrays in XAML syntax, for cases where the collection support provided by WPF base elements and control models is deliberately not used. 詳細については、「x:Array Markup Extension」を参照してください。For details, see x:Array Markup Extension.

注意

x: プレフィックスは、XAML 言語の組み込みに対する標準的な XAML 名前空間マッピングのために、XAML ファイルまたは稼働環境のルート要素で使用します。The x: prefix is used for the typical XAML namespace mapping of the XAML language intrinsics, in the root element of a XAML file or production. たとえば、WPF アプリケーションの Visual Studio テンプレートは、このx:マッピングを使用して XAML ファイルを開始します。For example, the Visual Studio templates for WPF applications initiate a XAML file using this x: mapping. 独自の XAML 名前空間マッピングに別のプレフィックス トークンを選ぶこともできますが、このドキュメントでは、WPF の既定の名前空間や、特定のフレームワークに関連のないその他の XAML 名前空間ではなく、XAML 言語の XAML 名前空間の一部として定義されているエンティティを識別する手段として、既定の x: マッピングを想定します。You could choose a different prefix token in your own XAML namespace mapping, but this documentation will assume the default x: mapping as a means of identifying those entities that are a defined part of the XAML namespace for the XAML language, as opposed to the WPF default namespace or other XAML namespaces not related to a specific framework.

WPF 固有のマークアップ拡張WPF-Specific Markup Extensions

WPF プログラミングで使用される最も一般的なマークアップ拡張には、リソースの参照をサポートするもの (StaticResourceDynamicResource) と、データ バインディングをサポートするもの (Binding) があります。The most common markup extensions used in WPF programming are those that support resource references (StaticResource and DynamicResource), and those that support data binding (Binding).

  • StaticResource は、既に定義されているリソースの値を代入することによって、プロパティの値を提供します。StaticResource provides a value for a property by substituting the value of an already defined resource. StaticResource の評価は、最終的には XAML の読み込み時に行われます。実行時にオブジェクト グラフにアクセスすることはできません。A StaticResource evaluation is ultimately made at XAML load time and does not have access to the object graph at run time. 詳細については、「StaticResource のマークアップ拡張機能」を参照してください。For details, see StaticResource Markup Extension.

  • DynamicResource は、プロパティの値がリソースに対する実行時参照になるように延期することによって、プロパティの値を提供します。DynamicResource provides a value for a property by deferring that value to be a run-time reference to a resource. 動的リソース参照では、そのようなリソースがアクセスされるたびに、強制的に新しいルックアップが行われます。実行時にオブジェクト グラフにアクセスすることもできます。A dynamic resource reference forces a new lookup each time that such a resource is accessed and has access to the object graph at run time. このようなアクセスを実現するために、DynamicResource の概念が、WPF プロパティ システムの依存関係プロパティと、評価された式によってサポートされます。In order to get this access, DynamicResource concept is supported by dependency properties in the WPF property system, and evaluated expressions. したがって、DynamicResource は、依存関係プロパティ ターゲットにのみ使用できます。Therefore you can only use DynamicResource for a dependency property target. 詳細については、「DynamicResource のマークアップ拡張機能」を参照してください。For details, see DynamicResource Markup Extension.

  • Binding は、実行時に親オブジェクトに適用されるデータ コンテキストを使用して、データ バインディングされた値をプロパティに提供します。Binding provides a data bound value for a property, using the data context that applies to the parent object at run time. このマークアップ拡張は、データ バインディングを指定するためにかなりの量のインライン構文を使用できるため、比較的複雑です。This markup extension is relatively complex, because it enables a substantial inline syntax for specifying a data binding. 詳細については、「バインディングのマークアップ拡張機能」を参照してください。For details, see Binding Markup Extension.

  • RelativeSource実行時オブジェクトツリー内Bindingの複数の可能なリレーションシップに移動できるのソース情報を提供します。RelativeSource provides source information for a Binding that can navigate several possible relationships in the run-time object tree. これにより、周囲のオブジェクト ツリーに関する完全な知識がなくても、多目的のテンプレートで作成されるバインド、またはコードで作成されるバインドに対して、特殊なソースを指定することができます。This provides specialized sourcing for bindings that are created in multi-use templates or created in code without full knowledge of the surrounding object tree. 詳細については、「RelativeSource のマークアップ拡張機能」を参照してください。For details, see RelativeSource MarkupExtension.

  • TemplateBinding により、コントロール テンプレートがテンプレート プロパティの値を使用できるようになります。それらの値は、テンプレートを使用するクラスのオブジェクト モデルで定義されたプロパティから取られます。TemplateBinding enables a control template to use values for templated properties that come from object-model-defined properties of the class that will use the template. つまり、テンプレート定義内のプロパティが、テンプレートを適用する場合にのみ存在するコンテキストにアクセスできます。In other words, the property within the template definition can access a context that only exists once the template is applied. 詳細については、「TemplateBinding のマークアップ拡張機能」を参照してください。For details, see TemplateBinding Markup Extension. TemplateBinding の実際の使用方法の詳細については、「ControlTemplate を使用したスタイル設定のサンプル」を参照してください。For more information on the practical use of TemplateBinding, see Styling with ControlTemplates Sample.

  • ColorConvertedBitmap は、比較的高度なイメージング シナリオをサポートします。ColorConvertedBitmap supports a relatively advanced imaging scenario. 詳細については、「ColorConvertedBitmap のマークアップ拡張機能」を参照してください。For details, see ColorConvertedBitmap Markup Extension.

  • ComponentResourceKeyThemeDictionary は、リソースのルックアップをサポートします。特に、カスタム コントロールでパッケージ化されるリソースとテーマを対象としています。ComponentResourceKey and ThemeDictionary support aspects of resource lookup, particularly for resources and themes that are packaged with custom controls. 詳細については、「ComponentResourceKey マークアップ拡張機能」、「ThemeDictionary のマークアップ拡張機能」、「コントロールの作成の概要」を参照してください。For more information, see ComponentResourceKey Markup Extension, ThemeDictionary Markup Extension, or Control Authoring Overview.

*Extension クラス*Extension Classes

一般的な xaml 言語と WPF 固有のマークアップ拡張機能の両方について、各マークアップ拡張機能の動作は、 *ExtensionからMarkupExtension派生しProvideValueたクラスを通じて xaml プロセッサに対して識別され、b.For both the general XAML language and WPF-specific markup extensions, the behavior of each markup extension is identified to a XAML processor through a *Extension class that derives from MarkupExtension, and provides an implementation of the ProvideValue method. 各拡張にあるこのメソッドは、マークアップ拡張の評価時に返されるオブジェクトを提供します。This method on each extension provides the object that is returned when the markup extension is evaluated. 返されるオブジェクトは、通常、マークアップ拡張に渡されたさまざまな文字列トークンに基づいて評価されます。The returned object is typically evaluated based on the various string tokens that are passed to the markup extension.

たとえば、クラスはStaticResourceExtension 、実際のリソース検索の表面実装を提供し、 ProvideValueその実装が要求されたオブジェクトを返すようにします。そのため、特定の実装の入力を、リソースをでx:Key検索します。For example, the StaticResourceExtension class provides the surface implementation of actual resource lookup so that its ProvideValue implementation returns the object that is requested, with the input of that particular implementation being a string that is used to look up the resource by its x:Key. 既存のマークアップ拡張を使用している場合は、この実装の詳細の大部分は重要ではありません。Much of this implementation detail is unimportant if you are using an existing markup extension.

一部のマークアップ拡張では、文字列トークン引数は使用されません。Some markup extensions do not use string token arguments. これは、それらのマークアップ拡張では静的な値や一貫した値が返されるため、または返されるべき値のコンテキストが serviceProvider パラメーターを介して渡されるサービスの 1 つから得られるためです。This is either because they return a static or consistent value, or because context for what value should be returned is available through one of the services passed through the serviceProvider parameter.

*Extension 名前付けパターンは、便宜上のものであり、一貫性を確保するためのものです。The *Extension naming pattern is for convenience and consistency. XAML プロセッサがマークアップ拡張のサポートとしてそのクラスを識別するためには必要ではありません。It is not necessary in order for a XAML processor to identify that class as support for a markup extension. コードベースに .xaml が含まれていて、.NET Framework xaml サービスの実装を使用している場合は、xaml マークアップ拡張機能としてMarkupExtension認識される必要があるのは、から派生し、構築構文をサポートするためです。So long as your codebase includes System.Xaml and uses .NET Framework XAML Services implementations, all that is necessary to be recognized as a XAML markup extension is to derive from MarkupExtension and to support a construction syntax. WPF は、マークアップ拡張機能を定義します。 *ExtensionたとえばBinding、という名前付けパターンに従っていないクラスを有効にします。WPF defines markup extension-enabling classes that do not follow the *Extension naming pattern, for example Binding. 通常、純粋なマークアップ拡張のサポートを超えたシナリオをそのクラスがサポートすることが原因です。Typically the reason for this is that the class supports scenarios beyond pure markup extension support. Binding場合、このクラスは、XAML を使用しないシナリオで、オブジェクトのメソッドおよびプロパティへの実行時アクセスをサポートします。In the case of Binding, that class supports run-time access to methods and properties of the object for scenarios that have nothing to do with XAML.

初期化テキストの拡張クラスの解釈Extension Class Interpretation of Initialization Text

マークアップ拡張名の後に続き、中かっこの内側にある文字列トークンは、次の方法のいずれかで XAML プロセッサに解釈されます。The string tokens following the markup extension name and still within the braces are interpreted by a XAML processor in one of the following ways:

  • コンマは常に個別のトークンの区切りまたは区切り記号を表します。A comma always represents the separator or delimiter of individual tokens.

  • 個別の区切られたトークンに等号が含まれない場合、各トークンはコンストラクター引数として扱われます。If the individual separated tokens do not contain any equals signs, each token is treated as a constructor argument. 各コンストラクター パラメーターは、そのシグネチャで想定される型として、そのシグネチャで想定される適切な順序で指定する必要があります。Each constructor parameter must be given as the type expected by that signature, and in the proper order expected by that signature.

    注意

    XAML プロセッサは、ペアの数の引数の数に一致するコンストラクターを呼び出す必要があります。A XAML processor must call the constructor that matches the argument count of the number of pairs. このため、カスタムマークアップ拡張機能を実装する場合は、同じ引数カウントを持つ複数のコンストラクターを指定しないでください。For this reason, if you are implementing a custom markup extension, do not provide multiple constructors with the same argument count. パラメーターの数が同じマークアップ拡張コンストラクター パスが複数存在する場合の XAML プロセッサの動作は、定義されていません。ただし、マークアップ拡張の型定義がこのような状態になっていると、使用方法に関する例外が XAML プロセッサからスローされる可能性があることを想定しておく必要があります。The behavior for how a XAML processor behaves if more than one markup extension constructor path with the same parameter count exists is not defined, but you should anticipate that a XAML processor is permitted to throw an exception on usage if this situation exists in the markup extension type definitions.

  • 個別に区切られたトークンに等号が含まれている場合、XAML プロセッサは最初にマークアップ拡張機能のパラメーターなしのコンストラクターを呼び出します。If the individual separated tokens contain equals signs, then a XAML processor first calls the parameterless constructor for the markup extension. その後、各 "名前=値" のペアは、マークアップ拡張に存在するプロパティ名、およびそのプロパティに割り当てる値として解釈されます。Then, each name=value pair is interpreted as a property name that exists on the markup extension, and a value to assign to that property.

  • マークアップ拡張でコンストラクターの動作とプロパティの設定の動作の結果が類似している場合は、どちらの動作を使用しても問題はありません。If there is a parallel result between the constructor behavior and the property setting behavior in a markup extension, it does not matter which behavior you use. 複数の設定可能なプロパティを持つマークアップ拡張では、"プロパティ=" のペアの方がよく使用されます。単に、その方がマークアップの意図が明確になり、コンストラクター パラメーターを間違って入れ替える可能性も低いためです。It is more common usage to use the property=value pairs for markup extensions that have more than one settable property, if only because it makes your markup more intentional and you are less likely to accidentally transpose constructor parameters. ("プロパティ=値" のペアを指定すると、それらのプロパティは任意の順序になります。)また、設定可能なプロパティのすべてを設定するコンストラクター パラメーターがマークアップ拡張によって提供されるという保証はありません。(When you specify property=value pairs, those properties may be in any order.) Also, there is no guarantee that a markup extension supplies a constructor parameter that sets every one of its settable properties. たとえば、 Bindingはマークアップ拡張機能であり、プロパティ フォーム=の拡張機能を通じて設定できるプロパティがBinding多数ありますが、パラメーターなしのコンストラクターと1つのコンストラクターのみをサポートしています。初期パスを設定する。For example, Binding is a markup extension, with many properties that are settable through the extension in property=value form, but Binding only supports two constructors: a parameterless constructor, and one that sets an initial path.

  • リテラルのコンマは、エスケープせずにマークアップ拡張に渡すことはできません。A literal comma cannot be passed to a markup extension without escapement.

エスケープ シーケンスとマークアップ拡張Escape Sequences and Markup Extensions

XAML プロセッサによる属性の処理では、マークアップ拡張シーケンスのインジケーターとして中かっこを使用します。Attribute handling in a XAML processor uses the curly braces as indicators of a markup extension sequence. 必要に応じて、空の中かっこペアの後にリテラル中かっこを使用したエスケープ シーケンスを入力することによって、リテラル中かっこ文字の属性値を生成することもできます。It is also possible to produce a literal curly brace character attribute value if necessary, by entering an escape sequence using an empty curly brace pair followed by the literal curly brace. {}エスケープシーケンスマークアップ拡張」を参照してください。See {} Escape Sequence - Markup Extension.

XAML の使用におけるマークアップ拡張の入れ子Nesting Markup Extensions in XAML Usage

複数のマークアップ拡張を入れ子にすることができます。各マークアップ拡張は、最も深いものが最初に評価されます。Nesting of multiple markup extensions is supported, and each markup extension will be evaluated deepest first. たとえば、次のような使用方法があります。For example, consider the following usage:

<Setter Property="Background"  
  Value="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" />  

この使用方法では、x:Static ステートメントが最初に評価され、文字列を返します。In this usage, the x:Static statement is evaluated first and returns a string. この文字列が、DynamicResource の引数として使用されます。That string is then used as the argument for DynamicResource.

マークアップ拡張とプロパティ要素構文Markup Extensions and Property Element Syntax

マークアップ拡張クラスは、プロパティ要素値を設定するオブジェクト要素として使用した場合、XAML で使用可能な通常の型に基づくオブジェクト要素と見た目上は区別できません。When used as an object element that fills a property element value, a markup extension class is visually indistinguishable from a typical type-backed object element that can be used in XAML. 通常のオブジェクト要素とマークアップ拡張の実用上の違いは、マークアップ拡張は、型指定された値に評価されるか、式として処理が遅延されるかのどちらかであることです。The practical difference between a typical object element and a markup extension is that the markup extension is either evaluated to a typed value or deferred as an expression. したがって、マークアップ拡張のプロパティ値について発生する可能性のある型エラーのメカニズムは異なります。これは、他のプログラミング モデルにおける遅延バインディング プロパティの処理方法と似ています。Therefore the mechanisms for any possible type errors of property values for the markup extension will be different, similar to how a late-bound property is treated in other programming models. 通常のオブジェクト要素では、XAML が解析される時点で、そのオブジェクト要素が設定しているターゲット プロパティに対して型の一致が評価されます。An ordinary object element will be evaluated for type match against the target property it is setting when the XAML is parsed.

ほとんどのマークアップ拡張は、プロパティ要素を指定するオブジェクト要素構文で使用される場合、内側にコンテンツや他のプロパティ要素構文を含みません。Most markup extensions, when used in object element syntax to fill a property element, would not have content or any further property element syntax within. このため、オブジェクト要素タグを閉じ、子要素は指定しません。Thus you would close the object element tag, and provide no child elements. オブジェクト要素が XAML プロセッサで検出されるたびに、そのクラスのコンストラクターが呼び出され、解析した要素から作成されたオブジェクトがインスタンス化されます。Whenever any object element is encountered by a XAML processor, the constructor for that class is called, which instantiates the object created from the parsed element. マークアップ拡張クラスは変わりません。オブジェクト要素構文でマークアップ拡張機能を使用できるようにするには、パラメーターなしのコンストラクターを指定する必要があります。A markup extension class is no different: if you want your markup extension to be usable in object element syntax, you must provide a parameterless constructor. 既存のマークアップ拡張の中には、有効な初期化のために指定する必要のある必須プロパティ値を少なくとも 1 つ持っているものがあります。Some existing markup extensions have at least one required property value that must be specified for effective initialization. その場合、通常、そのプロパティ値はオブジェクト要素のプロパティ属性として指定します。If so, that property value is typically given as a property attribute on the object element. XAML 名前空間 (x:)言語機能WPF XAML 拡張機能のリファレンスページ、必須プロパティを持つマークアップ拡張機能 (および必要なプロパティの名前) に注意してください。In the XAML Namespace (x:) Language Features and WPF XAML Extensions reference pages, markup extensions that have required properties (and the names of required properties) will be noted. これらのリファレンス ページでは、特定のマークアップ拡張でオブジェクト要素構文と属性構文のどちらかが使用できないケースについても説明します。Reference pages will also note if either object element syntax or attribute syntax is disallowed for particular markup extensions. 特に注意する必要があるケースは、x:Array マークアップ拡張です。このマークアップ拡張では、配列の内容をタグ設定の内側にコンテンツとして指定する必要があるため、属性構文をサポートできません。A notable case is x:Array Markup Extension, which cannot support attribute syntax because the contents of that array must be specified within the tagging as content. 配列の内容は一般的なオブジェクトとして扱われるため、属性に対する既定の型コンバーターは使用できません。The array contents are handled as general objects, therefore no default type converter for the attribute is feasible. また、x:Array マークアップ拡張には type パラメーターが必要です。Also, x:Array Markup Extension requires a type parameter.

関連項目See also