47 votes

Défis liés à la sélection de valeurs dans ListBoxFor

C'est ma première question, et c'est probablement une mauvaise, de sorte s'il vous plaît être doux.

Mon travail sur mon premier ASP.Net MVC2 web app récemment, je suis tombé sur quelques questions quand j'en avais besoin pour sélectionner plusieurs valeurs dans une liste déroulante. J'ai travaillé autour avec un peu de jQuery, mais est allé de l'avant et de mettre ensemble quelques code très simple à démontrer. Je suis à l'aide de EF pour le modèle, avec deux entités - Clients et HelpDeskCalls:

Contrôleur:

 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 en sélectionnant HelpDeskCall.Les id qui sont même un. Je suis en train d'essayer deux syntaxes différentes pour ListBoxFor: On utilise un IEnumerable de valeurs pour les sélections, à l'aide d'un IEnumerable de SelectListItems. Par défaut, lorsque j'exécute ce code, aucune sélection n'est faite, soit ListBoxFor, mais non fortement typé ListBox sélectionne correctement.

J'ai lu ce post sur ASP.Net et ce fil , mais pas de joie. En fait, si j'ajoute le remplacement ToString() de mon HelpDeskCall classe (comme suggéré dans le ASP.net thread) toutes les valeurs sont sélectionnées, ce qui n'est pas bon.

Si quelqu'un pouvait jeter une certaine lumière sur la façon dont cela devrait fonctionner (et ce que je suis absent ou faire du tort), néophyte en serais très reconnaissant.

Jean

92voto

Darin Dimitrov Points 528142

Voici un exemple illustrant la version fortement typée:

Modèle:

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

Manette:

 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) %>
 

9voto

kkara Points 301

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 de manière opérationnelle. Le seul problème est que le modèle doit contenir une propriété avec les ID, comme ceci:

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

Ensuite, les éléments suivants dans la vue fonctionneraient correctement, présélectionnant les valeurs correctes et liant correctement lors de la publication:

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

3voto

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

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

Ne fonctionne pas, jamais aucune option n'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);
}
 

Les rôles sélectionnés doivent être stockés dans ViewData, pour éviter un bogue méchant.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X