MVC: Uso de ListBox para selección múltiple de opciones

Cuando la elección de un usuario no es única, un DropDownList no nos alcanza.
Para este caso, es necesario un control que permita al usuario realizar más de una selección y que la misma llegue al controller para poder ser procesada.
En esta nota extenderemos lo visto en este post. Allí veíamos la posibilidad de enviar un array de opciones seleccionadas en un ListBox pero a través de ajax. En esta oprtunidad, veremos como hacer para que lo haga el propio framework de MVC, usando un formulario y que llegue al controller a través del propio framework de MVC, usando HttpPost.

Modelo

Utilizaremos un modelo muy similar al ya visto en esa nota, con la diferencia que en lugar de usar un array, usaremos directamente una lista y no será simplemente un string, sino otro objeto complejo.


public class Materia
{
    public int Id { get; set; }
    public string Descripcion { get; set; }
}

public class Inscripcion
{
    [Required]
    public string Alumno { get; set; }
    [Required]
    public string Dni { get; set; }
    public List Materias { get; set; }
    [Required]
    public List MateriasSeleccionadas { get; set; }
}

Controller

En nuestro controller, crearemos una propiedad dinámica en ViewBag para contener la lista de materias disponibles para inscribirse. Para este ejemplo, crearemos la lista en el momento, pero bien podría obtenerse desde un repositorio de datos.
Hay que notar el hecho de que la propiedad creada en ViewBag, debe llamarse diferente de cualquier otra propiedad perteneciente al modelo de la vista, en este caso, de Inscripcion.

Lamentablemente, al momento de realizarse la acción post del submit, MVC no nos puede crear la lista de objetos Materia que el usuario ha seleccionado, pero sí una lista de enteros con los Id de dichas materias. Con esta información, podemos llenar la lista de materias con las que el usuarios ha seleccionado.


public class InscripcionesController : Controller
{
    //Código omitido para resumir.

    public ActionResult Inscribir()
    {
        //Creamos una propiedad para alimentar el ListBox.
        ViewBag.ListMaterias = new MultiSelectList( this.repositorioMaterias.ObtenerTodo(), "Id", "Descripcion" );
        return View();
    }

    [HttpPost]
    [ValidateAntiForgeryToken]
    public virtual ActionResult Inscribir( Inscripcion entidad )
    {
        if ( ModelState.IsValid )
        {
            //Llenamos la lista de materias, en base a los id de materias seleccionadas
            foreach ( var materiaId in entidad.MateriasSeleccionadas )
            {
                //Como el repositorio acá usado no es "real",
                entidad.Materias.Add( this.repositorioMaterias.Obtener( materiaId ) );
                //En caso de tener un repositorio "real", se debe utilizar la línea siguiente, en lugar de la anterior.
                //entidad.Materias.Add( new Materia() { Id = materiaId } );
            }

            this.repositorioInscripciones.Grabar( entidad );
            return RedirectToAction( "Index" );
        }

        return View( entidad );
    }
}

Vista

Como se podrá ver, en el listado anterior, la clase o modelo Inscripcion posee dos listas. La primera es una lista de objetos Materia (List<Materia> Materias). Dependiendo del framework de persistencia que se utilice, este puede ser el listado persistible de materias a las que el alumno se inscribe. En segundo lugar, una lista de enteros (List<int> MateriasSeleccionadas) esta será la lista que será recibida por el controller con las materias seleccionadas por el alumno.
Para la vista, utilizaremos dos textbox; el primero para el DNI y el segundo para el nombre del alumno. Y además, usaremos un listbox para mostrar todas las materias disponibles a las que puede inscribirse un alumno.


    <tag>
@using (Html.BeginForm()) {
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)

    <fieldset>
        <!--...Controles para Nombre del alumno y DNI omitidos para resumir el código...-->

        <div class="editor-label">
            @Html.LabelFor(model => model.MateriasSeleccionadas)
        </div>
        <div class="editor-field">
             <!--Aquí utilizamos la opción ListBox de Html hepler. Indicamos como nombre del objeto, el nombre de la propiedad y luego usamos al ViewBag para poblar el control.-->
            @Html.ListBox( "MateriasSeleccionadas", ViewBag.ListMaterias as MultiSelectList )
            @Html.ValidationMessageFor(model => model.MateriasSeleccionadas)
        </div>

    </fieldset>
}


Para que resulte más práctico, dejo a disposición la descarga de este ejemplo. El mismo fue creado con Visual Studio 2012 y .Net Framework 4.5.

0 comentarios:

Publicar un comentario

Muchas gracias por leer el post y comentarlo.

 
Copyright 2009 Programación SOLIDa
BloggerTheme by BloggerThemes | Design by 9thsphere