Выбранный элемент в выпадающих списках из Enum в ASP.net MVC

Извините, если это дубликат, мой поиск ничего не обнаружил.

Я использую следующий метод для создания выпадающих списков для типов перечислений (снятых здесь: 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 " + 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);
     }

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

Он работает отлично, за исключением одного. Если я дам выпадающему списку то же имя, что и свойство на моей модели, выбранное значение не будет установлено должным образом. Это означает, что это работает:

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

Но это не так:

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

Поскольку я пытаюсь передать весь объект непосредственно методу контроллера, который я отправляю, мне бы очень хотелось иметь раскрывающийся список, названный для свойства на модели. При использовании "правильного" имени выпадающее сообщение корректно выводится, я просто не могу установить выбранное значение.

Я не думаю, что это имеет значение, но я запускаю MVC 1 на mono 2.6

edit: Я просто тестировал это на окнах, и я вижу то же поведение

Ответы

Ответ 1

Не пытайтесь использовать значение int для перечисления/вместо:

item.Value = value.ToString();

использовать:

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

imo, что происходит, так это то, что он автоматически устанавливает выбранное значение выпадающего списка в соответствии с моделью - используя имя перечисления вместо значения int. Помните, что движок просмотра ищет уже выбранное значение не только в опубликованной форме (в тех случаях, когда он уже отправлен), но также в модели + viewdata, передаваемых в представление. Только если он не найдет его там, он будет использовать указанное вами значение.

Ответ 2

Собственно, это решение. То же самое решение, что и мое в этом вопросе.
ASP.NET MVC - Html.DropDownList - значение не задано с помощью 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--");
    }

Использование item.Value = Enum.GetName(type, value); делает выпадающее <option> значения, которые будут отображаться как имена перечислений. Я лично предпочитаю иметь int значения в качестве обратной передачи.

Надеюсь, что это поможет.

Ответ 3

Это не совсем правильно, но я обнаружил, что если я назову выпадающий список с именем {nameOfInputParameter}. {propertyName}, он правильно загружает AND. Итак, если рассматриваемая форма отправляла методу, принимающему параметр того же типа, что и модель формы под названием "myModel", выпадающее меню для семьи можно было бы настроить следующим образом:

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

Это отображает идентификатор myModel_family и имя myModel.family. Я не уверен, как это поверить, мне кажется, что это немного от меня. Но, похоже, он работает до сих пор. Однако он вводит новую проблему. Вы больше не можете инициализировать текстовые поля и т.д. Так:

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

Это правильно загрузит значения, но когда вы отправляете методу контроллера, принимающего "myModel" в качестве параметра, значения не распознаются как часть объекта. Поэтому нам нужно включить имя параметра в наше имя ввода.

Однако следующее значение не разрешается для значения, по крайней мере, с использованием стандартного связующего объекта (мне интересно, будет ли копаться в нем наилучший ответ на этот вопрос):

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

Итак, вам нужно сделать это:

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

Все это становится довольно грубым (особенно на страницах, где мне нужно иметь дело с ситуациями, когда модель равна нулю). Надеюсь, у кого-то есть лучшая идея:)