TypeConverters と XAML
このトピックでは、一般的な XAML 言語機能としての文字列からの型変換の目的について説明します。 .NET Framework では、TypeConverter クラスは、XAML 属性の使用でプロパティ値として使用できるマネージド カスタム クラスの実装の一部として特定の目的を果たします。 カスタム クラスを記述し、クラスのインスタンスを XAML 設定可能な属性値として使用できるようにする場合は、クラスに TypeConverterAttribute を適用するか、カスタム TypeConverter クラスを記述するか、またはその両方を記述する必要があります。
型変換の概念
XAML と文字列の値
XAML ファイルで属性値を設定すると、その値の初期型は純粋なテキストの文字列になります。 Double などの他のプリミティブも、最初は XAML プロセッサへのテキスト文字列です。
XAML プロセッサでは、属性値を処理するために 2 つの情報が必要です。 最初の情報は、設定されているプロパティの値型です。 属性値を定義し、XAML で処理される文字列は、最終的にその型の値に変換または解決する必要があります。 値が XAML パーサーによって認識されるプリミティブ (数値など) の場合は、文字列の直接変換が試行されます。 値が列挙体の場合、その列挙体の名前付き定数と名前が一致するかどうかを確認するために文字列が使用されます。 値がパーサーが認識するプリミティブでも列挙型でもない場合、対象の型は、変換された文字列に基づいて型のインスタンスまたは値を提供できる必要があります。 これは、型コンバーター クラスを示すことによって行われます。 型コンバーターは、XAML シナリオと .NET コードでのコード呼び出しの両方で、別のクラスの値を提供するためのヘルパー クラスです。
XAML での既存の型変換動作の使用
基になる XAML の概念に関する知識によっては、認識せずに基本的なアプリケーション XAML で型変換動作を既に使用している可能性があります。 たとえば、WPF では、Point型の値を受け取る何百ものプロパティがリテラルで定義されます。 Point は 2 次元座標空間内の座標を記述する値であり、実際には X と Yの 2 つの重要なプロパティがあります。XAML でポイントを指定する場合は、指定した X と Y 値の間に区切り記号 (通常はコンマ) を含む文字列として指定します。 例: <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"/>
.
この単純な型の Point と XAML での単純な使用方法にも、型コンバーターが含まれます。 この場合、クラス PointConverterです。
クラス レベルで定義 Point の型コンバーターは、Pointを受け取るすべてのプロパティのマークアップの使用を合理化します。 ここに型コンバーターがない場合は、前に示したのと同じ例に対して、次のはるかに詳細なマークアップが必要になります。
<LinearGradientBrush>
<LinearGradientBrush.StartPoint>
<Point X="0" Y="0"/>
</LinearGradientBrush.StartPoint>
<LinearGradientBrush.EndPoint>
<Point X="1" Y="1"/>
</LinearGradientBrush.EndPoint>
</LinearGradientBrush>
型変換文字列を使用するか、より詳細な同等の構文を使用するかは、通常、コーディング スタイルの選択です。 XAML ツール ワークフローは、値の設定方法にも影響する場合があります。 一部の XAML ツールでは、デザイナー ビューや独自のシリアル化メカニズムへのラウンド トリップが簡単であるため、マークアップの最も詳細な形式が出力される傾向があります。
通常、既存の型コンバーターは、適用された TypeConverterAttributeの存在をクラス (またはプロパティ) で確認することで、WPF および .NET Framework 型で検出できます。 この属性は、その型の値をサポートする型コンバーターであるクラスに、XAML の目的や他の目的で名前を付けます。
型コンバーターとマークアップ拡張
マークアップ拡張と型コンバーターは、XAML プロセッサの動作と、それらが適用されるシナリオの観点から直交ロールを満たします。 マークアップ拡張機能の使用にはコンテキストを使用できますが、マークアップ拡張機能が値を提供するプロパティの型変換動作は、通常、マークアップ拡張機能の実装ではチェックされません。 つまり、マークアップ拡張機能がテキスト文字列を ProvideValue
出力として返した場合でも、特定のプロパティまたはプロパティ値型に適用された文字列に対する型変換動作は呼び出されません。一般に、マークアップ拡張機能の目的は、文字列を処理し、型コンバーターを使用せずにオブジェクトを返すということです。
型コンバーターではなくマークアップ拡張が必要になる一般的な状況の 1 つは、既に存在するオブジェクトへの参照を作成することです。 ステートレス型コンバーターでは、新しいインスタンスしか生成できなかったため、望ましくない可能性があります。 マークアップ拡張機能の詳細については、「マークアップ拡張機能と WPF XAML」を参照してください。
ネイティブ型コンバーター
XAML パーサーの WPF および .NET Framework の実装では、ネイティブ型変換処理を持つ特定の型がありますが、従来はプリミティブと考えられる型ではありません。 このような型の例として、DateTimeがあります。 その理由は、.NET Framework アーキテクチャのしくみに基づいています。DateTime 型は、.NET で最も基本的なライブラリである mscorlib で定義されています。 DateTime 依存関係を導入する別のアセンブリからの属性 (TypeConverterAttribute は System からの属性) を使用して属性付けすることは許可されていないため、属性付けによる通常の型コンバーター検出メカニズムはサポートされません。 代わりに、XAML パーサーには、このようなネイティブ処理を必要とする型の一覧があり、真のプリミティブの処理方法と同様に処理されます。 (DateTime の場合、これには Parseの呼び出しが含まれます)。
型コンバーターの実装
型変換
前述の Point 例では、PointConverter クラスについて説明しました。 XAML の .NET 実装の場合、XAML の目的で使用されるすべての型コンバーターは、基底クラスから派生するクラス TypeConverterです。 TypeConverter クラスは、XAML の存在に先行する .NET Framework のバージョンに存在しました。元の使用法の 1 つは、ビジュアル デザイナーのプロパティ ダイアログに文字列変換を提供するというものでした。 XAML の場合、TypeConverter のロールが拡張され、文字列への変換と文字列からの変換の基本クラスが含まれます。これにより、文字列属性値の解析が可能になり、場合によっては特定のオブジェクト プロパティの実行時値が属性としてシリアル化される文字列に処理されます。
TypeConverter では、XAML 処理の目的で文字列との間の変換に関連する 4 つのメンバーを定義します。
これらの中で最も重要な方法は ConvertFromです。 このメソッドは、入力文字列を必要なオブジェクト型に変換します。 厳密に言えば、ConvertFrom メソッドは、はるかに広い範囲の型をコンバーターの目的の変換先型に変換するために実装でき、ランタイム変換のサポートなどの XAML を超える目的に役立ちますが、XAML の目的では、重要な String 入力を処理できるコード パスにすぎません。
次に最も重要な方法は ConvertToです。 アプリケーションがマークアップ表現に変換された場合 (たとえば、XAML にファイルとして保存されている場合)、ConvertTo はマークアップ表現を生成します。 この場合、XAML にとって重要なコード パスは、String の destinationType
を渡すときです。
CanConvertTo と CanConvertFrom は、サービスが TypeConverter 実装の機能を照会するときに使用されるサポート メソッドです。 コンバーターの同等の変換メソッドがサポートする型固有のケースの true
を返すには、これらのメソッドを実装する必要があります。 XAML の場合、これは通常、String 型を意味します。
XAML のカルチャ情報および型コンバーター
各 TypeConverter 実装では、変換の有効な文字列を構成するものを独自に解釈でき、パラメーターとして渡される型の説明を使用または無視することもできます。 カルチャと XAML 型変換に関して重要な考慮事項があります。 ローカライズ可能な文字列を属性値として使用することは、XAML で完全にサポートされています。 ただし、XAML 属性値の型コンバーターには必ずしも固定言語の解析動作が必要であり、en-US
カルチャを使用するため、特定のカルチャ要件を持つ型コンバーター入力としてローカライズ可能な文字列を使用することはサポートされていません。 この制限の設計上の理由の詳細については、XAML 言語仕様 ([MS-XAML]を参照してください。
カルチャが問題になる可能性がある例として、一部のカルチャでは、数値の小数点区切り記号としてコンマを使用します。 これは、WPF XAML 型コンバーターの多くが持つ動作と競合します。これは、区切り記号としてコンマを使用することです (一般的な X、Y 形式、コンマ区切りリストなどの過去の優先順位に基づく)。 周囲の XAML でカルチャを渡しても (Language
または xml:lang
を sl-SI
カルチャに渡しても、この方法で 10 進数にコンマを使用するカルチャの例)、問題は解決されません。
ConvertFrom の実装
XAML をサポートする TypeConverter 実装として使用できるようにするには、そのコンバーターの ConvertFrom メソッドで、value
パラメーターとして文字列を受け入れる必要があります。 文字列が有効な形式で、TypeConverter 実装によって変換できる場合、返されるオブジェクトは、プロパティで予期される型へのキャストをサポートする必要があります。 それ以外の場合、ConvertFrom 実装は null
を返す必要があります。
各 TypeConverter 実装では、変換の有効な文字列を構成するものを独自に解釈でき、パラメーターとして渡される型の説明やカルチャ コンテキストを使用または無視することもできます。 ただし、WPF XAML 処理では、すべてのケースで型記述コンテキストに値が渡されない場合があり、また、xml:lang
に基づいてカルチャを渡さない場合もあります。
手記
文字列形式の可能な要素として、中かっこ (特に {) を使用しないでください。 これらの文字は、マークアップ拡張シーケンスのエントリおよび終了として予約されています。
ConvertTo の実装
ConvertTo は、シリアル化のサポートに使用される可能性があります。 カスタム型とその型コンバーターの ConvertTo によるシリアル化のサポートは、絶対要件ではありません。 ただし、コントロールを実装する場合、またはクラスの機能または設計の一部としてシリアル化を使用する場合は、ConvertToを実装する必要があります。
XAML をサポートする TypeConverter 実装として使用できるようにするには、そのコンバーターの ConvertTo メソッドは、value
パラメーターとしてサポートされている型 (または値) のインスタンスを受け入れる必要があります。 destinationType
パラメーターが String型の場合、返されるオブジェクトを Stringとしてキャストできる必要があります。 返される文字列は、value
のシリアル化された値を表す必要があります。 理想的には、選択するシリアル化形式は、その文字列が同じコンバーターの ConvertFrom 実装に渡された場合、情報を大幅に失うことなく、同じ値を生成できる必要があります。
値をシリアル化できない場合、またはコンバーターがシリアル化をサポートしていない場合、ConvertTo 実装は null
を返す必要があり、この場合は例外をスローできます。 ただし、例外をスローする場合は、CanConvertTo 実装の一部としてその変換を使用できないことを報告して、例外を回避するために最初に CanConvertTo で確認するベスト プラクティスがサポートされるようにする必要があります。
パラメーター destinationType
型 Stringでない場合は、独自のコンバーター処理を選択できます。 通常、基本実装の処理に戻ります。この処理は、最も基本的な ConvertTo で特定の例外を発生させます。
CanConvertTo の実装
CanConvertTo 実装では、String型のdestinationType
に対してtrue
を返し、それ以外の場合は基本実装に委ねる必要があります。
CanConvertFrom の実装
CanConvertFrom 実装では、型 Stringの sourceType
の true
を返し、それ以外の場合は、基本実装を使用する必要があります。
TypeConverterAttribute の適用
カスタム型コンバーターを XAML プロセッサによるカスタム クラスの動作型コンバーターとして使用するには、クラス定義に TypeConverterAttribute を適用する必要があります。 属性を使用して指定する ConverterTypeName は、カスタム型コンバーターの型名である必要があります。 この属性を適用すると、XAML プロセッサがプロパティ型がカスタム クラス型を使用する値を処理するときに、文字列を入力してオブジェクト インスタンスを返すことができます。
プロパティごとに型コンバーターを提供することもできます。 クラス定義に TypeConverterAttribute を適用する代わりに、プロパティ定義 (その中の get
/set
実装ではなく、メイン定義) に適用します。 プロパティの型は、カスタム型コンバーターによって処理される型と一致する必要があります。 この属性を適用すると、XAML プロセッサがそのプロパティの値を処理するときに、入力文字列を処理してオブジェクト インスタンスを返すことができます。 プロパティごとの型コンバーター手法は、Microsoft .NET Framework またはクラス定義を制御できず、そこに TypeConverterAttribute を適用できない他のライブラリからプロパティ型を使用する場合に特に便利です。
関連項目
- TypeConverter
- WPF 内の XAML
- マークアップ拡張機能と WPF XAML
- XAML 構文の詳細
.NET Desktop feedback