Saltar al contenido

Poblar las listas desplegables en ASP.NET MVC Vistas de la Navaja

La implementación de una lista desplegable con los datos suministrados en un modelo de vista implica cuatro componentes:

  1. Ver modelo
  2. Vista de la cuchilla
  3. Acción del controlador
  4. Método de depósito

Miraremos el código esencial de cada uno de estos. Si necesita comprender mejor cómo encajan estas piezas de código en cada componente, la siguiente sección proporcionará una imagen de mayor nivel de todos los componentes.

Poblar las listas desplegables en ASP.NET MVC Vistas de la Navaja
Poblar las listas desplegables en ASP.NET MVC Vistas de la Navaja

Ver Modelo

El uso de un modelo de vista como modelo para el formulario que contiene los elementos desplegables separa la presentación de la estructura. Mantener las cosas normalizadas sucede en el extremo posterior.

En nuestro ejemplo, estamos creando un nuevo registro de clientes. Los clientes tienen propiedades del país y la región (estado o provincia).

CustomerDisplayViewModel.cs

123456789101112131415161718192021222324252627usando System.Collections.Generic;usando System.ComponentModel.DataAnnotations;usando System.Web.Mvc;namespace BlipDrop. ViewModels{publicclassCustomerEditViewModel{[Display(Name ="Customer Number")]publicstring CustomerID {get;set;}[Required][Display(Name ="Customer Name")][StringLength(75)]publicstring CustomerName {get;set;}[Required][Display(Name ="Country")]publicstring SelectedCountryIso3 {get; set;}public IEnumerable<SelectListItem > Countries {get;set;}[Requerido][Mostrar(Nombre ="Estado / Región")]publicstring SelectedRegionCode {get;set;}public IEnumerable<SelectListItem> Regions {get;set;}}}

csharp

Fíjense que para cada propiedad para la que vamos a proporcionar listas desplegables, tenemos dos campos en el modelo de vista:

  1. uno para la lista
  2. uno para el artículo seleccionado

La lista se compone de una colección de tipo SelectListItem.

El campo que almacena el elemento seleccionado contiene la clave única para cada entidad. La clave única del valor seleccionado será la misma que la de uno de los elementos del SelectListItem.

Vista de la navaja

Estos son los elementos de forma para el campo País en la vista de la Navaja que muestra la aplicación de la Lista de Bajas para HtmlHelper.

Create.cshtml, Country Snippet

123456789...}; @Html.LabelFor(x = ); Model.SelectedCountryIso3, htmlAtributos: nuevo { @class = "control-label col-md-2" }) <div> @Html. DropDownListFor(x => Model.SelectedCountryIso3, new SelectList(Model.Countries, "Value", "Text"), htmlAtributos: new { @class = "form-control", id = "Country"}) @Html.ValidationMessageFor(x = ); x.SelectedCountryIso3, "", new { @class = "text-danger" }) </div></div;...

html

Compare la declaración @Html.DropDownListFor con el modelo de vista.

x => Modelo.SelectedCountryIso3 identifica el campo del modelo de la vista donde se almacenará el valor seleccionado. Estamos almacenando el identificador único del País.

El nuevo SelectList(Model.Countries, «Value», «Text») identifica la fuente de la lista que se utilizará para rellenar la lista desplegable, IEnumerable Countries del modelo de datos. Observe que lo hace creando una nueva SelectList con los campos Valor y Texto, que corresponden a los mismos campos en la propiedad Countries del modelo de datos.

No puedes utilizar un campo de tipo SelectList en tu modelo de vista. El motor Razor necesita obtener los datos como una colección de SelectListItems para construir el elemento HTML correctamente. Esto se documenta de la manera más opaca posible en la documentación del marco de trabajo en MSDN.

Tenga en cuenta que el elemento HTML de la página renderizada tendrá un valor de atributo id de País. El código JavaScript que veremos más adelante usará los atributos id de cada uno de los elementos desplegables.

La vista completa se ve así cuando es mostrada por el navegador:

/Cliente/Crear

Acciones del controlador

