Список MVC‹SelectListItem› с группами, создающими optgroup для каждого элемента

У меня возникла проблема, когда я создаю List<SelectListItem> с optgroups, но вместо создания optgroup для группы из SelectListItem создается новый SelectListGroup для SelectListItem. Это меня немного смутило, потому что в моем коде нет повторяющихся SelectListGroup.

Вот пример:

Ожидаемый результат:

<select datatag="data-States=''" class="form-control filter-select" data-multi-select="" id="States" multiple="multiple" name="States">
    <optgroup label="MA">
    <option value="01602">01602</option>
    <option value="02743">02743</option>
    <option value="01107">01107</option>
    </optgroup>
    </select>

Фактический результат:

<select datatag="data-States=''" class="form-control filter-select" data-multi-select="" id="States" multiple="multiple" name="States">
<optgroup label="MA">
<option value="01602">01602</option>
</optgroup>
<optgroup label="MA">
<option value="02743">02743</option>
</optgroup>
<optgroup label="MA">
<option value="01107">01107</option>
</optgroup>
</select>

Метод:

 public ManifestFilterDropDownItem ReturnManifestFilterDataBasedOnTotalDataSet(IEnumerable<ManifestTableItem> data, bool isUserASR) {
            IEnumerable<SelectListGroup> stateGroups = data.Select(x => x.AddrState.ToUpper()).Distinct().Select(x => new SelectListGroup() {
                Name = x
            });

            IList<SelectListItem> stateZipSelectListItems = data.GroupBy(x => x.AddrZip).Select(x => new SelectListItem() {
                Text = string.IsNullOrWhiteSpace(x.Key) ? "Empty" : x.Key,
                Value = string.IsNullOrWhiteSpace(x.Key) ? "" : x.Key,
                Group = stateGroups.Where(y => y.Name == data.Where(p => p.AddrZip == x.Key).First().AddrState.ToUpper()).Single()
            }).OrderBy(x => x.Group.Name).ToList();


            var manifestItem = new ManifestFilterDropDownItem {
                States = stateZipSelectListItems
            return manifestItem;
        }

ViewModel:

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

namespace FSVendor.Models.Manifest {
    public class ManifestFilterViewModel {
        public ManifestFilterViewModel() {

        }

        public string Name { get; set; }
        public string DataTag => $"data-{Name}=''";
        public IEnumerable<SelectListItem> SelectListItems { get; set; }
    }
}

Вид:

@model FSVendor.Models.Manifest.ManifestFilterViewModel

<label>States:</label>
@Html.DropDownList(Model.Name, Model.SelectListItems, new { @class = "form-control filter-select", data_multi_select = "", multiple = "multiple", @Model.DataTag })

person Andrew    schedule 25.06.2018    source источник


Ответы (2)


Ваш запрос создает новый SelectListGroup для каждого SelectListItem, хотя каждый SelectListGroup имеет одинаковое значение.

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

// Initialize model
var model = new ManifestFilterDropDownItem
{
    States = new List<SelectListItem>
}
var states = data.GroupBy(x => x.AddrState); // group by state
foreach (var group in states)
{
    // Create a SelectListGroup
    var optionGroup = new SelectListGroup() { Name = group.Key };
    // Add SelectListItem's
    foreach (var item in group)
    {   
        model.States.Add(new SelectListItem()
        {
            Value = item.AddrZip,
            Text = item.AddrZip,
            Group = optionGroup
        })
    }
}
return model;

В качестве альтернативы вы можете использовать одну из перегрузок конструктора SelectList

var model = new ManifestFilterDropDownItem
{
    States = new SelectList(data, "AddrZip", "AddrZip", "AddrState", null, null)
};
return model;

В качестве примечания: не используйте DropDownList() для создания <select multiple>. Вам нужно использовать ListBoxFor(), чтобы работала двусторонняя привязка модели. См. Почему теряет ли DropDownListFor множественный выбор после отправки, а ListBoxFor — нет?

person Community    schedule 25.06.2018
comment
Привет, по общему признанию, я еще не успел протестировать ваш код, но как мне создать новый SelectListGroup для каждого SelectListItem? Я выбираю отдельный набор AddrState, а затем зацикливаюсь, а затем устанавливаю группировку на основе почтового индекса для состояния? - person Andrew; 26.06.2018
comment
Хорошо, я проверил ваш код, и он не работает. На самом деле это не работает, когда я создаю одну группу и пытаюсь сгруппировать ее все. Я считаю, что это связано с отдельной проблемой, которую я обнаруживаю сейчас - person Andrew; 26.06.2018
comment
Я думаю, что это было связано с другой проблемой, которая у меня была. Я отследил и воспользовался вашими предложениями и удалил код, который, как мне казалось, вызывал проблемы, и это сработало, ура, братта. - person Andrew; 28.06.2018

Я считаю, что ваш класс ManifestTableItem имеет по крайней мере эту структуру:

class ManifestTableItem {
  public string AddrState { get ; set ; }
  public string AddrZip { get ; set ; }
}

Чтобы состояние отображалось как группа в selectlist, вам нужно использовать эту перегрузку:

new SelectList(data, nameof(ManifestTableItem.AddrZip), nameof(ManifestTableItem.AddrZip), null, nameof(ManifestTableItem.AddrState));
person Anup Sharma    schedule 28.08.2020