Tratar con listas seleccionadas

Tengo un modelo definido como IEnumerable<MyViewModel> que intenté usar para crear una lista de selección (Html.SelectListFor). Pero no pude averiguar cómo hacerlo. Que me hizo mirar el llano Html.SelectList método.

Ya que quiere un IEnumerable<SelectListITem> y no quiero agregar lógica de vista específica en mi controlador o lógica en mi vista, terminé creando el siguiente método de extensión:

public static class ExtensionMethods
{
    public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> items, Func<T, string> valueSelector, Func<T, string> textSelector)
    {
        return items.Select(item => new SelectListItem
                                        {
                                            Text = textSelector(item),
                                            Value = valueSelector(item)
                                        }).ToList();
    }

}

Que utilizo como:

@Html.DropDownList("trainid", Model.ToSelectList(item => item.Id, item => item.Name));

Ésta no parece ser la solución óptima. ¿Cómo debería haberlo hecho?

preguntado el 10 de mayo de 11 a las 12:05

Parece una muy buena solución genérica para crear listas seleccionadas.

Funciona, pero ¿debe haber una forma más sencilla de hacerlo con MVC? Si no es así, ¿cuál es el propósito de Html.SelectListFor? -

"No quiero agregar lógica de vista específica en mi controlador" - Espera, ¿no es esta la responsabilidad principal del controlador? ¿Reunir datos para la vista? -

Reunir datos sí. ¿Pero generar una lista de selección / html? En mi humilde opinión, eso es muy específico de vista. -

Estoy de acuerdo con Hunter, ¿qué tiene de malo? "Si es estúpido pero funciona, no es estúpido". También obtuve algo muy parecido a eso. -

3 Respuestas

Supongo que la respuesta es que ya estoy usando la mejor solución.

contestado el 29 de mayo de 11 a las 12:05

jg,

curiosamente enogh, debo haber obtenido un artículo similar al buscar una solución como esta. tengo un método extn que dice:

public static IList<SelectListItem> ToSelectItemList<T>(
    this IEnumerable<T> list, 
    Func<T, string> textSelector, 
    Func<T, string> valueSelector, T selected) where T : class
{
    var results = new List<SelectListItem>();
    if (list != null)
    {
        results.AddRange(
            list.Select(item => new SelectListItem
            {
                Text = textSelector.Invoke(item), 
                Value = valueSelector.Invoke(item), 
                Selected = selected != null ? selected.Equals(item) : false
            }));
    }
     return results;
}

y se invoca como:

<%: Html.DropDownList("Base.EntityRootID", Model.EntityRootList.ToSelectItemList(foo => foo.EntityName, foo => foo.ID.ToString(), Model.Base.EntityRoot))%>

que raro. De hecho, me gusta este método, ya que es genérico y al usar la entidad en sí para comparar el elemento seleccionado, significa que no estás cerca de comparar ID, etc.

funciona para mi.

contestado el 10 de mayo de 11 a las 23:05

Realmente me gusta este enfoque. Hice un cambio para agregar un parámetro de elemento seleccionado.

public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> items, Func<T, string> value, Func<T, string> text, object selectedValue)
    {
        return items.Select(item => new SelectListItem
                                     {
                                         Text = text(item),
                                         Value = value(item),
                                         Selected = (selectedValue.ToString() == value(item))
                                     });
    }

Además, pude usar este código con Html.DropDownListFor, que eliminó por completo la necesidad de cadenas mágicas:

Html.DropDownListFor(x => x.ContractId, Model.Contracts.ToSelectList(x => x.Value, x => x.Disp, Model.ContractId))

contestado el 11 de mayo de 11 a las 00:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.