Помощник Nullable Enum для значения по умолчанию

Недавно я сделал расширение для привязки выпадающего списка к модели. К сожалению, я не смог сделать так, чтобы -wanna be default- "пожалуйста, выберите..." было выбрано по умолчанию Всегда индекс выпадающего списка равен 1 и он выбирает 1-й элемент Enum в качестве элемента по умолчанию. Я сделал расширение на основе этого - отличный ответ Дарина -

Мне посоветовали использовать nullable enum, я пока не смог заставить его работать, надеюсь получить помощь.

Спецификация текста выбора по умолчанию в помощнике:

return htmlHelper.DropDownListFor(expression, items, "Please select ...");

Как сделать так, чтобы «пожалуйста, выберите…» было выбрано по умолчанию во всех раскрывающихся списках.

В ViewModel я использовал:

public TimePlan? TimeList { get; set; }

person LastBye    schedule 15.08.2013    source источник
comment
Я знаю, что удалил вторую часть, чтобы не вызывать неправильного понимания вопроса.   -  person LastBye    schedule 15.08.2013
comment
что отображается в html? ты это проверял?   -  person Guanxi    schedule 15.08.2013
comment
Не могу точно понять, что вы имеете в виду, перечисление полностью отображается, и у меня есть подсказка выбора вверху, проблема в том, что он не выбран, и выбранным элементом будет индекс 1.   -  person LastBye    schedule 15.08.2013


Ответы (1)


Ты делаешь это неправильно. Это не TimeList, который должен иметь значение NULL, а свойство TimePlan, которое должно хранить выбранный элемент. Вот что вы должны иметь в своей модели представления:

public TimePlan? TheTimePlan { get; set; }

public IEnumerable<SelectListItem> TimeList
{
    get
    {
        var enumType = typeof(TimePlan);
        var values = Enum.GetValues(enumType).Cast<TimePlan>();

        return
            from value in values
            select new SelectListItem
            {
                Text = Enum.GetName(typeof(TimePlan), value),
                Value = value.ToString(),
            };
    }
}

Затем в вашем представлении у вас будет:

@Html.DropDownListFor(model => model.TheTimePlan, Model.TimeList, "Please select...")

ОБНОВЛЕНИЕ:

Если вы хотите создать собственный html-помощник, вы можете сделать это следующим образом:

public static IHtmlString DropDownListForEnum<TModel, TEnum>(this HtmlHelper<TModel> htmlHelper, 
    Expression<Func<TModel, TEnum>> expression, string optionLabel)
{
    var metadata = ModelMetadata.FromLambdaExpression(expression, htmlHelper.ViewData);
    var enumType = GetNonNullableModelType(metadata);
    var values = Enum.GetValues(enumType).Cast<TEnum>();            

    var items =
        from value in values
        select new SelectListItem
        {
            Text = Enum.GetName(enumType, value),
            Value = value.ToString(),
            Selected = value.Equals(metadata.Model)
        };

    return htmlHelper.DropDownListFor(expression, items, optionLabel);
}

private static Type GetNonNullableModelType(ModelMetadata modelMetadata)
{
    Type modelType = modelMetadata.ModelType;

    Type underlyingType = Nullable.GetUnderlyingType(modelType);
    if (underlyingType != null)
    {
        modelType = underlyingType;
    }
    return modelType;
}

Затем в вашем представлении у вас будет:

@Html.DropDownListForEnum(model => model.TheTimePlan, "Please select...")
person ataravati    schedule 15.08.2013
comment
Я использую что-то вроде @Html.DropDownListForEnum(x => x.TheTimePlan), также, когда я прокомментировал там, я попробовал это, что не будет работать должным образом: я попробовал что-то вроде этого в качестве теста: return htmlHelper.DropDownListFor(expression , элементы,Пожалуйста, выберите из списка ниже); но выбранный индекс раскрывающегося списка всегда равен 1, а не 0. Я играю с кодом, чтобы найти обходной путь и сообщить вам, спасибо - person LastBye; 15.08.2013
comment
не смог найти никакой разницы между вашим кодом и предыдущим сообщением - person LastBye; 15.08.2013
comment
Есть только два небольших отличия. 1- В моем коде TimePlan можно обнулить (TimePlan?). 2- Помощник html DropDownListFor имеет аргумент optionLabel (пожалуйста, выберите...). И это работает. Я проверил это. Это основано на первом решении в ответе на другой вопрос. Вам не нужно создавать собственный html-помощник для чего-то подобного. - person ataravati; 15.08.2013
comment
Проверьте мой обновленный ответ, если вы хотите использовать собственный помощник html. - person ataravati; 15.08.2013
comment
Я был далеко отсюда, но, друг, ты знаешь, я не ищу просто большого ответа, точного ответа, который я видел и пробовал раньше. Все, что вы упомянули, было именно в той ссылке, которую я упомянул, я думаю, что вы не проверьте это сами, потому что результат тот же и не показывает OptionLabel при загрузке страницы (он скрыт под полем со списком. - person LastBye; 15.08.2013
comment
Я проверил это. Оно работает. Вы делаете что-то не так. Можете ли вы обновить вопрос с вашим полным кодом? Код в вашем вопросе явно неверен (public TimePlan? TimeList { get; set; }). Или хотя бы описать, что происходит. Вы получаете сообщение об ошибке? Где? - person ataravati; 15.08.2013
comment
Ошибок нет, у меня нет лишнего элемента в моем коде, что вы имеете в виду с общедоступным TimePlan? Список времени { получить; задавать; } ?! у вас тут то же самое. Итак, когда ваша страница загружается, у вас есть OptionsLabel в качестве выбранного значения по умолчанию? - person LastBye; 15.08.2013
comment
У меня нет такого же. Пожалуйста, обратите больше внимания. Вот почему я прошу вас опубликовать полный код. - person ataravati; 15.08.2013
comment
И да, у меня есть optionLabel в качестве выбранного значения по умолчанию при загрузке страницы. - person ataravati; 15.08.2013
comment
И, кстати, мой код здесь отличается от кода в другой ссылке. Я использую другой способ получить текст для SelectListItems. И я использую перечисление с нулевым значением. - person ataravati; 15.08.2013
comment
Новые части вашего кода были упомянуты в разделе комментариев по ссылке, которую я предоставил, я вставил их сюда, они были точно такими же, как мой код, и результат был таким же, но я обнаружил проблему, потому что вы упомянули, что видите их правильно форме я проверил перечисление и обнаружил, что установил их значения, начиная с 0, изменил начальную точку на 1, и проблема решена, может быть без значений, и они верны, пожалуйста, отредактируйте свой пост и удалите весь код и упомяните строки, относящиеся к optionLabel, в пределах 2-3 строк, я думаю, что так ответ выглядит лучше, спасибо за ваше время. - person LastBye; 16.08.2013
comment
Когда вы используете перечисление, допускающее значение NULL, не имеет значения, начинаете ли вы значения перечисления с 0 или 1. Это работает в любом случае. - person ataravati; 16.08.2013