Razor и Html.DropDownList: установка выбранных значений для раскрывающегося списка для каждой строки в списке? - PullRequest
1 голос
/ 03 августа 2011

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

В моей модели данных есть таблица «Server» и таблица «ServerType». PK для обеих таблиц - целые числа, и у Сервера есть поле ServerTypeId, которое является fk для ServerType.Id.

У меня есть Razor List.cshtml, который напечатан в IEnumerable:

@model IEnumerable<Server>
<table border="1">
    <tr>
        <th>
            Server Type
        </th>
        <th>
            Name
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DropDownListFor(modelItem => item.ServerTypeId, (IEnumerable<SelectListItem>)ViewData["ServerType"])
            </td>
            <td>
                @Html.DisplayFor(modelItem => item.Name)
            </td>
        </tr>
    }
</table>

Мой контроллер имеет:

    public ActionResult List()
    {
        var s = GetServers();
        ViewData["ServerType"] = GetServerTypes();
        return View("List", s);
    }

    private List<SelectListItem> GetServerTypes()
    {
        string id;
        SelectListItem si;
        List<SelectListItem> sl = new List<SelectListItem>();
        IQueryable<ServerType> items = (from t in _entities.ServerTypes select t);
        foreach (var item in items)
        {
            id = item.Id.ToString();
            si = new SelectListItem { Value = id, Text = item.Description };
            sl.Add(si);
        }
        return sl;
    }

Отображает данные, но значение в раскрывающемся списке не выбрано. Я пробовал как Html.DropDownList, так и Html.DropDownListFor, с разными перестановками имен для свойства ViewData, с идентификатором Id и без него в конце.

Нужно ли создавать модель представления с копиями ServerType, чтобы установить свойство Selected? Или это проблема, потому что мои идентификаторы являются целочисленными, а свойство SelectItemList Value является строкой?

Ответы [ 3 ]

1 голос
/ 01 июля 2013

@ TreyE правильно указывает, что вы никогда не указываете, что какой-либо конкретный элемент списка выбора должен быть выбран при отображении в представлении.

Есть несколько способов сделать это. Сначала нужно использовать объект SelectList и использовать его конструктор, который позволяет передавать объект, который должен быть выбран, это перегрузка SelectList(IEnumerable, String, String, Object) MSDN SelectList .

SelectList поддерживается только в .NET 3.5+, однако, к вашему сведению.

Во-вторых, в GetServerTypes() вы можете написать:

private List<SelectListItem> GetServerTypes()
{
    List<SelectListItem> sl = new List<SelectListItem>();
    IQueryable<ServerType> items = (from t in _entities.ServerTypes select t);

    foreach (var item in items)
        sl.add(new SelectListItem { Value = item.id, Text = item.Description, Selected = item.isSelected } );

    return sl;

}

Также помните, что должен быть выбран только один элемент, поэтому убедитесь, что если вы попытаетесь использовать какое-либо логическое свойство, то не исключено, что более чем у одного item может быть установлено свойство isSelected, установленное на true.

В качестве альтернативы, если вам нужно использовать какой-то тип оператора if, чтобы решить, является ли Selected = true (т.е. ваш элемент не имеет логического значения isSelected), вы можете добавить это в цикл foreach.

foreach(var item in items)
{
    if //condition
      sl.Add(new SelectListItem { Value = item.id, Text = item.Description, Selected = true });

    else
      sl.Add(new SelectListItem { Value = item.id, Text = item.Description, Selected = false });
}
1 голос
/ 01 августа 2014

Для всех, кто еще ищет ответ. Я должен был сделать 3 вещи, чтобы заставить это работать

  1. Пользователь @for вместо @foreach. Это так, у него есть индекс для работы с при названии вещей.
  2. Не иметь имя переменной ViewBag так же, как собственность. Он пытается помочь вам и связывает вещи тоже рано, если они имеют одинаковое имя.
  3. Передать текущее значение в конструкторе для SelectList. мой код закончился как:

       @for (int i = 0; i < Model.Count; i++)
       {
           <tr>
               <td>          
          @Html.DropDownListFor(modelItem => Model[i].operatorToken, 
    new SelectList(ViewBag.operatorTokensList, "Value", "Text", Model[i].operatorToken), 
    "Select", htmlAttributes: new { @class = "form-control" })
    
    
    
    ...ect...
        }
    

    Обратите внимание, что 4-й параметр для SelectList () устанавливает выбранное значение.

    Мой operatorTokensList был оценен с:

    new[] { new { Value = ">", Text = ">" }, 
                   new { Value = ">=", Text = ">=" },
                   new { Value = "=", Text = "=" },
                   new { Value = "<=", Text = "<=" },
                   new { Value = "<", Text = "<" } };
    

(пользователь выбирал «больше чем», «больше или равно» и т. Д.)

1 голос
/ 03 августа 2011

Ни в одной точке вашего населения Списка в GetServerTypes () вы не указали, что какой-либо из элементов выбран. Это то, что вам нужно сделать вручную, поскольку MVC3 не достаточно умен, чтобы сделать это для вас в методе DropDownListFor. Это еще более осложняется тем, что вы не используете одну модель.

Лучший способ сделать это может быть:

(Имейте в виду, что в приведенном ниже коде я предполагаю, что класс Server имеет первичный идентификатор с именем "Id")

Для кода контроллера:

public ActionResult List()
{
    IEnumerable<Server> s = GetServers();
    ViewData["ServerTypes"] = GetServerTypes(s);
    return View("List", s);
}

private Dictionary<int, SelectList> GetServerTypes(IEnumerable<Server> s)
{
    Dictionary<int, SelectList> sl = new Dictionary<int, SelectList>();
    IEnumerable<ServerType> items = (from t in _entities.ServerTypes select t);
    foreach (Server srv in s) {
      sl.Add(srv.Id, new SelectList(items, "Id", "Description", srv.ServerTypeId));
    }
    return sl;
}

Для кода просмотра:

(также обратите внимание, как я исправил аргументы, используемые в лямбда-функциях)

@model IEnumerable<Server>
<table border="1">
    <tr>
        <th>
            Server Type
        </th>
        <th>
            Name
        </th>
    </tr>
    @foreach (var item in Model)
    {
        <tr>
            <td>
                @Html.DropDownListFor(modelItem => modelItem.ServerTypeId, (IEnumerable<SelectListItem>)(ViewData["ServerTypes"][item.Id]))
            </td>
            <td>
                @Html.DisplayFor(modelItem => modelItem.Name)
            </td>
        </tr>
    }
</table>
...