MVC4 DataType.Date EditorFor在Chrome中不显示日期值,在Internet Explorer中很好


198

我在模型上使用DataType.Date属性,并在视图中使用EditorFor。在Internet Explorer 8Internet Explorer 9中,这可以正常工作,但是在Google Chrome浏览器中,它显示的是日期选择器,而不是显示值,而只是以淡灰色文本显示“月/日/年”。

Google Chrome为什么不显示该值?

模型:

[DataType(DataType.Date)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }

视图:

<td class="fieldLabel">Est. Pur. Date</td>
<td class="field">@Html.EditorFor(m=>m.EstPurchaseDate)</td>

铬

IE浏览器

Answers:


377

[DataType(DataType.Date)]在ASP.NET MVC 4 中用默认模板装饰模型属性时,将生成一个输入字段type="date"

<input class="text-box single-line" 
       data-val="true" 
       data-val-date="The field EstPurchaseDate must be a date."
       id="EstPurchaseDate" 
       name="EstPurchaseDate" 
       type="date" value="9/28/2012" />

支持HTML5的浏览器(例如Google Chrome)使用日期选择器呈现此输入字段。

为了正确显示日期,该值的格式必须为2012-09-28。引用规范

值: [RFC 3339]中定义的有效完整日期,另外具有年份成分为四位或更多位数字表示大于0的数字的资格。

您可以使用DisplayFormat属性来强制采用这种格式:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public Nullable<System.DateTime> EstPurchaseDate { get; set; }

44
达林,谢谢你,那太完美了!在过去的两年中,您已经回答了我的许多MVC问题,您真棒!
Ben Finkel 2012年

3
很好的答案,但是我觉得这很有吸引力,您必须强迫它才能使控件正常工作!
合作社

7
对所有标记的属性进行“全局”处理的方式是什么,[DataType(DataType.Date)]这样我就不必分别标记所有这些属性,而会有丢失某些属性的风险?
Marjan Venema

7
达林,我们在美国以外的人能做什么?如何设置规格值但显示自定义日期格式?即英国?
Piotr Kula

3
@ MarjanVenema-我使用了Matt Honeycutt的FailTracker(github.com/MattHoneycutt/Fail-Tracker)中的“ ExtensibleModelMetadataProvider” 。在“基础结构”文件夹下查看“模型元数据”。我使用了这些类,然后创建了IModelMetadataFilter的过滤器实现。调用TransformMetadata方法时,可以随后编辑元数据的“ DisplayFormatString”和“ EditFormatString”属性。希望这能为您指明正确的方向(顺便说一句,有一个很棒的使用Fail-Tracker的复数视频)
SwampyFox 2014年

44

在MVC5.2中,将Date.cshtml添加到文件夹〜/ Views / Shared / EditorTemplates中:

@model DateTime?
@{
    IDictionary<string, object> htmlAttributes;
    object objAttributes;
    if (ViewData.TryGetValue("htmlAttributes", out objAttributes))
    {
        htmlAttributes = objAttributes as IDictionary<string, object> ?? HtmlHelper.AnonymousObjectToHtmlAttributes(objAttributes);
    }
    else
    {
        htmlAttributes = new RouteValueDictionary();
    }
    htmlAttributes.Add("type", "date");
    String format = (Request.UserAgent != null && Request.UserAgent.Contains("Chrome")) ? "{0:yyyy-MM-dd}" : "{0:d}";
    @Html.TextBox("", Model, format, htmlAttributes)
}

谢谢!修复了提到的chrome“问题”,当然,您可以在datetime属性上使用另一种displayformat格式!
cmxl

是的,很好的解决方案。这为不在美国的我们这些人提供了出色的工作。
理查德·麦肯纳

我认为这是解决该问题的最佳方法,它仅解决了编辑器问题,并且不会影响现有的显示格式。
dsghi 2015年

1
神奇的答案是使用“ Date.cshtml”而不是“ DateTime.cshtml”!它也可以在MVC 4中使用。
Atron Seige,2015年

大!Obrigado。
Guilherme de Jesus Santos,

16

除了Darin Dimitrov的答案之外:

如果只希望该特定行使用某种(不同于标准)格式,则可以在MVC5中使用:

@Html.EditorFor(model => model.Property, new {htmlAttributes = new {@Value = @Model.Property.ToString("yyyy-MM-dd"), @class = "customclass" } })

