有没有更好的方法来处理跨语言的双重值?

时间:2012-02-05 02:16:41

标签: c# windows-phone-7 cultureinfo

现在,为了在丹麦语等语言中使用逗号作为小数占位符,我检索存储有小数点的值,例如: “.123”来自.resx文件,如下所示:

// Getting a value from a .resx parameter
double minValue = Convert.ToDouble(AppParams.minVal, CultureInfo.InvariantCulture);

当我需要使用从TextBox接收的值时,例如“,321”我用这个:

// Getting a value from a TextBox    
double newValue = Convert.ToDouble(value, CultureInfo.CurrentCulture);

在.csproj文件中,我添加了<SupportedCultures>da;</SupportedCultures>,但除此之外没有尝试过一些应用程序范围的处理这两个问题的方法。

3 个答案:

答案 0 :(得分:4)

您不需要将值存储为resx文件中的字符串:

<data name="minVal" type="System.Double, mscorlib">
    <value>.123</value>
</data>

这样生成的minVal属性的类型为double,您无需手动转换。

此方法的唯一问题是您必须手动编辑XML中的resx文件,因为资源设计器无法处理此类型的资源(实际上您可以重命名或删除资源或更改其值,但是您不能改变它的类型,你不能创建一个新的)。无论如何,自从我开始使用Resharper以来,我已经切换到resx文件的手动编辑,因为它为这些文件提供了一些很好的分析和重构功能;)

作为旁注,我认为minValue常数不是资源的良好候选者。如果是可以更改的设置,请将其置于设置中,而不是放在资源中。如果它确实是常量,请在C#代码中将其设为const。将它放入资源的唯一理由是,如果您希望值可以本地化,并且在这种情况下似乎不太可能。

答案 1 :(得分:1)

从用户输入解析字符串时,尝试接受许多可能的输入,例如

public static class Helper
{
    public static bool TryParseDouble(this TextBox textbox, out double value)
    {
        if (double.TryParse(textbox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out value))
        {
            textbox.Foreground = Brushes.Black; //indicates that the user typed correct number
            return true;
        }
        else
        {
            textbox.Foreground = Brushes.Red; // not a number
            return false;
        }
    }
}

解析.resx时,XML和其他文件也使用InvariantCulture。 Here是我在XML解析器中遇到的一个问题。

向用户显示数据时,请使用当前文化。

答案 2 :(得分:0)

我非常感谢Thomas Levesque和lukas的答案。它们包含一些有用的见解和例子。我发布这个作为答案,因为我想提供更多信息和示例解决方案。与许多计算/ UI问题一样,通常必须做出妥协。我做了一个不幸的发现,当更改区域+语言设置时,没有任何InputScopeNameValues(MSDN InputScopeNameValue Enumeration)在十进制(。)和逗号(,)之间切换(是的,我仔细检查了键盘是否设置在我的电话只能使用Deutsch)。

enter image description here

但是,因为这些TextBox输入是数字的并且需要快速输入,所以数字InputScopes仍然是最好的方法。有趣的是,即使用户被迫使用小数点代替逗号,只要它在TextBox中输入,字符串格式就会改变,例如,从“.123”到“,123”,即使如“{0:#。000}”所示。因此妥协并在下面的代码中,解决方法(到目前为止在en-US和de-DE中测试)。

注意:正如lukas所提到的,验证用户输入总是明智的。我在这里没有使用TryParse(尽管我可能)所以我不必重写很多代码。通过选择数字InputScope并在处理代码中通过try / catch块来缓解这一点,这甚至可以正确处理试图通过从剪贴板粘贴文本来绕过数字输入的用户:

<TextBox x:Name="myTBox" InputScope="Number" Text="{Binding SomeNumber, Mode=TwoWay}" />

代码:

public string SomeNumber

{     得到     {         return String.Format(“{0:#。000}”,SomeProfileModel.Instance.SomeProfile.SomeNumber);     }

set
{
    if (SomeProfileModel.Instance.SomeProfile.SomeNumber.ToString() == value) return;

    var oldValue = SomeProfileModel.Instance.SomeProfile.SomeNumber;

    try
    {
        double newValue;

        try
        {
            newValue = Convert.ToDouble(value, CultureInfo.CurrentCulture);
        }
        catch (Exception)
        {
            newValue = Convert.ToDouble(value, CultureInfo.InvariantCulture);
        }

        if (Convert.ToDouble(MyAppParams.SomeNumberMin, CultureInfo.InvariantCulture) > newValue || Convert.ToDouble(MyAppParams.SomeNumberMax, CultureInfo.InvariantCulture) < newValue)
        {
            // Revert back to previous value
            // NOTE: This has to be done here. If done in the catch statement, 
            // it will never run since the MessageBox interferes with it.
            throw new Exception();
        }

        SomeProfileModel.Instance.SomeProfile.SomeNumber = newValue;

        RaisePropertyChanged("SomeNumber", oldValue, newValue, true);
    }
    catch (Exception err)
    {
        System.Windows.MessageBox.Show("Value must be a number between " + MyAppParams.SomeNumberMin + " and " + MyAppParams.SomeNumberMax);
    }
}

}