Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET MVC 2 - HTML.EditorFor() and Custom EditorTemplates

With MVC 2's addition of the HtmlHelper EditorFor() it is not possible to create strongly typed Display and Editor templates for a given Model object and after fiddling with it I am a bit stumped as to how to pass additional Model data to the editor without losing the strong-typing of the editor control.

Classic Example: Product has Category. ProductEditor has a DropDownList for Category containing the names of all Categories. The ProductEditor is strongly typed to Product and we need to pass in the SelectList of Categories as well as the Product.

With a standard view we would wrap the Model data in a new type and pass that along. With the EditorTemplate we lose some of the standard functionality if we pass in a mixed Model containing more than one object (first thing I noticed was all of the LabelFor/TextBoxFor methods were producing entity names like "Model.Object" rather than just "Object").

Am I doing it wrong or should Html.EditorFor() have an additional ViewDataDictionary/Model parameter?

like image 732
Nathan Taylor Avatar asked Aug 05 '09 20:08

Nathan Taylor


3 Answers

You can either create a custom ViewModel which has both properties OR you'll need to use ViewData to pass that information in.

like image 139
Haacked Avatar answered Nov 06 '22 18:11

Haacked


I am still learning, but I had a similar problem for which I worked out a solution. My Category is an enum and I use a template control which examines the enum to determine the contents for the Select tag.

It is used in the view as:

<%= Html.DropDownList
            (
            "CategoryCode",
            MvcApplication1.Utility.EditorTemplates.SelectListForEnum(typeof(WebSite.ViewData.Episode.Procedure.Category), selectedItem)
            ) %>

The enum for Category is decorated with Description attributes to be used as the text values in the Select items:

 public enum Category 
        {
            [Description("Operative")]
            Operative=1,
            [Description("Non Operative")]
            NonOperative=2,
            [Description("Therapeutic")]
            Therapeutic=3 
        }
        private Category _CategoryCode; 
        public Category CategoryCode 
        {
            get { return _CategoryCode; }
            set { _CategoryCode = value; }
        }

The SelectListForEnum constructs the list of select items using the enum definition and the index for the currently selected item, as follows:

        public static SelectListItem[] SelectListForEnum(System.Type typeOfEnum, int selectedItem)
    {
        var enumValues = typeOfEnum.GetEnumValues();
        var enumNames = typeOfEnum.GetEnumNames();
        var count = enumNames.Length;
        var enumDescriptions = new string[count];
        int i = 0;
        foreach (var item in enumValues) 
        {
            var name = enumNames[i].Trim();
            var fieldInfo = item.GetType().GetField(name);
            var attributes = (DescriptionAttribute[])fieldInfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            enumDescriptions[i] = (attributes.Length > 0) ? attributes[0].Description : name;
            i++;
        }
        var list = new SelectListItem[count];
        for (int index = 0; index < list.Length; index++)
        {
            list[index] = new SelectListItem { Value = enumNames[index], Text = enumDescriptions[index], Selected = (index == (selectedItem - 1)) };
        }
        return list;
    }

The end result is a nicely presented DDL.

Hope this helps. Any comments about better ways to do this will be greatly appreciated.

like image 5
Graeme Avatar answered Nov 06 '22 19:11

Graeme


Try using ViewData.ModelMetadata this contains all of your class Annotations.

Excellent article http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

like image 4
DalSoft Avatar answered Nov 06 '22 18:11

DalSoft