После просмотра ответа выше я хотел проверить его, потому что все примеры, которые я видел, действительно использовали ViewDataDictionary, а не строго типизированный ViewDataModel.
Итак, я провел несколько экспериментов. Я построил очень простое представление, которое использовало обычный ViewDataDictionary и передавало значения по именованным ключам. Сохранился выбранный пункт просто отлично. Затем я вырезал и вставил этот View (и контроллер) в другой, изменив только то, что было необходимо для переключения на строго типизированную модель ViewData. И вот, он также сохранил выбранный пункт.
Так что же отличалось между моим простым тестом и моим приложением? В моем тесте я использовал просто "Html.DropDownList (" name "," optionLabel ")". Однако в моем приложении мне нужно было добавить атрибуты HTML, и единственные доступные перегрузки, которые включали атрибуты HtmlAttributes, также включают список выбора.
Оказывается, перегрузка DropDownList с параметром списка выбора прервана! Глядя на загруженный исходный код MVC, когда DropDownList вызывается только с именем или именем и optionLabel, он заканчивает тем, что получает целевой список выбора из ViewData, а затем вызывает закрытый метод SelectInternal следующим вызовом:
return SelectInternal(htmlHelper, optionLabel, name, selectList, true /* usedViewData */, false /* allowMultiple */, (IDictionary<string, object>)null /* htmlAttributes */);
Однако, если он вызывается с параметром selectList, он заканчивается следующим:
return SelectInternal(htmlHelper, optionLabel, name, selectList, false /* usedViewData */, false /* allowMultiple */, htmlAttributes);
Разница в том, что в первом (который будет работать правильно) параметр usedViewData имеет значение true, а во втором - false. Что на самом деле нормально, но обнаруживает внутренний дефект в процедуре SelectInternal.
Если usedViewData имеет значение false, он получает объектную переменную "defaultValue" из модели ViewData.
Однако defaultValue используется, как если бы это была либо строка, либо массив строк, тогда как фактически то, что возвращается из ViewData, представляет собой SelectList. (IEnumerable<SelectListItem>
).
Если usedViewData имеет значение true, тогда defaultValue будет иметь значение null или строку.
Тогда, если defaultValue не равно NULL, он в конечном итоге попадает в блок кода, который содержит это:
foreach (SelectListItem item in selectList) {
item.Selected = (item.Value != null) ? selectedValues.Contains(item.Value) : selectedValues.Contains(item.Text);
newSelectList.Add(item);
selectList - это исходный список selectList, который был передан, поэтому элемент представляет собой SelectListItem (строка Text, строка Value и bool Selected). Но selectedValues был получен из defaultValue и становится списком списков выбора, а не списком строк. Таким образом, для каждого из элементов он устанавливает флаг Selected в зависимости от того, содержит ли selectedValues список item.Value. Что ж, список SelectLists никогда не собирается «содержать» строку, поэтому item.Selected никогда не устанавливается. (Исправление: на самом деле, после более подробной трассировки с помощью отладчика, я обнаружил, что selectedValues наследуется от defaultValue с помощью вызова ToString (). Таким образом, на самом деле это список строк, но вместо того, чтобы содержать нужные значения, содержит "System.Web.Mvc.SelectList" - результат применения ToString () "к сложному объекту, например, SelectList. Результат все тот же - мы не собираемся находить искомое значение в этом список.)
Затем он заменяет недавно созданный "newSelectList" на оригинальный "selectList" и продолжает строить HTML из него.
Как сказал выше cagdas (я прошу прощения за разделку вашего имени, но я не знаю, как сделать эти символы на моей клавиатуре США), я думаю, мне придется создать свой собственный метод для использования вместо DropDownList HtmlHelper. Я полагаю, что поскольку этот выпуск 1 и выпуск 2 находятся в бета-версии 2, мы не можем ожидать каких-либо исправлений ошибок, если сами не сделаем это правильно?
Кстати, если вы следили за мной так далеко, этот код находится в src \ SystemWebMvc \ Mvc \ Html \ SelectExtensions.cs, около строки 116-136