【问题标题】:Change display format number decimal separator更改显示格式数字小数分隔符
【发布时间】:2016-02-06 18:38:48
【问题描述】:

我有以下浮点数:-95.83334 这是在我的视图模型中:

[DisplayFormat(DataFormatString = "{0:#.##}")]
public float? mx { get; set; }

这是我的看法

@Html.HiddenFor(model => model.mx)

这是生成的html

<input data-val="true" id="mx" name="mx" type="hidden" value="-95,83334">

这是所需的 html

<input data-val="true" id="mx" name="mx" type="hidden" value="-95.83334">

所以问题是,更改此隐藏输入的小数分隔符的最佳方法是什么?不改变我项目的其余部分

【问题讨论】:

  • 如果您希望全局更改,您可以强制更改线程的CultureInfo.CurrentCulture
  • 我的猜测是这里不需要DisplayFormat 属性,它会与您的输入值混淆。
  • 我试了一下,它工作正常,我的 CurrentCultur 是 en-US
  • 为什么?它是一个隐藏的输入,所以你甚至看不到它。然后因为它与您的服务器文化不匹配,绑定会失败(除非您有自定义模型绑定器)并且mx 的值将是null
  • @StephenMuecke 因为我的应用使用了这些值

标签: c# asp.net-mvc razor asp.net-mvc-5


【解决方案1】:

DisplayFormat 在您使用Html.DisplayFor 时使用。而且,它仅用于格式化应该在视图上显示的内容。如果您想更改一般小数的格式,则需要使用不同的文化。

【讨论】:

  • 那我怎样才能改变这个隐藏的文化呢?我需要在某些情况下打印逗号并在同一视图中指向其他情况
  • 改变隐藏输入的文化有什么意义?这没有任何意义。
  • 因为我的应用程序文化是 es-CL,我需要使用点分隔小数而不是逗号。我不能用逗号分隔小数进行数学运算
【解决方案2】:
@Html.HiddenFor(model => model.mx.ToString(new CultureInfo("en-us")));

编辑: 很抱歉简短的回答。我认为如果它有效的话会很有用,不幸的是我错过了你的代码中的一些重要内容。

您的问题是本地化问题。我猜你的机器运行的是欧洲文化。 (刚刚注意到您关于将其设置为西班牙语的评论)

ToString() 已经为一些基本类型重载,包括浮点数。这些重载之一接受 CultureInfo 实现的 IFormatProvider。通过使用美国英语的 culture code 传递 CultureInfo,您可以确保将使用点而不是逗号作为小数分隔符。

我错过的是 mx 是一个浮点数?,它是 Nullable 的缩写。 Nullable 不会以相同的方式重载 ToString,因此您有多种选择。

如果您使用的是 C#6,您可以使用空检查运算符来转换您的浮点数吗?回到浮动。然后你可以使用 ToString 重载:

@Html.HiddenFor(model => model.mx?.ToString(CultureInfo.GetCultureInfo("en-us")));

或者,您可以使用 String.Format 重载,它同时接受格式字符串和 IFormatProvider:

@Html.HiddenFor(model => String.Format(CultureInfo.GetCultureInfo("en-us"), "{0:#.##}", model.mx));

我不想建议更改您线程的文化,因为这在您的问题“不改变我的项目的其余部分”中很突出,我可能错误地认为这意味着您不想更改格式应用程序中的其他组件。更改默认线程文化可能会产生比您预期更大的影响。

编辑 2: 这是我尝试接受 IFormatProvider 的扩展重载。这只是一个实验,不应该在生产中使用......我只是为了兴趣而将其包括在内。

public static class HtmlExtensions
{
    public static IHtmlString HiddenFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IFormatProvider formatter)
    {
        var value = expression.Compile().Invoke(helper.ViewData.Model);

        var modelMetadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
        var property = typeof(TModel).GetProperty(modelMetadata.PropertyName);
        var attribute = property.GetCustomAttributes(typeof(DisplayFormatAttribute), false).SingleOrDefault() as DisplayFormatAttribute;

        var displayValue = String.Format(formatter, attribute?.DataFormatString ?? "{0}", value);

        TagBuilder tagBuilder = new TagBuilder("input");
        tagBuilder.MergeAttribute("type", "hidden");
        tagBuilder.MergeAttribute("value", displayValue);

        return MvcHtmlString.Create(tagBuilder.ToString());
    }
}

这样使用

@Html.HiddenFor(mode => mode.myNumber, System.Globalization.CultureInfo.GetCultureInfo("en-us"))

【讨论】:

  • 没有对采用 1 个参数的方法 ToString 进行覆盖
  • 抱歉,这个的答案,它根本不是一个好的答案。我进行了编辑以添加适当的上下文。
  • 我可以在打印浮点值时使用CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");,然后使用CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("es-CL"); 再次回到我的默认文化。但是在 cshtml 中进行此设置仅在此 html 中生效,并且不会更改项目的其余部分
  • 我尝试使用您的代码 @Html.HiddenFor(model =&gt; tring.Format(CultureInfo.GetCultureInfo("en-us"), "{0:#.##}", model.mx)); 并收到此错误 Las plantillas solo se pueden usar con expresiones de acceso de campos, acceso de propiedades, índice de matriz de una dimensión o indizador personalizado de un parámetro. Detalles de la excepción: System.InvalidOperationException: Las plantillas solo se pueden usar con expresiones de acceso de campos, acceso de propiedades, índice de matriz de una dimensión o indizador personalizado de un parámetro.
  • 我看到 HtmlHelper 方法比我想象的要复杂。我认为我的本地化知识可以转移到这个问题上,但我显然没有深入使用 MVC。作为一个实验,我为 HtmlHelper 方法 HiddenFor 创建了一个扩展重载,该方法接受一个 IFormatProvider 但我不建议使用它,因为我不知道这些提供程序如何工作得足够好以进行全功能覆盖。我有点惊讶微软没有包括这个,但也许暂时设置默认线程文化是“正确”的解决方案......
【解决方案3】:

最后,这就是我的解决方案

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
@Html.HiddenFor(model => model.mx)

添加行

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");

在我的隐藏解决问题之前。感谢您的想法和指导!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多