Использование DropDownList(For) с привязкой модели к вложенному классу

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

Рассмотрим эту модель (View):

public class CreateStudentViewModel
{
    public DropDownList StudentTypes { get; set; }
    public CreateStudent Command { get; set; }
}

public class DropDownList {
    public string SelectedValue { get; set; }
    public IList<SelectListItem> Items { get; set; }
}

public class CreateStudent {
    public string Name { get; set; }
    public int StudentTypeId { get; set; }
}

Я использую это, чтобы предоставить пользователю внешнего интерфейса возможность установить тип ученика, это делается с помощью следующего EditorTemplate:

@model DropDownList
<div class="form-group@(Html.ValidationErrorFor(m => m.SelectedValue, " has-error"))">
    @Html.LabelFor(m => m)
    @Html.DropDownListFor(m => m.SelectedValue, Model.Items)
    @Html.ValidationMessageFor(m => m.SelectedValue, null)
</div>

И используется в моем представлении:

@Html.EditorFor(m => m.StudentTypes)

Теперь этот EditorTemplate привязан к StudentTypes.SelectedValue на DropDownList, что в некоторых случаях хорошо, но мне нужно привязать это к моему Model.Command.StudentTypeId здесь.

Я знаю, что могу переместить весь этот код непосредственно в представление и напрямую связать его, вместо того, чтобы размещать его внутри EditorTemplate, но я постараюсь избежать этого.

В идеале я думаю о расширении EditorFor, чтобы обеспечить такой способ:

@Html.EditorFor(m => m.StudentTypes, new { selectedValue = Model.Command.StudentTypeId });

Но я не могу перевести это как-то так:

@Html.DropDownList(@ViewBag.selectedValue.ToString(), Model.Items);

Поскольку это просто помещает значение (int) в качестве имени поля. Любые предложения приветствуются! :-)


person janhartmann    schedule 07.08.2014    source источник
comment
По моему опыту, html.dropdownlist в Razor всегда был придирчивым. Мне слишком часто приходилось втискивать все в запутанную модель представления, чтобы заставить ее привязываться так, как мне нужно, особенно со сложными объектами.   -  person NeatoBandito    schedule 07.08.2014


Ответы (1)


Ваша главная проблема здесь заключается в том, чтобы инкапсулировать раскрывающийся список в классе, чтобы полагаться на соглашение о шаблонах редактора типов C#. Вместо этого просто используйте свою модель напрямую и используйте UIHint, чтобы указать Razor использовать определенный шаблон. Вот упрощенная версия того, что я использую:

Просмотреть модель

[UIHint("Choice")]
public int SelectedFoo { get; set; }

public IEnumerable<SelectListItem> FooChoices { get; set; }

Виды\Общие\EditorTemplates\Choice.cshtml

@{
    var choices = ViewData["choices"] as IEnumerable<SelectListItem> ?? new List<SelectListItem>();

    if (typeof(System.Collections.IEnumerable).IsAssignableFrom(ViewData.ModelMetadata.ModelType) && ViewData.ModelMetadata.ModelType != typeof(string))
    {
        @Html.ListBox("", choices)
    }
    else
    {
        @Html.DropDownList("", choices)
    }
}

Просмотреть

@Html.EditorFor(m => m.SelectedFoo, new { choices = Model.FooChoices })

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

person Chris Pratt    schedule 07.08.2014
comment
Интересно, я попробую это. Вместо использования аннотации UIHint я могу просто указать непосредственно на шаблон, используя строку в EditorFor? - person janhartmann; 07.08.2014
comment
Спасибо, это помогло мне :-) Почему вы предлагаете ListBox и DropDownList? (просто для информации) - person janhartmann; 07.08.2014
comment
Итак, есть один шаблон для обоих сценариев. Я не хочу заботиться о том, ожидаю ли я одно выбранное значение или несколько выбранных значений. Я просто передаю свойство шаблону, и если ему нужен множественный выбор, он его получает. - person Chris Pratt; 07.08.2014
comment
Отлично :-) Еще раз спасибо! - person janhartmann; 07.08.2014