WPF本地化:具有StringFormat的DynamicResource? [英] WPF Localization: DynamicResource with StringFormat?

查看:149
本文介绍了WPF本地化:具有StringFormat的DynamicResource?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用ResourceDictionary在.NET 4中进行本地化.有没有人有使用字符串格式的值的解决方案?

I am doing localization in .NET 4 with a ResourceDictionary. Does anyone have a solution for using a value with string format?

例如,假设我有一个键为"SomeKey"的值:

For instance, let's say I have a value with the key "SomeKey":

<ResourceDictionary ...>
    <s:String x:Key="SomeKey">You ran {0} miles</s:String>
</ResourceDictionary>

在TextBlock中使用它:

Using it in a TextBlock:

<TextBlock Text="{DynamicResource SomeKey}" />

例如,如何将一个具有SomeKey值的整数作为格式字符串组合?

How would I combine, for example, an integer with the value of SomeKey as a format string?

推荐答案

因此,我终于想出了一个解决方案,该解决方案使我可以在ResourceDictionary中使用格式字符串,并能够在运行时动态更改语言.我认为可以改进,但是可以.

So, I finally came up with a solution that allows me to have format strings in my ResourceDictionary and be able to dynamically change the language at runtime. I think it could be improved, but it works.

此类将资源密钥从ResourceDictionary转换为它的值:

This class converts the resource key into its value from the ResourceDictionary:

public class Localization
{
    public static object GetResource(DependencyObject obj)
    {
        return (object)obj.GetValue(ResourceProperty);
    }

    public static void SetResource(DependencyObject obj, object value)
    {
        obj.SetValue(ResourceProperty, value);
    }

    // Using a DependencyProperty as the backing store for Resource.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty ResourceProperty =
        DependencyProperty.RegisterAttached("Resource", typeof(object), typeof(Localization), new PropertyMetadata(null, OnResourceChanged));

    private static void OnResourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        //check if ResourceReferenceExpression is already registered
        if (d.ReadLocalValue(ResourceProperty).GetType().Name == "ResourceReferenceExpression")
            return;

        var fe = d as FrameworkElement;
        if (fe == null)
            return;

        //register ResourceReferenceExpression - what DynamicResourceExtension outputs in ProvideValue
        fe.SetResourceReference(ResourceProperty, e.NewValue);
    }
}

此类允许ResourceDictionary中的值用作String.Format()中的格式参数

This class allows the value from the ResourceDictionary to be used as the format parameter in String.Format()

public class FormatStringConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        if (values[0] == DependencyProperty.UnsetValue || values[0] == null)
            return String.Empty;

        var format = (string)values[0];
        var args = values.Where((o, i) => { return i != 0; }).ToArray();

        return String.Format(format, args);
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

示例用法1 :在此示例中,我使用MultiBinding中的FormatStringConverter将其Binding集合转换为所需的输出.例如,如果"SomeKey"的值为对象ID为{0}",而"Id"的值为"1",则输出将变为对象ID为1".

Example Usage 1: In this example, I use the FormatStringConverter in the MultiBinding to convert its Binding collection into the desired output. If, for instance, the value of "SomeKey" is "The object id is {0}" and the value of "Id" is "1" then the output will become "The object id is 1".

                <TextBlock ap:Localization.Resource="SomeKey">
                    <TextBlock.Text>
                        <MultiBinding Converter="{StaticResource formatStringConverter}">
                            <Binding Path="(ap:Localization.Resource)" RelativeSource="{RelativeSource Self}" />
                            <Binding Path="Id" />
                        </MultiBinding>
                    </TextBlock.Text>
                </TextBlock>

示例用法2 :在此示例中,我使用与Converter的绑定将资源密钥更改为更详细的名称,以防止密钥冲突.例如,如果我有枚举值Enum.Value(默认显示为"Value"),则使用转换器将其命名空间附加到一个唯一键上.因此,该值将变为"My.Enums.Namespace.Enum.Value".然后,Text属性将使用ResourceDictionary中的"My.Enums.Namespace.Enum.Value"的值进行解析.

Example Usage 2: In this example, I use a binding with a Converter to change the resource key to something more verbose to prevent key collisions. If, for instance, I have the enum value Enum.Value (displayed by default as "Value"), I use the converter to attach its namespace to make a more unique key. So the value becomes "My.Enums.Namespace.Enum.Value". Then the Text property will resolve with whatever the value of "My.Enums.Namespace.Enum.Value" is in the ResourceDictionary.

        <ComboBox ItemsSource="{Binding Enums}"
                  SelectedItem="{Binding SelectedEnum}">
            <ComboBox.ItemTemplate>
                <DataTemplate>
                    <TextBlock ap:Localization.Resource="{Binding Converter={StaticResource enumToResourceKeyConverter}}"
                               Text="{Binding Path=ap:Localization.Resource), RelativeSource={RelativeSource Self}}"/>
                </DataTemplate>
            </ComboBox.ItemTemplate>
        </ComboBox>

示例用法3 :在此示例中,键是文字,仅用于在ResourceDictionary中查找其对应的值.例如,如果"SomeKey"具有值"SomeValue",那么它将仅输出"SomeValue".

Example Usage 3: In this example, the key is a literal and is used only to find its corresponding value in the ResourceDictionary. If, for instance, "SomeKey" has the value "SomeValue" then it will simply output "SomeValue".

                    <TextBlock ap:Localization.Resource="SomeKey"
                               Text="{Binding Path=ap:Localization.Resource), RelativeSource={RelativeSource Self}}"/>

这篇关于WPF本地化:具有StringFormat的DynamicResource?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