Wpf 使用数据绑定值的MarkupExtension

Wpf 使用数据绑定值的MarkupExtension,wpf,data-binding,markup-extensions,Wpf,Data Binding,Markup Extensions,我正在尝试创建一个WPF MarkupExtension类,它提供来自文本翻译类的翻译文本。翻译工具工作得很好,但是需要一个带有文本键的静态方法调用来返回翻译后的文本。像这样: ImportLabel.Text = Translator.Translate("import files"); // will be "Dateien importieren" in de or "Import files" in en 它的特殊性在于它接受一个计数值以提供更好的措辞 ImportLabel.Text

我正在尝试创建一个WPF 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分钟的词是不同的。如果任何数字的文本键“分钟”定义为“分钟”,计数为1的文本键定义为“分钟”,则以下方法调用将返回要使用的正确单词:

Translator.Translate("minutes", numberOfMinutes)
// will be "minute" if it's 1, and "minutes" for anything else
现在在WPF应用程序中,有很多XAML代码,其中包含大量文本。为了能够在不发疯的情况下翻译它们,我需要一个标记扩展,我可以传递我的文本键,并在运行时返回翻译后的文本。这部分相当简单。创建一个从MarkupExtension继承的类,添加一个接受文本键作为参数的构造函数,将其存储在私有字段中,并让其ProviderValue方法为存储的键返回翻译文本

我真正的问题是:如何使我的标记扩展接受一个计数值,使其数据绑定,并且当计数值更改时,翻译文本将相应地更新

应该这样使用:

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

每当FileCount的绑定值更改时,TextBlock必须接收新的文本值以反映更改,并且仍然提供良好的措辞

我在那里找到了一个类似的解决方案:但尽管我努力遵循它,但我无法理解它的作用,甚至无法理解它为什么会起作用。一切似乎都发生在WPF内部,提供的代码只是将其推向正确的方向,但不清楚如何实现。我无法使我的适应做任何有用的事情

我不确定在运行时更改翻译语言是否有用。我想我需要另一个级别的绑定。为了保持低复杂性,在基本版本运行之前,我不会尝试这样做


目前我没有代码可以给你看。它只是处于一种糟糕的状态,它所做的唯一事情就是抛出异常,或者不翻译任何东西。任何简单的示例都是非常受欢迎的(如果在本例中存在这种情况)。

不过,我最终发现了引用的代码是如何工作的,并可以提出解决方案。这里只是一个简短的解释记录

<TextBlock Text="{t:Translate 'import files', {Binding FileCount}}"/>
例如,TranslateConverter类的转换器有一个接受一个参数(字符串)的构造函数。这是我在上面的TranslateExtension中的关键论点。它会记住它以备以后使用

每当计数值改变时(通过绑定),WPF将重新请求其值。它似乎是从绑定源经过转换器,到达显示它的表面。通过使用转换器,我们根本不必担心绑定,因为转换器将绑定的当前值作为方法参数获取,并期望返回其他内容。输入计数值(int),输出翻译文本(string)。这是我的密码

因此,转换器的任务是使数字适应公式化的文本。它使用存储的文本键来执行该操作。所以发生的事情基本上是一种向后的数据流。我们不需要将文本键作为主要信息并向其添加计数值,而需要将计数值视为主要信息,只需将文本键用作辅助参数即可使其完整。这并不简单,但绑定必须是主要触发器。由于密钥不会更改,因此可以将其永久存储在转换器实例中。每次出现翻译文本都会得到自己的转换器副本,每个副本中都有一个单独的键

这就是转换器的外观:

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

这就是魔法。添加错误处理和更多功能以获得解决方案。

我认为
IValueConverter
MarkupExtension
在这种情况下效果更好<代码>?打字有点落后。如果我想让语言词典在运行时可以更改,那么这也需要一个绑定呢?如果原始绑定已经有了一个转换器,那么这将中断。有更好的办法
class TranslateConverter : IValueConverter
{
    private string key;
    public TranslateConverter(string key)
    {
        this.key = key;
    }
    public object Convert(object value, ...)
    {
        return Translator.Translate(key, (int) value);
    }
}