views:

5830

answers:

3

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?

+4  A: 

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

Haacked
Naturally this makes sense but I couldn't help but notice that placing the model in a custom ViewModel causes the form field names to be prefixed by the property name of the object in the custom ViewModel. Not that this is a problem but it does add another step to updating the model. I'm probably whining unnecessarily eh?
Nathan Taylor
+2  A: 

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.

Graeme
+1  A: 

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

DalSoft
Thank you so much. I've been looking for this for days now, forgot to bookmark last time I stumbled upon it.
jfar