Su controlador puede ser simple: su controlador sólo tiene que llamar al repositorio apropiado para obtener el modelo de la vista, y luego pasa el modelo de la vista a la vista:

CustomerController.cs, Index Action

12345678910111213141516171819usando System.Collections.Generic;usando System.Web.Mvc;usando BlipDrop.Data;usando BlipDrop.ViewModels;namespace BlipDrop.Controllers{publicclassCustomerController:Controller{// GET: ClienteClasePúblicaAcciónResultadoIndex(){var repo =nuevoClienteRepositorio();var listacliente= repo.GetCliente();returnView(listacliente);}...}}

csharp

Observe en las declaraciones de uso que el controlador hace referencia al contexto de los datos y a los modelos de vista, pero no necesita acceder a las entidades que mapean a los objetos de la base de datos.

Métodos de depósito

En nuestro simple ejemplo, el repositorio de clientes crea una instancia de CustomerEditViewModelclass y asigna un nuevo GUID al campo CustomerID.

También llama a los depósitos de países y regiones para obtener la lista de países y regiones, de modo que el modelo de vista tenga los datos para las listas desplegables de la vista.

CustomerRepository.cs

123456789101112131415161718192021222324252627usando Sistema;usando Sistema.Colecciones.Genéricas;usando Sistema.Datos.Entidad;usando Sistema.Linq;usando BlipDrop.Modelos;usando BlipDrop.ViewModels;espacio de nombres BlipDrop.Datos{clase públicaClientesRepositorio{... publicCustomerEditViewModelCreateCustomer(){var cRepo =newCountriesRepository();var rRepo =newRegionsRepository();var customer =newCustomerEditViewModel(){ CustomerID = Guid. NewGuid().ToString(), Countries = cRepo.GetCountries(), Regions = rRepo.GetRegions()};return customer;}...}}

csharp

Obsérvese que en este escenario no es necesario utilizar una instancia del contexto de datos, ApplicationDbContext, para crear una instancia del CustomeEditViewModel porque sólo los campos Países y Regiones requieren llamadas a la base de datos para obtener valores, y esas llamadas son manejadas por los respectivos repositorios de esos objetos.

PaísesRepository.cs

12345678910111213141516171819202122232425262728293031 usando System.Collections.Generic;usando System.Linq;usando System.Web.Mvc;namespace BlipDrop. Data{publicclassCountriesRepository{public IEnumerable<SelectListItem >GetCountries(){using(var context =newApplicationDbContext()){ List<SelectListItem> countries = context. Countries.AsNoTracking().OrderBy(n = > n.CountryNameEnglish).Select(n = ];newSelectListItem{ Value = n.Iso3.ToString(), Text = n.CountryNameEnglish }). ToList();var countrytip =newSelectListItem(){ Valor =null, Texto ="--- select country ---"}; countries.Insert(0, countrytip);returnnnewSelectList(countries, "Value", "Text");}}}

csharp

Obsérvese que el tipo de devolución para el Depósito de Países es el mismo que el de la lista de Países en el modelo de vista, IEnumerable. Esta es la misma colección que utiliza la declaración @Html.DropDownListFor en la vista Razor. El elemento Value de cada SelectListItem es el código Iso3 del País convertido de una GUID a texto.

RegionsRepository.GetRegions() devuelve una colección SelectListItem vacía. Esto es para que el modelo de la vista no pase una referencia de objeto nulo a la lista desplegable de Regiones.

RegionsRepository.cs, Part 1

1234567891011121314151617181920212223usando el sistema;usando System.Collections.Generic;usando System.Linq;usando System.Web.Mvc;namespace BlipDrop. Datos{clase públicaRegionesRepositorio{público IEnumerable<SelectListItem{;GetRegions(){ List<SelectListItem;}; regiones =newList<SelectListItem;}} {newSelectListItem{ Valor =nulo, Texto =" "}};regiones de retorno;}}}

csharp

Iniciar un menú desplegable dependiente de esta manera también le da la oportunidad de mostrar un mensaje informativo (por ejemplo, «seleccione un país primero») antes de poblar los valores de la lista.