Выпадающие списки в ASP.NET MVC

| Пятница, 22 марта, 2013

Метки: ASP.NET MVC Комментарии: 0

Иногда работа c выпадающими списками вызывает некоторые затруднения. Рассмотрим пример, в котором нам нужно создать страницу редактирования музыкального трека. Каждая композиция содержится в каком либо альбоме, имеет название и номер. Это можно изобразить в следующем коде:

@Html.DropDownList("AlbumId", Model.Albums)
...
@Html.TextBox("Title", Model.Title)
...
@Html.TextBox("TrackNumber", Model.TrackNumber)

Вспомогательный метод Html.DropDownList работает с объектами SelectListItem. Модель представления можно представить так:

public class EditSongViewModel
{        
    public string Title { get; set; }                
    public int TrackNumber { get; set; }
    public IEnumerable Albums { get; set; }
}

Некоторым разработчикам не нравится использовать типы SelectListItem в моделях представления и вместо этого они конвертируют элементы коллекции в SelectListItem прямо в представлении. Но на самом очень предпочтительно использовать SelectListItem в модели представления, так как модель должна упрощать код в самих представлениях.

Создание коллекции объектов SelectListItem

Существует несколько способов для создания последовательностей объектов SelectListItem. Наиболее подходящим может быть создание метода расширения для последовательности (в нашем случае – объекты Album), в котором коллекция сущностей конвертируется в коллекцию объектов SelectListItem.

public static IEnumerable ToSelectListItems(this IEnumerable albums, int selectedId)
{
    return albums.OrderBy(album => album.Name)
              .Select(album => 
                  new SelectListItem
                  {
                    Selected = (album.ID == selectedId),
                    Text = album.Name,
                    Value = album.ID.ToString()
                   });
}

Этот метод можно использользовать так:

model.Albums = _repository.FindAllAlbums().ToSelectItems(selectedId);

Этот код работает, потому что Html.DropDownList принимает в качестве входного параметра IEnumerable.

Можно использовать класс SelectList, но применять его нужно аккуратно. Например, если в SelectList не указать параметры DataTextField и DataValueField, то выпадающий список не будет работать корректно.

// неправильное использование
model.Albums = new SelectList(
                _repository.FindAllAlbums().ToSelectListItems(1)
                );

Выпадающий список отобразит “System.Web.Mvc.SelectListItem” вместо текстового имени каждого элемента.

Класс SelectList разработан для преобразования элементов, с той же целью, что и наш метод расширения выше (для преобразования элементов в коллекцию SelectListItem), но тут используется позднее связывание. Следующий код будет работать, так как мы указали поля описаний и значений для елементов списка.

// правильное использование
model.Albums = new SelectList(
                _repository.FindAllAlbums(), "ID", "Name"
                );

Получение выбранного значения

Если для принятия данных формы страницы используется та же сама модель представления, то можно предположить, что стандартный привязчик значений ASP.NET MVC проинициализирует снова коллекцию альбомов и укажет выбранный. Но , к сожалению, это не так - коллекция альбомов будет пустой.

Серверу страница вышлет только идентификатор выбранного альбома. Если нужно получить это значение в модели, то необходимо добавить свойство AlbumID.

public class EditSongViewModel
{
    public int AlbumId { get; set; }
    public string Title { get; set; }                
    public int TrackNumber { get; set; }
    public IEnumerable<SelectListItem> Albums { get; set; }
}
И дополнительно код в представлении можно изменить так:
@Html.DropDownListFor(x => x.AlbumId, Model.Albums)
...
@Html.TextBoxFor(x => x.Title)
...
@Html.TextBoxFor(x => x.TrackNumber)

Итак, резюмируем главные моменты вышеизложенного:

  • Не используйте SelectList без указания свойств DataTextField и DataValueField.
  • Не ожидайте увидеть коллекцию для выпадающего списка заполненной при обратном ответе.
  • Методы расширения помогают создавать последовательности объектов SelectListItem в строго типизированном коде.
  • Html.DropDownList не обязательно требует SelectList – подойдет любая коллекция объектов SelectListItem.

Комментарии
Никто еще не оставил здесь комментарий.
Войдите, чтобы написать комментарий , или воспользуйтесь формой ниже.
 

Copyright © CodeHint.ru 2013-2019