开发者

Selected Item in Dropdown Lists from Enum in ASP.net MVC

Sorry if this is a dup, my searching turned up nothing.

I am using the following method to generate drop down lists for enum types (lifted from here: http://addinit.com/?q=node/54):

public static string DropDownList(this HtmlHelper helper, string name, Type type, object selected)
{
    if (!type.IsEnum)
        throw new ArgumentException("Type is not an enum.");

    if(selected != null && selected.GetType() != type)
        throw new ArgumentException("Selected object is not " + typ开发者_如何学编程e.ToString());

    var enums = new List<SelectListItem>();
    foreach (int value in Enum.GetValues(type))
    {
        var item = new SelectListItem();
        item.Value = value.ToString();
        item.Text = Enum.GetName(type, value);

        if(selected != null)
            item.Selected = (int)selected == value;

        enums.Add(item);
     }

    return System.Web.Mvc.Html.SelectExtensions.DropDownList(helper, name, enums, "--Select--");
}

It is working fine, except for one thing. If I give the dropdown list the same name as the property on my model the selected value is not set properly. Meaning this works:

<%= Html.DropDownList("fam", typeof(EnumFamily), Model.Family)%>

But this doesn't:

<%= Html.DropDownList("family", typeof(EnumFamily), Model.Family)%>

Because I'm trying to pass an entire object directly to the controller method I am posting to, I would really like to have the dropdown list named for the property on the model. When using the "right" name, the dropdown does post correctly, I just can't seem to set the selected value.

I don't think this matters but I am running MVC 1 on mono 2.6

edit: I just tested this on windows, and I am seeing the same behavior


Try not using the int value for the enum / instead of:

item.Value = value.ToString();

use:

item.Value = Enum.GetName(type, value);

imo what's happening is that its automatically setting the selected value of the drop down to match the model - using the enum name instead of its int value. Remember that the view engine looks for the already selected value not only in the form posted (in cases when its already being posted) but also in the model+viewdata being passed to the view. Only if it doesn't find it there, it'll use the selected value you specified.


Actually, this is the solution. The same solution as mine in this question.
ASP.NET MVC - Html.DropDownList - Value not set via ViewData.Model

    public static string DropDownList(this HtmlHelper helper, string name, Type type, object selected)
    {
        if (!type.IsEnum)
            throw new ArgumentException("Type is not an enum.");

        if (selected != null && selected.GetType() != type)
            throw new ArgumentException("Selected object is not " + type.ToString());

        var enums = new List<SelectListItem>();
        foreach (int value in Enum.GetValues(type))
        {
            var item = new SelectListItem();
            item.Value = value.ToString();
            item.Text = Enum.GetName(type, value);

            if (selected != null)
                item.Selected = (int)selected == value;

            enums.Add(item);
        }

        // set ViewData first
        helper.ViewData[name] = enums;

        // pass in "null" intentionally into the DropDownList extension method
        return System.Web.Mvc.Html.SelectExtensions.DropDownList(helper, name, null, "--Select--");
    }

Using item.Value = Enum.GetName(type, value); makes the drop down <option> values to be rendered as the Enum Names. I personally prefer having int values as postback.

Hope it helps.


This doesn't seem quite right, but I found that if I name the drop down list with {nameOfInputParameter}.{propertyName} it loads AND posts correctly. So, if the form in question was posting to a method taking a parameter of the same type as the form's model called "myModel" the dropdown for family could be set up like this:

<%= Html.DropDownList("myModel.family", typeof(EnumFamily), Model.Family)%>

This renders with an id of myModel_family and a name of myModel.family. I'm not sure how to feel about this, it seems a bit off to me. But it does seem to be working so far. It does introduce a new problem though. You can no longer initialize textboxes, etc... like so:

<%= Html.TextBox("name") %>

This will load the values correctly, but when you post to the controller method taking "myModel" as a parameter the values aren't recognized as part of the object being submitted. So we need to include the parameter name in our input name.

However, the following does not resolve to a value, at least using the default model binder (I'm wondering if digging around in there is going to hold the best answer to this question):

<%= Html.TextBox("myModel.name") %>

So you need to do this:

<%= Html.TextBox("myModel.name", Model.Name) %>

This is all getting pretty gross (especially on pages where I need to be able to deal with situations where the model is null). Hopefully someone else has a better idea :)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