views:

121

answers:

2

I have an easy one for you guys. In my view I have a textbox, like so:

<%= Html.TextBoxFor(x => x.Price, new { @class = "text tiny" })%>

Price is a decimal. When the form loads up. the textbox displays "0". I would like it to display "0.00".

I tried <%= Html.TextBoxFor(x => String.Format("{0:0.00}", x.Price), new { @class = "text tiny" })%> which errored.

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

+1  A: 

You can use ModelMetadata. Some of the Metadata attributes are EditFormatString and DisplayFormatString.

RedFilter
I added the attribute to my model and it still displays "0"
Josh
+1  A: 

Here's a Money display template:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<decimal?>" %>
<%= Html.TextBox( string.Empty, (Model.HasValue ? Model.Value.ToString("C") : string.Empty), new { @class = "money" } ) %>

and editor template

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<decimal?>" %>
<%= Html.TextBox( string.Empty, (Model.HasValue ? Model.Value.ToString("0.00") : string.Empty), new { @class = "money" } ) %>

I'd suggest defining the CSS class money, but you could replace that with the other classes if you want. Name them both Money.ascx and put them in Views\Shared\DisplayTemplates and Views\Shared\EditorTemplates, respectively.

Used as

<%= Html.DisplayFor( x => x.Price, "Money" ) %>
<%= Html.EditorFor( x => x.Price, "Money" ) %>

EDIT: the other thing you can do if you want to have different editor/display formats (as I do) is extend the DataAnnotationsModelMetadataProvider, implement a new EditFormatAttribute that provides the format when in edit mode (this overrides the DataAnnotations setting), the supply both a display format and edit format via the two attributes.

public class ExtendedDataAnnotationsMetadataProvider : DataAnnotationsModelMetadataProvider
{
    private HttpContextBase Context { get; set; }

    public ExtendedDataAnnotationsMetadataProvider() : this( null ) { }

    public ExtendedDataAnnotationsMetadataProvider( HttpContextBase httpContext )
    {
        this.Context = httpContext ?? new HttpContextWrapper( HttpContext.Current );
    }
    protected override ModelMetadata CreateMetadata( IEnumerable<Attribute> attributes, Type containerType, Func<object> modelAccessor, Type modelType, string propertyName )
    {
        List<Attribute> attributeList = new List<Attribute>( attributes );
        var metadata = base.CreateMetadata( attributes, containerType, modelAccessor, modelType, propertyName );
        EditFormatAttribute editFormatAttribute = attributeList.OfType<EditFormatAttribute>().FirstOrDefault();
        if (editFormatAttribute != null)
        {
            metadata.EditFormatString = editFormatAttribute.EditFormatString;
        }

       // RequiredAdminAttribute requiredAdminAttribute = attributeList.OfType<RequiredAdminAttribute>().FirstOrDefault();
       // if (requiredAdminAttribute != null)
       // {
       //     metadata.IsRequired = this.Context.User == null || requiredAdminAttribute.RequiredForUser( this.Context.User );
       // }

        return metadata;
    }
}

public class EditFormatAttribute : Attribute
{
    public string EditFormatString { get; set; }
}

Then hook it up in Global.asax.cs in Application_Start()

ModelMetadataProviders.Current = new ExtendedDataAnnotationsMetadataProvider();

This allows you to configure your model properties like:

[DataType( DataType.Currency )]
[DisplayFormat( DataFormatString = "{0:C}", ApplyFormatInEditMode = false )]
[EditFormat( EditFormatString = "{0:0.00}" )]
public decimal? Amount { get; set; }

This allowed me to get rid of the templates I showed above and retain the ability to easily apply HTML attributes to the generated fields. I thought it might be more complex than necessary. I did it to support an additional attribute that supports conditional requirement based on who the user is or their group membership is (commented out in the sample).

tvanfosson
I used Html.EditorFor and in combination with RedFilter's suggestion it worked.
Josh
@Josh - That works ok. This way allows you to have separate format's for display and edit. As you can see this formats the display with the currency sign but omits it when editting.
tvanfosson