2013-02-06 7 views
9

私はテキスト変換クラスから翻訳されたテキストを提供するWPF MarkupExtensionクラスを作成しようとしています。翻訳はうまくいきますが、翻訳されたテキストを返すためにテキストキーを使用した静的メソッド呼び出しが必要です。このように:DataBinding値を使用するMarkupExtension

ImportLabel.Text = Translator.Translate("import files"); 
// will be "Dateien importieren" in de or "Import files" in en 

その専門は、より良い言葉を提供するためにカウント値を受け入れることです。

ImportLabel.Text = Translator.Translate("import n files", FileCount); 
// will be "Import 7 files" or "Import 1 file" 

もう1つの例:4分以上かかる場合は、1分かかる場合とは異なる単語です。 WPFで今

Translator.Translate("minutes", numberOfMinutes) 
// will be "minute" if it's 1, and "minutes" for anything else 

:テキストキー「分」場合は、任意の数の1のカウントのための「分」として「Minuten」と定義され、以下のメソッド呼び出しが使用する権利の単語を返します。 XAMLコードがたくさんあり、多くのリテラルテキストが含まれています。ナッツを取得せずに翻訳できるようにするには、テキストキーを渡すことができるマークアップ拡張機能が必要で、実行時に翻訳されたテキストが返されます。この部分はかなり簡単です。 MarkupExtensionを継承するクラスを作成し、テキストキーを引数として受け入れるコンストラクターを追加し、それをプライベートフィールドに格納し、そのProvideValueメソッドが格納されたキーの変換テキストを返すようにします。

実際の問題は次のとおりです。マークアップ拡張がデータバインドされ、カウント値が変更されたときに翻訳テキストが更新されるようにカウント値を受け入れるにはどうすればよいですか?

それはこのように使用する必要がありますてFileCount変更の

<TextBlock Text="{t:Translate 'import files', {Binding FileCount}}"/> 

たび結合値、のTextBlockは、変更を反映し、まだ良い文言を提供するために、新しいテキスト値を受け取る必要があります。

私はそこに似たような解決策を見つけました:http://blogs.microsoft.co.il/blogs/tomershamam/archive/2007/10/30/wpf-localization-on-the-fly-language-selection.aspx私はそれを追いかけようとするほど難しいですが、それが何であるか、それがなぜ機能するのか理解できません。すべてがWPF内部で起こっているようですが、提供されたコードは正しい方向にプッシュするだけですが、その方法は不明です。私は何か有用なことをするための私の適応を得ることができません。

実行時に翻訳言語を変更することが有用かどうかはわかりません。私はそれのために別のレベルのバインディングが必要だと思います。複雑さを低く抑えるために、私は基本バージョンが動作するまでこれを行うつもりはありません。

現時点ではコードは表示されません。単に恐ろしい状態にあり、例外を投げたり、何かを翻訳したりしていない唯一のことです。単純な例は非常に歓迎されます(このようなことが存在する場合)。

+0

私はこのシナリオで 'IValueConverter'が' MarkupExtension'よりもうまくいくと思います。 –

+0

どのように見えますか? ''?後方に少しタイプします。実行時に言語辞書を変更できるようにしたいのであれば、バインディングも必要でしょうか? – ygoe

答えて

15

Nevermind、私はついに、参照されたコードがどのように機能し、解決策が出てくるかを見出しました。ここでは、レコードの簡単な説明だけです。

<TextBlock Text="{t:Translate 'import files', {Binding FileCount}}"/> 

これは二つのパラメータ、1つのストリングと一つの結合を受け入れるコンストラクタとMarkupExtensionから継承クラスTranslateExtensionを必要とします。両方の値をインスタンスに格納します。次に、クラスのProvideValueメソッドは、取得したバインディングを使用してカスタムコンバータインスタンスを追加し、BindingExpressionインスタンスIIRCであるbinding.ProvideValueから結果を返します。

public class TranslateExtension : MarkupExtension 
{ 
    public TranslateExtension(string key, Binding countBinding) 
    { 
     // Save arguments to properties 
    } 
    public override object ProvideValue(IServiceProvider serviceProvider) 
    { 
     countBinding.Converter = new TranslateConverter(key); 
     return countBinding.ProvideValue(serviceProvider); 
    } 
} 

コンバータは、クラスTranslateConverterの言う、一つのパラメータ、文字列を受け取るコンストラクタを持っています。上記のTranslateExtensionの主な議論です。それは後でそれを覚えています。

Count値が変更されると(バインディングが発生するたびに)、WPFはその値を新たに要求します。バインディングの元から、コンバーターを経て、表示されているサーフェイスまで歩いているようです。コンバーターを使用することで、バインディングについては何も心配する必要はありません。コンバーターはメソッドの引数としてバインディングの現在の値を取得し、別のものを返すことが予想されるためです。カウント値(int)、変換されたテキスト(文字列)out。これは私のコードです。

変換されたテキストに数値を適応させるのはコンバーターの仕事です。それはそのために格納されたテキストキーを使用します。だから何が起こるかは、基本的には逆のデータフローです。メインの情報であるテキストキーとそれに追加されるカウント値の代わりに、カウント値をプライマリ情報として扱い、テキストキーをサイドパラメータとして使用して全体を作成する必要があります。これは正確ではありませんが、バインディングが主なトリガーである必要があります。キーは変更されないため、コンバーターのインスタンスでキーを保存することができます。そして、翻訳されたテキストのすべての出現はでプログラムの個々のキーを使用して、コンバータの独自のコピー、それぞれを取得し

これは、コンバータは、のように見えることができるものである:魔法だ

class TranslateConverter : IValueConverter 
{ 
    private string key; 
    public TranslateConverter(string key) 
    { 
     this.key = key; 
    } 
    public object Convert(object value, ...) 
    { 
     return Translator.Translate(key, (int) value); 
    } 
} 

。エラー処理などの機能を追加して、ソリューションを入手してください。

+0

この**は元のバインディングに既にコンバーターがあった場合に**破損します。より良い[解決策]があります(https://stackoverflow.com/a/48090008/332528) – torvin

関連する問題