Asp.net mvc 3 pre-select Html.DropDownListFor не работает в ботаническом ужине

Изучение выпадающих списков, я пытаюсь добавить страницу создания RSVP для nerddinner, как в блог Скотта Гуга с Html.DropDownListДля перечисления доступных обедов,

Я могу получить раскрывающийся список, но я не могу получить раскрывающееся меню, чтобы выбрать значение ( "Sample Dinner 2" ), которое я хочу. Я использую инициализатор для посева нескольких объектов обеда в db. База данных представляет собой sql ce 4 с использованием первого подхода к коду EF. Извините, я знаю, что это общая проблема и ненависть спросить, но честно потратили довольно много времени на это, но не могу заставить ее работать:

ViewModel

public class RSVPViewModel
{
    public SelectList DinnersList { get; set; }
    public RSVP Rsvp { get; set; }
    public string SelectedItem { get; set; }
}

контроллер

    //
    //GET: /RSVP/Create

    public ActionResult Create()
    {
        RSVP rsvp = new RSVP();
        string selected = "Sample Dinner 2";
        var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title", selected);

        var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp, SelectedItem = selected };

        return View("Create", viewModel);
    }

Просмотр

@Html.DropDownListFor(model => model.Rsvp.DinnerID, Model.DinnersList)

Результат HTML

<select data-val="true" data-val-number="The field DinnerID must be a number." data-val-required="The DinnerID field is required." id="Rsvp_DinnerID" name="Rsvp.DinnerID">
     <option value="1">Sample Dinner 1</option>
     <option value="2">Sample Dinner 2</option>
</select>

Таким образом, вы не выбираете выпадающий список со значением "Sample Dinner 2" при загрузке страницы. Список отображает ok и устанавливает правильный DinnerID, когда я делаю выбор, и нажмите "Отправить".

Игнорирует это:

@Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)

но не устанавливает или не связывается с Rsvp.DinnerID.

Это выбирается из списка, но не связывает (или не устанавливает Rsvp.DinnerID)

@Html.DropDownList("DinnersList")

Я хочу сохранить его mvc3, поэтому хочу реализовать с сильным типом с использованием подхода ViewModel (без ViewData) и предпочтительно с использованием Html.DropDownListFor(не Html.DropDownList).Viewbag кажется ненужным для этого случая.

Спасибо!

Edit1

Думаю, что я должен использовать selectList из selectListItems Я пробовал этот подробный подход:

RSVP rsvp = new RSVP();
string selected = "2";
List<SelectListItem> dinners = new List<SelectListItem>();

foreach (Dinner dinner in dbc.Dinners.ToList())
{
    SelectListItem slDinner = new SelectListItem();
    slDinner.Value = dinner.DinnerID.ToString();
    slDinner.Text = dinner.Title;
    slDinner.Selected = (slDinner.Value == selected);
    dinners.Add(slDinner);
 }

 var dinnersList = new SelectList(dinners, "Value", "Text", selected);
 var viewModel = new RSVPViewModel { DinnersList = dinnersList, Rsvp = rsvp, SelectedItem = selected };

Однако до сих пор нет работы. Должен ли я использовать свойство ViewModel SelectedItem в: @Html.DropDownListFor.. как-то? Что-то вроде:

@Html.DropDownListFor(x => x.SelectedItem, Model.DinnersList)

но как получить выбранное значение для установки Rsvp.DinnerID. Я думаю, что это называется привязкой.

Ответы

Ответ 1

После чтения здесь и здесь, я, наконец, понимаю как HtmlDropDownlistFor автоматически выбирает правильный элемент в раскрывающемся списке на основе вашей модели - выбор идентификатора lunchID в RSVP (внешний ключ для файла dinner.dinnerID) приведет к тому, что выпадающий список, содержащий список Dinner.DinnerID, должен предварительно выбрать это значение, Не нужно, я думаю, для selectedValue в SelectList или ViewModel.

Решение:

    //
    //GET: /RSVP/Create

    public ActionResult Create()
    {
        //automatically preselects matching DinnerID in the Dinner dropdownlist            
        var rsvp = new RSVP {DinnerID = 2 };

        var typeList = new SelectList(dbc.Dinners.ToList(), "DinnerID", "Title");
        var viewModel = new RSVPViewModel { DinnersList = typeList, Rsvp = rsvp};

        return View("Create", viewModel);
    }

Ответ 3

Html.DropDownList работает только в том случае, если связанное свойство является int. Любой другой тип, такой как имя enum, приведет к тому, что он по умолчанию будет первым.

Добавьте свойство в свою модель, введите int, который обертывает перечисление, которое вы пытаетесь сохранить:

public myEnumType myProperty {get; set;} // don't bind this to Html.DropDownList

public myEnumType myPropertyAsInt {
    get {return (int)this.myProperty; }
    set {this.myProperty = (myEnumType)value; }
} // bind this instead

Не нужно использовать Selected в вашем SelectList - Html.DropDownList будет синхронизироваться просто отлично.

Ответ 4

Пожалуйста, позаботьтесь, если есть QUERY STRING с тем же именем, это переопределит это поведение, Не уверен в HIDDEN FIELDS с тем же именем.

например.

DropDownListFor будет использовать значение Строка запроса DinnerID, если найдено

Ответ 5

Html.DropDownList принимает свойства int, DropDownListFor тоже, но вы должны быть осторожны, что вы делаете. Я изучил SelectExtensions.cs из ASP.NET MVC 3 и нашел это:

Когда вы используете DropDownList ( "XyField" , "default" ) для создания DropDown, тогда вы должны поместить список выбора в ViewBag.XyField и DropDownList() обрабатывает это правильно.

Когда вы используете DropDownListFor (m = > m.XyField,...), вы можете передать список выбора явно, например:  DropDownListFor (m = > m. XyField, ViewBag. XyFieldList как IEnumerable)

Когда вы это сделаете, произойдет следующее:

  • Второй параметр DropDownListFor (...) будет использоваться в качестве источника для параметров
  • Если есть запись ModelState для "XyField" , это будет использоваться как значение модели
  • Если нет состояния модели И Html.ViewData.Eval( "XyField" ) возвращает не null, это значение будет использоваться в качестве значения модели.
  • Если найденное значение модели не равно null, оно будет преобразовано в строку, используя CultureInfo.CurrentCulture, и это значение сравнивается с вашими значениями SelectListItem, чтобы предварительно выбрать параметры списка.

Внимание: если вы сохранили свой список выбора в ViewBag.XyField, он будет найден до того, как будет получен доступ к модели. Не хотите сравнивать "selectList.ToString()" с "selectList [i].Value", чтобы предварительно выбрать ваши параметры. Сохраните свой список выбора в другом месте!

Самое забавное: вы можете использовать DropDownListFor с неявным списком выбора, точно так же, как вы ожидаете от DropDownList(). В этом случае вы даже сохраните свой список в ViewBag.XyField. Чтобы выполнить эту работу, вам просто нужно вызвать помощника с нулевым значением в качестве второго параметра:  DropDownListFor (m = > m. XyField, null)

Затем список выбора вытягивается из ViewBag.XyField, и шаг 3 в приведенном выше списке пропускается. Итак, если XyField находится в состоянии модели, это будет иметь приоритет перед вашими выбранными свойствами в списке выбора, но в противном случае список выбора будет использоваться "как есть".

Привет Rolf