Home > C# > 目的別資料 > 地域設定

Resxリソースのために、ユーザー定義したマークアップ拡張機能

WPFのための地域設定の手引き Localization Guidance for WPF

原文

WPF Localization Guidance 「Rick StrahlとMichele Leroux Bustamante(2009年6月)」の和訳です。
地域設定の実装の参考にしてください。

関連ファイル

Resxリソースのために、ユーザー定義したマークアップ拡張機能

Custom Markup Extensions for Resx Resources

あなたが、x:Static結合構文が提供するよりも、より多くのコントロールが欲しい場合、 あなたは、あなた自身の手で結合を持ち、そして、ユーザー定義したマークアップ拡張機能を作成することができます。 それは、追加の機能を提供します。

あなたは、いくつかのStaticExtensionで使用できない、ユーザー定義したマークアップ拡張機能で、以下を処理することができます:

  • ユーザー定義したResourceManagerか、厳格に型指定されたリソースのどちらかを使用します。
  • あなたが、文字列以外のプロパティと一緒に文字列の値を使用できように、型変換を処理します。
  • 結合が失敗した時のために、既定の設定値を与えます。
  • 書式設定された文字列を使用します。
  • 動的にカルチャを検出し、変更します。そして、実行時に、ユーザーインターフェースを更新します。
  • この白書に添付されて含まれている、WpfControlsサンプル・プロジェクトは、ResExtensionマークアップ拡張機能を提供します。 それは、上記の機能を実装しています。これは、リソース結合のための、ユーザー定義したマークアップ拡張機能の機能を説明する、ユーザー定義した実装です。 しかし、これは、あなたが、どのように、この作業を実行できる、ただ1つの例にすぎないことを理解してください。 あなたが、オンラインで検索した場合、あなたは、何十もの利用できるWPFの地域設定の異なるマークアップ拡張機能を見つけることができます。 それで、ここで提供される拡張子が、あなたの気を引かない場合、あなたに、利用できる他の選択肢があります。 それにもかかわらず、あなたは、いくつかの共通原理を使用し共有する、ここで取り扱う、Resxための、すべてのマークアップ拡張機能とResExtensionを見つけ出すでしょう。

    なぜなら、ユーザー定義したマークアップ拡張機能は、また、多くの処理と同じように、x:Static拡張子のようなマークアップ拡張機能です。: あなたは、更に、個々のプロパティに、リソースを手動でマッピングする必要があります。そして、XAMLで、それぞれの要素プロパティに、マークアップ構文を割り当てます。

    ResExtensionを使用しているページに、地域設定された値を埋め込みます。あなたは、まず、名前空間とアセンブリが含まれている必要があります。:

  • あなたのプロジェクトの参照に、WpfControlsプロジェクトやアセンブリを追加します。
  • あなたのドキュメント・ヘッダに、xmlns:res=http://www.west-wind.com/WpfControls 名前空間を追加します。 (あなたは、あなたが好きな、どんな名前空間接頭辞でも使うことができます)、ここでは、「res」が使用されます。
  • あなたは、一度に、この一つのラベル要素に詰め込む、次に示すマークアップ構文バージョンのどれでも使用し構成することができます。:

    
    <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を使用して、 値を自動的に変換することにより、文字列の値を保存することができます。

    FIGURE 20

    プロパティ値内の区切り文字に注意してください。
    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度、とても重要になります。 あなたは、常に、既定の値を指定します。それで、あなたは、デザイナーで表示されると期待される値が見られることが保証されます。

    このエントリーをはてなブックマークに追加

    Home PC C# Illustration

    Copyright (C) 2011 Horio Kazuhiko(kukekko) All Rights Reserved.
    kukekko@gmail.com
    ご連絡の際は、お問い合わせページのURLの明記をお願いします。
    「掲載内容は私自身の見解であり、所属する組織を代表するものではありません。」