Как форматировать значение в сильном типизированном представлении при использовании ASP.Net MVC Html.TextBoxFor

Я пытаюсь отформатировать дату, предоставленную ASP.Net MVC TextBoxДля использования значения строго типизированного представления. Дата имеет значение null, поэтому, если она равна нулю, я хочу увидеть пустое значение, в противном случае я хочу увидеть его в формате MM/dd/yyyy.

<%= Html.TextBoxFor(model => model.BirthDate, new { style = "width: 75px;" })%>

Спасибо,
Пол Сперанца

Ответ 1

Вы можете сохранить сильную типизацию с помощью настраиваемого шаблона редактора и Html.EditorFor() вместо Html.TextBoxFor().

Создайте новую папку EditorTemplates в папке /Views/Shared и добавьте новый элемент управления MVC 2 View с именем DateTime.ascx. Добавьте следующий

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.DateTime?>" %>
<%= Html.TextBox("", (Model.HasValue ? Model.Value.ToString("MM/dd/yyyy") : string.Empty)) %>

Затем в вашем представлении используйте

<%= Html.EditorFor(model => model.BirthDate)%></p>

Не беспокойтесь о "", именование будет по-прежнему работать правильно.

Если вы показываете DateTime в другом формате культуры для культуры приложения по умолчанию, вам необходимо изменить информацию о культуре или создать настраиваемое связующее устройство, чтобы привязка модели работала при отправке DateTime.

Ответ 3

Сначала добавьте это расширение для получения пути свойства:

public static string GetPropertyPath<TEntity, TProperty>(Expression<Func<TEntity, TProperty>> property)
{                       
     Match match = Regex.Match(property.ToString(), @"^[^\.]+\.([^\(\)]+)$");
     return match.Groups[1].Value;
}

Затем добавьте расширения для HtmlHalper:

public static MvcHtmlString DateBoxFor<TEntity>(
            this HtmlHelper helper,
            TEntity model,
            Expression<Func<TEntity, DateTime?>> property,
            object htmlAttributes)
        {
            DateTime? date = property.Compile().Invoke(model);

            // Here you can format value as you wish
            var value = date.HasValue ? date.Value.ToShortDateString() : string.Empty;
            var name = ExpressionParseHelper.GetPropertyPath(property);

            return helper.TextBox(name, value, htmlAttributes);
        }

Также вы должны добавить этот код jQuery:

$(function() {
    $("input.datebox").datepicker();
});

datepicker - это плагин jQuery.

И теперь вы можете использовать его:

 <%= Html.DateBoxFor(Model, (x => x.Entity.SomeDate), new { @class = "datebox" }) %>

Ответ 4

Это грязный хак, но, похоже, он работает.

<%= Html.TextBoxFor(model => model.SomeDate,
    new Dictionary<string, object> { { "Value", Model.SomeDate.ToShortDateString() } })%>

Вы получаете привязку к модели и можете переопределить свойство "значение" HTML в текстовом поле с форматированной строкой.

Ответ 5

Вы можете рассмотреть следующий образец метода TextBoxFor Extension для данных datetime:

    public static MvcHtmlString CalenderTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TProperty>> expression)
        {
            Func<TModel, TProperty> deleg = expression.Compile();
            var result = deleg(htmlHelper.ViewData.Model);

            string value = null;

            if (result.ToString() == DateTime.MinValue.ToString())
                value = string.Empty;
            else
                value = string.Format("{0:M-dd-yyyy}", result);

            return htmlHelper.TextBoxFor(expression, new { @class = "datepicker text", Value = value });
       }

Ответ 6

Просто назовите его, что он ищет. Как:

Html.TextBox("Person.StartTime",Person.StartTime.ToShortDateString());

Когда он вернется к контроллеру, ваша модель будет иметь ограниченное значение.

Ответ 7

Вы пытались заставить культуру использовать текущее приложение? Вы можете переопределить его в файле web.config с помощью этой строки (в теге):

