DropDownList устанавливает выбранный элемент в asp.net MVC

Я заметил, что мне кажется ошибка в asp.net MVC или просто я делаю что-то неправильно. В настоящее время я использую 1.0, поэтому, возможно, это то, что будет рассмотрено в версии 2.0. Но в любом случае, мы идем.

Когда у моей модели просмотра есть свойство, имя которого совпадает с объявленным идентификатором для выпадающего списка, выбранный элемент игнорируется, а отображаемый html ничего не выбрал. Не уверен, что я сделал что-то неправильно, но изменение имени идентификатора устраняет проблему. Я упростил пример, надеюсь, что это понятно, иначе, пожалуйста, дайте мне знать.

Вот мой взгляд, где объявленный идентификатор совпадает с моим списком в модели:

<table border="0" cellpadding="0" cellspacing="0">
   <tr>
      <td>
         <%= Html.DropDownList("IsMultipleServicers", Model.IsMultipleServicers) %>
      </td>
   </tr>
</table>

И предоставленный Html

<table border="0" cellpadding="0" cellspacing="0">
      <tr>
         <td>
             <select id="IsMultipleServicers" name="IsMultipleServicers">
                <option value="false">No</option>
                <option value="true">Yes</option>
             </select>
         </td>
      </tr>
</table>

Теперь сделаем небольшое изменение. Я изменю объявленный идентификатор на что-то другое.

Вот мой вид:

<table border="0" cellpadding="0" cellspacing="0">
    <tr>
       <td>
          <%= Html.DropDownList("MultipleServicers", Model.IsMultipleServicers) %>
       </td>
    </tr>
</table>

И теперь вынесенный html:

<table border="0" cellpadding="0" cellspacing="0">
   <tr>
      <td>
         <select id="IsMultipleServicers" name="IsMultipleServicers">
            <option value="false">No</option>
            <option selected="selected" value="true">Yes</option>
         </select>
      </td>
   </tr>
</table>

Обратите внимание, что теперь я получаю выбранную опцию, которая будет вторым элементом в списке.

Вот моя ViewModel только для того, чтобы связать все вместе:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace MVCProject.Models.ViewModels.Service
{
    public class ServiceViewModel : ViewModel
    {
         public List<SelectListItem> IsMultipleServicers { get; set; }
    }
}

Вот мое действие:

[AcceptVerbs(HttpVerbs.Get)]
public virtual ActionResult Service()
{
   return View(new ServiceViewModel()
   {
      IsMultipleServicers = BuildBooleanSelectList(true)
   };
}

 private List<SelectListItem> BuildBooleanSelectList(bool isTrue)
 {
    List<SelectListItem> list = new List<SelectListItem>();

    if (isTrue)
    {
       list.Add(new SelectListItem() { Selected = false, Text = "No", Value = "false" });
       list.Add(new SelectListItem() { Selected = true, Text = "Yes", Value = "true" });
    }
    else
    {
       list.Add(new SelectListItem() { Selected = true, Text = "No", Value = "false" });
       list.Add(new SelectListItem() { Selected = false, Text = "Yes", Value = "true" });
    }
 return list;
  }

Ответ 1

Я думаю, что проблема заключается в путанице в отношении перегрузок DropDownList:

  • Html.DropDownList(string name) ищет свойство модели просмотра name и введите IEnumerable<SelectListItem>. Он будет использовать выбранный элемент (SelectListItem.Selected == true) из списка, если только одно сообщение о значении формы не указано.

  • Html.DropDownList(string name, IEnumerable<SelectListItem> selectList) использует элементы из selectList, но не их выбранные значения. Выбранный найден путем разрешения name в модели представления (или пост-данных) и сопоставления ее с SelectListItem.Value. Даже если значение не может быть найдено (или равно null), оно все равно не будет использовать выбранное значение из списка SelectListItems.

Ваш код использует вторую перегрузку, но указывает свойство "значение", которое не существует ( "MultipleServicers" ).

Чтобы исправить вашу проблему, используйте первую перегрузку:

<%= Html.DropDownList("IsMultipleServicers") %>

Или добавьте свойство string MultipleServicers в свою модель просмотра и заполните его в своем контроллере. Я бы рекомендовал это решение, поскольку он сталкивается с рядом проблем с начальным отображением, отображением сообщений и отображением данных сообщения в модель вида/публикации:

public class ServiceViewModel : ViewModel 
{ 
     public string MultipleServicers { get; set; } 
     public List<SelectListItem> IsMultipleServicers { get; set; } 
}

Затем для вашего HTML:

<%= Html.DropDownList(Model.MultipleServicers, Model.IsMultipleServicers) %>

Этот метод также отображается в MVC2:

<%= Html.DropDownListFor(x => x.MultipleServicers, Model.IsMultipleServicers) %>

Ответ 2

Я столкнулся с этой же проблемой, используя перегрузку Html.DropDownList(имя строки, IEnumerable selectList). Похоже, что моя модель имеет свойство с тем же именем, что и имя выпадающего списка. В этом случае MVC одобрил значение свойства моей модели над свойством Selected каждой записи в IEnumerable.

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

Ответ 3

Помощник DropDownList извлекает значение по умолчанию из модели. В первом случае значением в модели, соответствующей названию, является SelectList - это не соответствует ни одному из элементов в списке, это список, поэтому не выбрано никакое значение. Во втором примере ваша модель не включает свойство с этим именем, поэтому значение из модели нельзя использовать и по умолчанию оно соответствует состоянию, указанному в самом SelectList. Как правило, у меня будет свойство модели для выбранного значения - это становится значением по умолчанию - и другое свойство, представляющее потенциальные значения для списка.