How to format the value in a strongy typed view wh

2019-02-06 00:12发布

问题:

I am trying to format a date rendered by ASP.Net MVC's TextBoxFor using the value of a strongly typed view. The date is nullable so if it is null I want to see a blank value, otherwise I want to see it in the format MM/dd/yyyy.

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

Thanks,
Paul Speranza

回答1:

You can keep the strong typing by using a custom editor template and Html.EditorFor() instead of Html.TextBoxFor().

Create a new EditorTemplates folder in your /Views/Shared folder and add a new MVC 2 View User Control named DateTime.ascx. Add the following

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

Then in your view use

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

Don't worry about the "", the naming will still work correctly.

If you are displaying the DateTime in a different culture format to the default application culture then you will need to change the culture information or alternatively create a custom model binder in order for the model binding to work when posting back the DateTime.



回答2:

MVC4 http://msdn.microsoft.com/en-us/library/hh833694.aspx

@Html.TextBoxFor(model => model.YOUR_DATE, "{0:MM/dd/yyyy}")


回答3:

First, add this extension for getting property path:

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

Than add this extensions for 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);
        }

Also you should add this jQuery code:

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

datepicker is a jQuery plugin.

And now you can use it:

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


回答4:

It's a dirty hack, but it seems to work.

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

You get the model binding, and are able to override the HTML "value" property of the text field with a formatted string.



回答5:

You can consider the following sample of TextBoxFor Extension method for datetime data:

    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:

Just name it what it is looking for. Like:

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

When it returns to the controller, your model will have the value bounded.



回答7:

Have you tried to force the culture of your current thread application? You can override it in the web.config using this line (in the tag) :

<!-- 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:

A simple solution is to not use the strongly typed helper.

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


回答9:

I use some custom helpers and have used them successfully in MVC 2 and 3 (code also on Snipplr). The helpers have some css logic thrown in as I use the jQuery-ui datepicker, but that can easily be removed.

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:

Seriously, why should the view have to do this?

Map your core model which has the date time object to your mvc view model.

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

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

So mapping might look like:

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
}

And your controller action might look like:

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

        return View(personForm)
    }

You won't have to change your view example at all then.


From Chapter 2, MVC 2 in Action (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; }
}

This model is intentionally simple; it consists mostly of strings. That’s what we’re representing, after all: text on a page. The logic that displays the data in this object will be straightforward; the view will only output it. The presentation model is designed to minimize decision making in the view.



回答11:

Have you tried just passing in the date format that you'd like?

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