2013-02-06 64 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" 

又如:如果事情還需要4分鐘,這是一個不同的字比如果只需要一分鐘。如果文本鍵「分鐘」爲所有號和「分」爲計數1定義爲「Minuten」,下面的方法調用將返回正確的詞來使用:

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

現在在WPF應用程序,有很多XAML代碼,幷包含大量文字文本。爲了能夠毫不費力地翻譯它們,我需要一個標記擴展,我可以傳遞我的文本鍵,並在運行時返回翻譯的文本。這部分相當簡單。創建一個繼承自MarkupExtension的類,添加一個接受文本鍵作爲參數的構造函數,將其存儲在專用字段中,並讓其ProvideValue方法返回存儲鍵的翻譯文本。

我真正的問題是這樣的:如何讓我的標記擴展接受一個計數值,使得它是數據綁定的,並且翻譯文本會在計數值更改時相應更新?

應該像這樣使用:

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

每當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

沒關係,我終於找到了引用的代碼是如何工作的,並且可以想出一個解決方案。這裏只是對記錄的簡短解釋。

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

這需要一個類TranslateExtension,從繼承的MarkupExtension,使用構造接受兩個參數,一個字符串和一個結合。將這兩個值存儲在實例中。類的ProvideValue方法然後使用它獲得的綁定,向它添加一個自定義的轉換器實例並從binding.ProvideValue返回結果,這是一個BindingExpression實例IIRC。

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,有一個構造函數,它接受一個參數String。這是我上面TranslateExtension的關鍵參數。它會記住它以後。

每當計數值發生變化(通過綁定),WPF將重新請求其值。它似乎從綁定的來源,通過轉換器,走到它顯示的表面。通過使用轉換器,我們不必擔心綁定,因爲轉換器將獲取綁定的當前值作爲方法參數,並且預計會返回其他值。計算翻譯文本(字符串)out中的值(int)。這是我的代碼。

所以這是轉換器的任務,以適應編號文本的數量。它使用存儲的文本鍵。所以發生的事情基本上是一種有點後向的數據流。我們需要將計數值作爲主要信息,而不是將主要信息和計數值添加到文本鍵,而只是使用文本鍵作爲副參數來使其成爲整體。這不是直截了當的,但綁定需要成爲主要的觸發器。由於密鑰不會改變,所以在轉換器的情況下可以保存好。而一個翻譯文本的每一次出現都有自己的轉換器的副本,每一個在編程的各個關鍵

這是轉換器可能是什麼樣子:

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

相關問題