2010-07-07 3 views
44

En travaillant sur ma première application Web ASP.Net MVC2 récemment, j'ai rencontré quelques problèmes lorsque j'ai dû sélectionner plusieurs valeurs dans une zone de liste. J'ai travaillé autour avec un peu de jQuery, mais je suis allé de l'avant et j'ai mis en place un code très simple à démontrer. J'utilise EF pour le modèle, avec deux entités - Les clients et HelpDeskCalls:Challenges avec la sélection des valeurs dans ListBoxFor

Controller:

public ActionResult Edit(int id) 
    { 
     Customer currCustomer = ctx.Customers.Include("HelpDeskCalls").Where(c => c.ID == id).FirstOrDefault(); 
     List<HelpDeskCall> currCustCalls = (ctx.HelpDeskCalls.Where(h => h.CustomerID == id)).ToList(); 
     List<SelectListItem> currSelectItems = new List<SelectListItem>(); 
     List<String> selectedValues = new List<string>(); 
     foreach (HelpDeskCall currCall in currCustCalls) 
     { 
      bool isSelected = (currCall.ID % 2 == 0) ? true : false; 
      //Just select the IDs which are even numbers... 
      currSelectItems.Add(new SelectListItem() { Selected = isSelected, Text = currCall.CallTitle, Value = currCall.ID.ToString() }); 
      //add the selected values into a separate list as well... 
      if (isSelected) 
      { 
       selectedValues.Add(currCall.ID.ToString()); 
      } 
     } 
     ViewData["currCalls"] = (IEnumerable<SelectListItem>) currSelectItems; 
     ViewData["currSelected"] = (IEnumerable<String>) selectedValues; 
     return View("Edit", currCustomer); 
    } 

Vue:

<div class="editor-field"> 
    <%: Html.ListBoxFor(model => model.HelpDeskCalls, new MultiSelectList(Model.HelpDeskCalls, "ID", "CallTitle", (IEnumerable) ViewData["currSelected"]), new { size = "12" })%>  
    <%: Html.ListBoxFor(model => model.HelpDeskCalls, ViewData["currCalls"] as IEnumerable<SelectListItem>, new { size = "12"}) %> 
    <%: Html.ListBox("Model.HelpDeskCalls", new MultiSelectList(Model.HelpDeskCalls, "ID", "CallTitle", (IEnumerable)ViewData["currSelected"]), new { size = "12"}) %>  
    <%: Html.ValidationMessageFor(model => model.HelpDeskCalls) %> 
</div> 

Pour cet exemple, je suis juste sélectionner HelpDeskCall. Les ID qui sont pairs. J'essaie deux syntaxes différentes pour ListBoxFor: L'une utilise un IEnumerable de valeurs pour les sélections, l'autre utilise un IEnumerable de SelectListItems. Par défaut, lorsque je cours ce code, aucune sélection n'est faite à ListBoxFor, mais la ListBox non fortement typée sélectionne correctement. Je lis this post sur ASP.Net et this thread sur SO, mais pas de joie. En fait, si j'ajoute le remplacement ToString() à ma classe HelpDeskCall (comme suggéré dans le thread ASP.net), toutes les valeurs sont sélectionnées, ce qui n'est pas correct non plus.

Si quelqu'un pouvait faire la lumière sur la façon dont cela devrait fonctionner (et ce qui me manque ou mal faire), alors ce néophyte serait très reconnaissant.

Répondre

89

Voici un exemple illustrant la version fortement typé:

Modèle:

public class MyViewModel 
{ 
    public int[] SelectedItemIds { get; set; } 
    public MultiSelectList Items { get; set; } 
} 

Controller:

public class HomeController : Controller 
{ 
    public ActionResult Index() 
    { 
     // Preselect items with id 1 and 3 
     var selectedItemIds = new[] { 1, 3 }; 

     var model = new MyViewModel 
     { 
      Items = new MultiSelectList(
       new[] 
       { 
        // TODO: Fetch from your repository 
        new { Id = 1, Name = "item 1" }, 
        new { Id = 2, Name = "item 2" }, 
        new { Id = 3, Name = "item 3" }, 
       }, 
       "Id", 
       "Name", 
       selectedItemIds 
      ) 
     }; 

     return View(model); 
    } 
} 

Vue:

<%: Html.ListBoxFor(x => x.SelectedItemIds, Model.Items) %> 
+0

Oui, cela fonctionne. Merci! – JohnMc0831

+0

Brillant! J'ai passé un moment à essayer de faire fonctionner ça. Cela a fonctionné pour moi aussi. Merci beaucoup! Upvoting. –

+0

ty! Cela m'a aidé beaucoup. – Kevin

2

J'ai trouvé une meilleure solution . manière habituelle de présélectionner liste de sélection:

@Html.ListBoxFor(
    model => model.Roles, 
    new MultiSelectList(db.Roles, "Id", "Name") 
) 
@Html.ValidationMessageFor(model => model.Roles)  

ne fonctionne pas .., jamais une option est sélectionnée, jusqu'à ce que:

public ActionResult Edit(int id) 
{ 
    var user = db.Users.Find(id); 
    // this is workaround for http://aspnet.codeplex.com/workitem/4932?ProjectName=aspnet 
    ViewData["Roles"] = user.Roles.Select(r => r.Id); 
    return View(user); 
} 

rôles sélectionnés doit être stocké dans ViewData, pour contourner vilain bug .

+0

Probablement évident (mais toujours agréable à savoir): cela fonctionne aussi si vous utilisez le ViewBag.Roles de style MVC3. –

+0

Aide même dans MVC5. Pourquoi ça fonctionne? –

8

Je ne sais pas si ce comportement a changé dans le RTM de MVC3 que j'utilise, mais il semble que la sélection et la liaison fonctionnent désormais correctement. Le seul hic est que le modèle doit contenir une propriété avec les ID, comme ça:

public class MyViewModel { 
    public int[] ItemIDs { get; set; } 
} 

Alors ce qui suit dans la vue fonctionnerait très bien, aussi bien avant le choix des valeurs et correctement la liaison correcte lors de la post:

@Html.ListBoxFor(model => model.ItemIDs, (IEnumerable<SelectListItem>)(new[] { 
           new SelectListItem() { Value = "1", Text = "1" }, 
           new SelectListItem() { Value = "2", Text = "2" } 
          })) 
+5

Une petite correction. Même si ce qui précède fonctionne, il semble y avoir un bug mineur qui pourrait causer des problèmes. Il semble que lorsque le ViewBag contient une propriété nommée "X" et que la propriété du modèle est aussi nommée "X", la sélection automatique de la ListBox ne fonctionne pas ... Des choses étranges ... – kkara

+0

Ce commentaire m'a vraiment sauvé! – loraderon

+0

Toujours en 2016, ces commentaires m'aident - j'avais une propriété ViewBag avec le même nom que la propriété du modèle lié, donc la population d'éléments sélectionnés ne fonctionnait pas. – PhillipH

Questions connexes