2011-05-10 2 views
4

Je suis un modèle défini comme IEnumerable<MyViewModel> que j'ai essayé d'utiliser pour créer une liste de sélection (Html.SelectListFor). Mais je ne pouvais pas comprendre comment le faire. Ce qui m'a fait regarder la méthode plaine Html.SelectList.Faire face à des listes de sélection

Comme il veut un IEnumerable<SelectListITem> et je ne veux pas ajouter vue logique spécifique dans mon contrôleur ou logique à mon avis, je fini par créer la méthode d'extension suivante:

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(); 
    } 

} 

qui me sert:

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

Cela ne semble pas être la solution optimale. Comment aurais-je dû faire?

+1

Cela semble être une très bonne solution générique pour construire des listes de sélection – hunter

+0

Il fonctionne, mais il doit y avoir un moyen d'avancer plus droit de le faire avec MVC? Si non, quel est le but de 'Html.SelectListFor'? – jgauffin

+0

"Je ne veux pas ajouter de logique spécifique à la vue dans mon contrôleur" - Attendez, n'est-ce pas la responsabilité principale du contrôleur? Assemble les données pour la vue? – jfar

Répondre

1

Je suppose que la réponse est que je suis déjà en utilisant le meilleur Solution.

0

jg,

funnily enogh, je dois avoir un article similaire d'origine lors de la recherche d'une solution comme celui-ci. J'ai une méthode EXTN qui va:

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; 
} 

et est invoquée comme:

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

comment bizarre. J'aime réellement cette méthode car elle est à la fois générique et en utilisant l'entité elle-même pour comparer l'élément sélectionné avec, signifie que vous n'êtes pas en train de comparer les ID etc ..

travaille pour moi.

0

Je aime vraiment cette approche. J'ai fait un changement pour ajouter un paramètre d'élément sélectionné.

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)) 
            }); 
    } 

Aussi, j'ai pu utiliser ce code avec Html.DropDownListFor, qui a complètement éliminé la nécessité pour les chaînes magiques:

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

presque un « déclic » robert :) –

+1

@ Jim - si près! –

Questions connexes