MVC4 DataType.Date Editor не будет отображать значение даты в Chrome, хорошо в Internet Explorer


198

Я использую атрибут DataType.Date в моей модели и EditorFor, на мой взгляд. Это отлично работает в Internet Explorer 8 и Internet 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>

Хром

Internet Explorer

Ответы:


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 за последние два года, ты молодец!
Бен Финкель

3
Отличный ответ, но я чувствую, что это привлекательно, вы должны заставить его просто заставить управление работать должным образом!
Курятник

7
Каков будет способ сделать это «глобально» для всех помеченных свойств, [DataType(DataType.Date)]чтобы мне не пришлось отмечать все эти свойства отдельно с риском пропустить некоторые из них?
Марьян Венема

7
Дарин, что мы, люди за пределами США, можем сделать? Как я могу установить значение спецификации, но отображать пользовательский формат даты? то есть Великобритания?
Петр Кула

3
@ MarjanVenema - я использовал «ExtensibleModelMetadataProvider» из FailTracker Мэтта Ханикатта ( github.com/MattHoneycutt/Fail-Tracker ). Посмотрите под Инфраструктурная папка для ModelMetadata. Я использовал эти классы, а затем создал реализацию фильтра IModelMetadataFilter. Когда вызывается метод TransformMetadata, вы можете редактировать свойства метаданных «DisplayFormatString» и «EditFormatString». Надеюсь, что это приведет вас в правильном направлении (кстати, есть отличное многослайтовое видео, которое использует Fail-Tracker)
SwampyFox

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, и, конечно, у вас может быть другой displayformat в свойстве datetime!
CMXL

Да, отличное решение. Это обеспечивает отличную работу для тех из нас, кто не в США.
Ричард МакКенна

Я думаю, что это лучшее решение проблемы, оно решает только проблему редактора и не влияет на существующее форматирование экрана.
DSGI

1
Использование «Date.cshtml» вместо «DateTime.cshtml» было волшебным ответом! Это работает и в MVC 4.
Атрон Сейдж


16

Как дополнение к ответу Дарина Димитрова:

Если вы хотите, чтобы эта конкретная строка использовала определенный (отличный от стандартного) формат, вы можете использовать в 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

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"и не будет отображать средство выбора даты.


Спасибо Берни. У меня не было таких проблем с отображением сборщика, как с данными, которые не помещались в поле ввода. Это хорошо знать, хотя.
Бен Финкель

Опера рендеринга даты хотя. Используйте Modernizr, чтобы сделать несколько заливок
cleftheris 10.10.12

1
Если предполагается, что это дата, она должна отображаться как ввод типа 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 не работал с частичным классом, не знаю почему? В любом случае, если кто-то попробовал этот метод, я не стал не пытайтесь, но если кому-то нужно, надеюсь, это поможет
shaijut

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" })
    } 
}

Радоваться, веселиться! С уважением, Блертон


Если вы сделаете это таким образом, Chrome не даст вам выбора даты. Я использую ваше решение, но изменяю его так, чтобы 1) Я действительно использовал DisplayFormatатрибут 2) Измените тест, чтобы проверить, является ли тип браузера chrome, затем сделайте @Html.EditorFor(m=>m.EstPurchaseDate)3) Иначе сделайте @Html.TextBox("EstPurchaseDate", dt.ToString("MM/dd/yyyy"))Примечание: на # 2 лучше проверить, если браузер понимает HTML5, но я не знаю, как это сделать.
Дэвид

4
Downvoting для обнаружения браузера в коде на стороне сервера.
Тецуджин но Они

1

Если вам нужен контроль над форматом даты (другими словами, не только формат гггг-мм-дд), то другим решением может быть добавление вспомогательного свойства типа string и добавление валидатора даты к этому свойству. и привязать к этому свойству на пользовательском интерфейсе.

    [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;
    }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.