原文
WPF Localization Guidance 「Rick StrahlとMichele Leroux Bustamante(2009年6月)」の和訳です。地域設定の実装の参考にしてください。
関連ファイル
Resxリソースのために、ユーザー定義したマークアップ拡張機能
Custom Markup Extensions for Resx Resources
あなたが、x:Static結合構文が提供するよりも、より多くのコントロールが欲しい場合、 あなたは、あなた自身の手で結合を持ち、そして、ユーザー定義したマークアップ拡張機能を作成することができます。 それは、追加の機能を提供します。
あなたは、いくつかのStaticExtensionで使用できない、ユーザー定義したマークアップ拡張機能で、以下を処理することができます:
この白書に添付されて含まれている、WpfControlsサンプル・プロジェクトは、ResExtensionマークアップ拡張機能を提供します。 それは、上記の機能を実装しています。これは、リソース結合のための、ユーザー定義したマークアップ拡張機能の機能を説明する、ユーザー定義した実装です。 しかし、これは、あなたが、どのように、この作業を実行できる、ただ1つの例にすぎないことを理解してください。 あなたが、オンラインで検索した場合、あなたは、何十もの利用できるWPFの地域設定の異なるマークアップ拡張機能を見つけることができます。 それで、ここで提供される拡張子が、あなたの気を引かない場合、あなたに、利用できる他の選択肢があります。 それにもかかわらず、あなたは、いくつかの共通原理を使用し共有する、ここで取り扱う、Resxための、すべてのマークアップ拡張機能とResExtensionを見つけ出すでしょう。
なぜなら、ユーザー定義したマークアップ拡張機能は、また、多くの処理と同じように、x:Static拡張子のようなマークアップ拡張機能です。: あなたは、更に、個々のプロパティに、リソースを手動でマッピングする必要があります。そして、XAMLで、それぞれの要素プロパティに、マークアップ構文を割り当てます。
ResExtensionを使用しているページに、地域設定された値を埋め込みます。あなたは、まず、名前空間とアセンブリが含まれている必要があります。:
あなたは、一度に、この一つのラベル要素に詰め込む、次に示すマークアップ構文バージョンのどれでも使用し構成することができます。:
<Label x:Name="lblResxHelloWorldMarkupExtension1Value"
content="{res:Res Id=HelloWorld,Default=Hello#}"
Margin="{res:Res Id=HelloWorldMargin,Default=10}"
Width="{res:Res Id=HelloWorldWidth,
ResourceSet=WpfClickOnce.MyFormRes,
Default=50}" />
このマークアップ拡張機能は、ResourceManagerを構成します。 そして、参照するためのリソース・キーとして、IDプロパティを使用します。 拡張子は、さらに、ほぼ同じ方法で、厳格に型指定されたリソース・オブジェクトへの、直接アクセスをサポートします。 同様に、x:Staticは、動作しますが、拡張子による後処理を提供します。それで、あなたは、型変換することができます。 厳格に型指定されたリソースを使用する構文は、リソースを識別し結合するために、IDの代わりに静的な属性を使用します。 ここに、Static構文を使用している同じラベルがあります。
<Window
…
xmlns:res="http://www.west-wind.com/WpfControls"
xmlns:props="clr-namespace:WpfClickOnce.Properties"
xmlns:local="clr-namespace:WpfClickOnce"
…
>
<Label x:Name="lblResxHelloWorldMarkupExtension1Value"
content="{res:Res Static=props:Resources.HelloWorld,Default=Hello#}"
Margin="{res:Res Static=props:Resources.HelloWorldMargin,Default=10}"
Width="{res:Res Static=local:MyFormRes.HelloWorldWidth, Default=50}" />
あなたが、Resxリソースを使用している場合、そして、あなたは、後者の方法が望ましい、利用できる厳格に型指定されたクラスを持っています。 なぜなら、それは、一部の結合のように、アセンブリとリソースの設定をインクルードする必要をなくします。 前者の方法は、役に立ちます。 あなたが、既定のResourceManagerと結合することを望まない場合、たとえば、現在のUICulture以外のカルチャを提示している要素をサポートします。
ResExtensionは、静的、あるいは、IDが必要とされますが、Figure 19に示される、多数のパラメータをサポートしています。
FIGURE 19:.ResExtensionマークアップ拡張機能のためのパラメータ
Markup Parameter
Id
リソース・キーは、ResourceManagerを使用して読み込まれるリソースに、識別されます。
Static
あなたは、StaticExtensionのような、同じ構文を使用して、厳格に型指定されたリソースを示すことができます。 リソース値を取得するために、厳格に型指定されたリソースを使用します。 しかし、(例えば)文字列変換のための後処理もまた適用されます。この構文を使用するとき、ResourceSetとアセンブリ名は無視されます。
例:Static=properties:Resources.Helloworld
ResourceSet
リソース・セットの名前は、結合されます。これは、既定の名前空間のアセンブリ内の、コンパイルされたリソースの名前です。 加えたパスは、さらにピリオド(.)によって切り離される、Resxファイルの名前を加えられます。 既定のリソース設定が省略される場合、あなたが、提供したものが使用されます。
例:ResourceSet=WpfLocalization.Properties.Resources
Assembly
アセンブリの名前やプレインストールされているアセンブリのIDは、特別なアセンブリでリソースに結合できます。 あなたが、マークアップ拡張機能を使用している、複数のプロジェクトを持っている場合にのみ必要です。 指定していない場合、起動アセンブリやLocalizationSettings.DefaultResourceAssemblyが、使用されます。
例:Assembly=MyControlLibrary
Default
値が見つからない、あるいは、結合エラーが発生する場合、既定の値が表示されます。 マークアップ拡張機能が、リソースやリソースの設定を見つけられないとき、この値は、同様に、デザイナーで使用されます。 あなたは、常に、設計や実行時エラーを避けるために、この値を与える必要があります。
Format
変換された値は、書式設定された文字列に埋め込まれます。
Converter
値を変換するために使用される、明示された型コンバータ。指定しない場合、プロパティの既定の型コンバータが使用されます。
ResourceSetとおそらくAssemblyは、ID結合を使用するときのみ必要とされます。 ID結合は、それ自身のResourceManagerインスタンスを効果的に作成し、それらをキャッシュに格納します。 ResourceSetとAssemblyを読み込むために、適切なResourceManagerを見つけ出すことが必要です。Setを指定する必要があります。 Static結合が使用される時、厳格に型指定されたリソースクラスは、アクセスするために、 含まれているResourceManagerのインスタンスを参照するので、ResourceSetとAssemblyは無視されます。
ResExtensionは、同様に、失敗するのではなく、既定の値を表示することで結合の失敗に対処します。 アプリケーションが実行時に、リソースに関する問題に陥ることは、珍しくありません。 それは、多くの場合、コンパイル時や、さらに、ユーザーインターフェースの検証の間に捕まえるのが困難です。 むしろ欠点よりも、拡張機能はエラーを捕えて、代わりに既定の値を表示します。 お望みならば、あなたは、同様に、作成することができます。 それで既定の値は、リソースが正しく読み込まれなかったことを示すために、ある種の区切り文字を表示します。 しかし、少なくとも、あなたのアプリケーションは、そのために壊れることはないでしょう。 また、既定の値は、Visual StudioとBlendデザイナーのために重要です。 それは、常に、リソースにアクセスする可能性はなく、むしろ失敗し、既定の値を表示します。 これは、特に、例のように、サテライト・アセンブリからリソースを表示することができないBlendに当てはまります。
この拡張機能の他の大きな利点は、あなたが、XAML属性で使用する同じ方法で、文字列以外のプロパティのために、リソースの文字列の値を使用することができることです。 マークアップ拡張機能がValueConverterを適用するため、文字列は対応するXAMLプロパティ型に変換されます。 上記の例では、MarginとWidthは、結合されており、そして、これらは、文字列ではないプロパティです。 (ThicknessとDoubleそれぞれ)、しかし、単純な文字列としてリソースファイルに保存されます。( 10と50は、それぞれ、Figure 20に示します)。
FIGURE 20:
ユーザー定義した拡張機能は、Resxファイルの中の文字列ではないプロパティのために、結合するとき、ValueConverterを使用して、 値を自動的に変換することにより、文字列の値を保存することができます。
プロパティ値内の区切り文字に注意してください。
Watch out for Separator Characters in Property Values
あなたは、おそらく、あなたは、区切り文字で区切られた複数の値を指定できる、MarginとPaddingのような特定のプロパティを知っています。 例えば、あなたは、コンマが区切り文字である、Margin="10,5,10,10"で、それぞれの境界線の余白を指定します。 あなたは、異なるカルチャで、これらの区切り文字を変更することは、知らないかもしれません。 最後の行に表示される値が、en-USで動作するしている間、それは、de-DEではありません。 なぜなら、コンマは、ドイツ語でDouble Margin値で小数点のように扱われます。 あなたが、既定の設定カルチャで、10,5,10,10を、そして、特定な地域設定していないドイツ語版で、10;5;10;10を適用する場合、あなたは、ランタイム・エラーを手に入れます。
MarginとPaddingのような、地域設定された値を使用するとき、あなたが、特に実行時に、それぞれのカルチャを注意深く確認するために、 それらを使用する場合、リソース代替システムが動作するとき、区切り文字使用をできるだけ避けるようにしてください。
あなたが、コントロールのライブラリ・プロジェクトとあなたの中心となるアプリケーションのような、あなたのアプリケーションの1つ以上のアセンブリのマークアップ拡張機能を使用する場合、 Assembly属性だけが必要です。マークアップ拡張機能が、特別な内容なしで読み込まれるため、それは、ID結合を使用する時、リソースを読み込む場所は、暗黙的にはわかりません。
この理由のため、静的なLocalizationSettingsクラスがあります。それは、既定のリソースの位置を与えるために使用されます。そして、また、ResourceSetがない場合、既定のResourceManagerが提供されます。マークアップ拡張機能は、ロジックが含まれています。それは、自動的に、既定のリソース・アセンブリとResourceManagerを探します。 ほとんどの独立したWPFアプリケーションで、構成は必要とされていません。しかし、あなたは、また、アプリケーションの起動で、これらの設定を手動で構成することができます。:
public App()
{
InitializeComponent();
// Explicitly initialize the resource manager
// 明示的に、リソースマネージャを初期化します。
LocalizationSettings.Initialize(this.GetType().Assembly,
WpfLocalization.Properties.Resources.ResourceManager);
LocalizationSettings.AddAssembly("WpfControls", typeof(ResExtension).Assembly);
}
Visual StudioとBlendデザイナーが、このコードを実行しないことに注意します。 それで、あなたが、リソースために、標準ではない位置を使用する場合、デザイナーは、それらのリソースを表示しないでしょう。 そして、既定の値やリソース・キーを表示することを元に戻します。これは、これらの既定の値が役に立つ場所です。 あなたの格納したリソースは、デザイナーが、更に、表示する既定の値を変更します。 既定では、デザイナーでResExtensionは、中心となるWPFアプリケーションでのみ利用可能なリソースを使用しようとします。 内部では、それは、ロードしたアセンブリを少しずつ動かすために、アプリケーションのインスタンスを見つけようとする必要があります。 ユーザー定義したマークアップ拡張機能とリソースのためのデザイナーの支援は、厄介な問題です。 そして、あなたは、ResExtension.FindDefaultResourceAssemblyメソッドで、既定のリソース・アセンブリを取得するロジックを調べることができます。
特にBlendのデザイナーの不安定さのため、既定の値は、もう1度、とても重要になります。 あなたは、常に、既定の値を指定します。それで、あなたは、デザイナーで表示されると期待される値が見られることが保証されます。