2013-06-04 2 views
6

Attualmente non sono soddisfatto del modo in cui vengono popolati gli oggetti DropDownListFor(). Sto tentando di trovare un modo generico per popolare IEnumerable il più possibile. Questo è quello che ho finora.ASP.NET MVC 3 Elenco <T> in IEnumerable <SelectListItem>

Helper:

public static List<SelectListItem> ToSelectList(IDictionary<string,string> dictionaryItems, string selectedValue, string noSelection, bool search = false) 
    { 
     List<SelectListItem> items = new List<SelectListItem>(); 

     if (search) 
     { 
      items.Add(new SelectListItem { Selected = true, Value = "-1", Text = string.Format("-- {0} --", noSelection) }); 
     } 

     foreach (var item in dictionaryItems) 
     { 
      items.Add(new SelectListItem 
      { 
       Text = item.Key, 
       Value = item.Value, 
       Selected = selectedValue == item.Value ? true : false 
      }); 
     } 

     return items 
      .OrderBy(l => l.Text) 
      .ToList(); 
    } 

Controller:

[HttpGet] 
    public ActionResult Index() 
    { 
     var model = new CreateModel(); 

     var parentOrganisations = _orgs.FindBy(o => o.OwningOrganisationID == Globals.OrganisationID || o.ID == Globals.OrganisationID) 
      .OrderBy(o => o.OrganisationName); 

     Dictionary<string, string> items = new Dictionary<string, string>(); 

     foreach (var item in parentOrganisations) 
     { 
      items.Add(item.OrganisationName, item.ID.ToString()); 
     } 

     model.Organisations = SelectLists.ToSelectList(items, "-1", "-- None -- ", true); 

     return View(model); 
    } 

Vista:

<div class="control-group"> 
     <label class="control-label">Parent Organisation</label> 
     <div class="controls"> 
      @Html.DropDownListFor(m => m.ParentOrganisationID, Model.Organisations, new { @class = "input-xlarge"}) 
      <p class="help-block">Select a parent organisation to create a branch</p> 
     </div> 
    </div> 

Sembra che ci sia un sacco di codice ripetitivo nel controller. Prende un elenco generico, aggiunge il valore e il testo a un dizionario e quindi lo utilizza come input per un helper che crea l'elenco di selezione da inviare come parte del modello.

Qualcuno ha modi migliori per raggiungere questo obiettivo? Odio avere gonfiare il mio controller e quando ottengo diversi drop down su un modulo questo è esattamente ciò che accadrà in questo caso.

Grazie,

EDIT - Grazie al metodo di supporto di Kenneth, ho ormai consolidato il tutto in una chiamata nel controller:

  model.Organisations = _orgs.FindBy(o => o.OwningOrganisationID == Globals.OrganisationID || o.ID == Globals.OrganisationID) 
      .OrderBy(o => o.OrganisationName) 
      .ToList() 
      .ToSelectList(org => org.OrganisationName, org => org.ID.ToString(), "-1", "None", true); 

risposta

8

si potrebbe fornire callback che ottengono la chiave e la valore e quindi utilizzare quelli. A parte che è possibile creare come un metodo di estensione:

metodo di estensione:

public static List<SelectListItem> ToSelectList<T>(this List<T> Items, Func<T, string> getKey, Func<T, string> getValue, string selectedValue, string noSelection, bool search = false) 
    { 
     List<SelectListItem> items = new List<SelectListItem>(); 

     if (search) 
     { 
      items.Add(new SelectListItem { Selected = true, Value = "-1", Text = string.Format("-- {0} --", noSelection) }); 
     } 

     foreach (var item in Items) 
     { 
      items.Add(new SelectListItem 
      { 
       Text = getKey(item), 
       Value = getValue(item), 
       Selected = selectedValue == getValue(item) ? true : false 
      }); 
     } 

     return items 
      .OrderBy(l => l.Text) 
      .ToList(); 
    } 

Usage:

List<Org>() parentOrganisations = // fetch here 
model.Organisations = parentOrganisations.ToSelectList(org => org.ID.ToString(), 
                 org => org.OrganisationName, 
                 "-1", 
                 "-- None -- ", 
                 true); 

Nota: ho scritto questo nel SO-editore, quindi potresti avere alcuni errori di sintassi (dovrebbero comunque essere facili da risolvere).

+0

Grazie! Questo è esattamente quello che speravo. – Paul

1

Si può fare in centralina solo in questo modo: -

List<SelectListItem> dropdownItems = parentOrganisations 
    .Select(item => new SelectListItem 
    { 
     Value = item.ID.ToString(), 
     Text = item.OrganisationName, 
     Selected = "-1" == item.ID.ToString() ? true : false 
    }) 
    .ToList();