<!-- Default resource files are set here. The culture will also change date format, decimal, etc... -->
<globalization enableClientBasedCulture="false" culture="en-US" uiCulture="en-US"/>

Ответ 8

Простое решение - не использовать строго типизированный помощник.

<%= Html.TextBox("StartDate", string.Format("{0:d}", Model.StartDate)) %>

Ответ 9

Я использую некоторые пользовательские помощники и успешно использовал их в MVC 2 и 3 (код также на Snipplr). У помощников есть какая-то css-логика, в которую я использую jQuery-ui datepicker, но это можно легко удалить.

public static MvcHtmlString DateTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string formatString, object htmlAttributes)
    {
        var metadata = ModelMetadata.FromLambdaExpression(expression, helper.ViewData);
        string format = String.IsNullOrEmpty(formatString) ? "M/d/yyyy" : formatString;
        DateTime date = metadata.Model == null ? new DateTime() : DateTime.Parse(metadata.Model.ToString());
        string value = date == new DateTime() ? String.Empty : date.ToString(format);
        RouteValueDictionary attributes = new RouteValueDictionary(htmlAttributes);
        string datePickerClass = "date-selector";
        if (attributes.ContainsKey("class"))
        {
            string cssClass = attributes["class"].ToString();
            attributes["class"] = cssClass.Insert(cssClass.Length, " " + datePickerClass);
        }
        else
        {
            attributes["class"] = datePickerClass;
        }
        return helper.TextBox(ExpressionHelper.GetExpressionText(expression), value, attributes);
    }

    public static MvcHtmlString DateTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression)
    {
        return DateTextBoxFor<TModel, TValue>(helper, expression, String.Empty, null);
    }

    public static MvcHtmlString DateTextBoxFor<TModel, TValue>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TValue>> expression, string formatString)
    {
        return DateTextBoxFor<TModel, TValue>(helper, expression, formatString, null);
    }

Ответ 10

Серьезно, почему это должно выглядеть?

Сопоставьте свою основную модель, у которой есть объект времени даты, к вашей модели представления mvc.

//core model
public class Person
{
    public DateTime? BirthDate { get; set;}
}

//view model
public class PersonForm
{
    public string BirthDate { get; set; }
}

Таким образом, отображение может выглядеть так:

public interface IDomainToViewMapper<TModel, TViewModel>
{
    /// <summary>
    /// Use an automapper or custom implementation to map domain model to presentation model.
    /// </summary>
    /// <param name="source">domain model</param>
    /// <returns>presentation model</returns>
    TViewModel MapDomainToView(TModel source);        
}

public interface IPersonMapper : IDomainToViewMapper<Person, PersonForm>
{
}

public class PersonMapper : IPersonMapper
{
    #region IDomainToViewMapper<Person,PersonForm> Members

    public PersonForm MapDomainToView(Person source)
    {
        PersonForm p = new PersonForm();

        if (source.BirthDate.HasValue)
        {
            p.BirthDate = source.BirthDate.Value.ToShortDateString();
        }

        return p;
    }

    #endregion
}

И ваше действие контроллера может выглядеть так:

    public ActionResult Index()
    {
        Person person = //get person;
        var personForm = _personMapper.MapDomainToView(person);

        return View(personForm)
    }

Вам больше не придется менять свой пример.


Из главы 2, MVC 2 в действии (Manning)

public class CustomerSummary
{
public string Name { get; set; }
public bool Active { get; set; }
public string ServiceLevel { get; set; }
public string OrderCount { get; set;}
public string MostRecentOrderDate { get; set; }
}

Эта модель намеренно проста; он состоит в основном из строк. То, что представляли, в конце концов: текст на странице. Логика, отображающая данные в этом объекте, будет прямой; представление будет выводить его только. Модель презентации предназначена для минимизировать принятие решений в представлении.

Ответ 11

Вы пробовали просто передать формат даты, который вам нужен?

Html.TextBoxFor(model => model.BirthDate.ToString("MM/dd/yyyy"), 
                new { style = "width: 75px;" })