就像@一开始那样,那@Value = @Model.Property...还需要@吗?你是说new { Value = Model.Property...
user3454439 '18

11

在MVC 3中,我必须添加:

using System.ComponentModel.DataAnnotations;

在添加属性时的用法之间:

[DataType(DataType.Date)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

特别是如果您要像我一样在.edmx文件中添加这些属性。我发现默认情况下.edmx文件没有使用此功能,因此仅添加属性是不够的。


10

如果您[DataType(DataType.Date)]从模型中删除,则Chrome中的输入字段type="datetime"将显示为,也不会显示日期选择器。


谢谢伯尼。我对选择器的显示并没有那么麻烦,因为我没有将数据放入输入框。知道这是一件好事。
Ben Finkel

Opera会渲染一个日期选择器。使用modernizr做一些
填充

1
如果应该是日期,则应将其呈现为type的输入date。使用datetime的解决办法是不合适的,因为它没有语义上表示数据。
克里斯·普拉特

4

通过格式yyyy-MM-dd仍然存在问题,但是我通过更改Date.cshtml解决了它:

@model DateTime?

@{
    string date = string.Empty;
    if (Model != null)
    {
        date = string.Format("{0}-{1}-{2}", Model.Value.Year, Model.Value.Month, Model.Value.Day);
    }

    @Html.TextBox(string.Empty, date, new { @class = "datefield", type = "date"  })
}

谢谢,终于这工作了,我尝试string.Format("{0}/{1}/{2}")获取dd/mm/yyyy格式,并且工作正常,我使用数据库优先方法,但DisplayFormat不适用于部分类,不知道为什么吗?无论如何,如果有人需要尝试方法,我没有请尝试,但如果有人需要,希望对您
有所

3

回复MVC4 DataType.Date EditorFor在Chrome中不显示日期值,在IE中很好

在模型中,您需要具有以下声明类型:

[DataType(DataType.Date)]
public DateTime? DateXYZ { get; set; }

要么

[DataType(DataType.Date)]
public Nullable<System.DateTime> DateXYZ { get; set; }

您不需要使用以下属性:

[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]

在Date.cshtml使用以下模板:

@model Nullable<DateTime>
@using System.Globalization;

@{
    DateTime dt = DateTime.Now;
    if (Model != null)
    {
        dt = (System.DateTime)Model;

    }

    if (Request.Browser.Type.ToUpper().Contains("IE") || Request.Browser.Type.Contains("InternetExplorer"))
    {
        @Html.TextBox("", String.Format("{0:d}", dt.ToShortDateString()), new { @class = "datefield", type = "date" })
    }
    else
    {
        //Tested in chrome
        DateTimeFormatInfo dtfi = CultureInfo.CreateSpecificCulture("en-US").DateTimeFormat;
        dtfi.DateSeparator = "-";
        dtfi.ShortDatePattern = @"yyyy/MM/dd"; 
        @Html.TextBox("", String.Format("{0:d}", dt.ToString("d", dtfi)), new { @class = "datefield", type = "date" })
    } 
}

玩得开心!此致Blerton


如果您采用这种方式,Chrome将不会为您提供日期选择器。我正在使用您的解决方案,但请进行以下修改:1)我确实使用DisplayFormat属性2)更改测试以检查浏览器类型是否为chrome,然后执行@Html.EditorFor(m=>m.EstPurchaseDate)3)其他操作@Html.TextBox("EstPurchaseDate", dt.ToString("MM/dd/yyyy"))注意:在#2上,更好的检查是浏览器可以理解HTML5,但我不知道该怎么做。
大卫

4
拒绝在服务器端代码中进行浏览器检测。
Tetsujin no Oni 2014年

1

如果您需要控制日期的格式(换句话说,不仅可以接受yyyy-mm-dd格式),另一种解决方案可以是添加字符串类型的helper属性,并向该属性添加日期验证器,并绑定到UI上的此属性。

    [Display(Name = "Due date")]
    [Required]
    [AllowHtml]
    [DateValidation]
    public string DueDateString { get; set; }

    public DateTime? DueDate 
    {
        get
        {
            return string.IsNullOrEmpty(DueDateString) ? (DateTime?)null : DateTime.Parse(DueDateString);
        }
        set
        {
            DueDateString = value == null ? null : value.Value.ToString("d");
        }
    }

这是一个日期验证器:

[AttributeUsage(AttributeTargets.Property, AllowMultiple = true, Inherited = true)]
public class DateValidationAttribute : ValidationAttribute
{
    public DateValidationAttribute()
    {
    }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        if (value != null)
        {
            DateTime date;

            if (value is string)
            {
                if (!DateTime.TryParse((string)value, out date))
                {
                    return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
                }
            }
            else
                date = (DateTime)value;

            if (date < new DateTime(1900, 1, 1) || date > new DateTime(3000, 12, 31))
            {
                return new ValidationResult(validationContext.DisplayName + " must be a valid date.");
            }
        }
        return null;
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.