2016-11-21 4 views
6

Ich habe viele Artikel über die Verwendung von MultiSelectList gelesen und muss noch verstehen, was mit meinem DropDownListFor los ist. Ich habe eine ListBoxFor mit der gleichen View, ViewModel und Daten, die gut funktioniert. Ich möchte den DropDownListFor wegen seines optionLabel-Parameters verwenden, den ListBoxFor nicht hat.Warum verliert DropDownListFor die Mehrfachauswahl nach dem Senden, aber die ListBoxFor nicht?

Wenn die Ansicht zum ersten Mal geladen wird, zeigen sowohl DropDownListFor als auch ListBoxFor die mehreren ausgewählten Elemente an.

Initial View

Wenn die Senden-Schaltfläche geklickt wird, wird die ausgewählten Elemente Sammlung zurück an die Controller Aktion geschrieben in Ordnung und die Aussicht ist aufgefrischt mit der ListBoxFor noch beiden ausgewählten Elemente zeigt aber die DropDownListFor ist nur ein ausgewähltes Element darstellt .

Refreshed View Die Controller-Aktion wird die MultiSelectList wie diese Konstruktion:

vm.TasksFilterGroup.Assignees = new MultiSelectList(employees, "Id", "FullName", new string[] { "51b6f06a-e04d-4f98-88ef-cd0cfa8a2757", "51b6f06a-e04d-4f98-88ef-cd0cfa8a2769" }); 

The View Code wie folgt aussieht:

<div class="form-group"> 
 
    <label>ListBoxFor</label> 
 
    @Html.ListBoxFor(m => m.TasksFilterGroup.SelectedAssignees, Model.TasksFilterGroup.Assignees, new { @class = "form-control", multiple = "multiple" }) 
 
</div> 
 
<div class="form-group"> 
 
    <label>DropDownListFor</label> 
 
    @Html.DropDownListFor(m => m.TasksFilterGroup.SelectedAssignees, Model.TasksFilterGroup.Assignees, new { @class = "form-control", multiple = "multiple" }) 
 
</div>

Warum verlieren die DropDownListFor die Mehrfachauswahl nach Senden aber die ListBoxFor nicht?

Antwort

15

Wie die Namen der Verfahren implizieren, DropDownListFor() ist für die Schaffung eines <select> (1 Option) und ListBoxFor() zum Erzeugen einer <select multiple> (mehrere Optionen auszuwählen). Während beide Methoden viel gemeinsamen Code teilen, führen sie zu unterschiedlichen Ergebnissen.

Das Hinzufügen des Attributs multiple="multiple" ändert die Anzeige, ändert jedoch nicht die Funktionalität des von diesen Methoden ausgeführten Codes.

Wenn Sie die source code überprüfen, werden Sie feststellen, dass alle Überlastungen von DropDownListFor() schließlich die private static MvcHtmlString DropDownListHelper() Methode aufrufen, und in ähnlicher Weise ListBoxFor() schließlich ruft die private static MvcHtmlString ListBoxHelper() Methode.

Beide Methoden aufrufen, die private static MvcHtmlString SelectInternal() Methode, aber der Unterschied ist, dass DropDownListHelper() gibt allowMultiple = false während die ListBoxHelper()allowMultiple = true gibt.

Im SelectInternal() Verfahren wird die Schlüsselcodezeile ist

object defaultValue = (allowMultiple) ? htmlHelper.GetModelStateValue(fullName, typeof(string[])) : htmlHelper.GetModelStateValue(fullName, typeof(string)); 

Der Wert von defaultValue dann verwendet wird, wenn HTML für die <option> Elemente Aufbau und verwendet wird, um das selected Attribut gesetzt (s).

Im Fall ListBoxFor() ist der Wert defaultValue das Array, das von Ihrer SelectedAssignees-Eigenschaft definiert wird. Im Fall von DropDownListFor() wird null zurückgegeben, da der Wert Ihrer Eigenschaft nicht in string (ein Array) umgewandelt werden kann.

Da defaultValuenull ist, keine der <option> Elemente haben die selected Attribut gesetzt, und Sie verlieren Modell verbindlich. Wenn Sie die Werte SelectedAssignees in der GET-Methode festlegen, bevor Sie das Modell an die Ansicht übergeben, sehen Sie, dass keine davon ausgewählt ist, wenn Sie DropDownListFor() aus den gleichen Gründen wie oben beschrieben verwenden.

Beachten Sie auch, dass der Code zur Erzeugung der SelectList nur

sein sollte
vm.TasksFilterGroup.Assignees = new SelectList(employees, "Id", "FullName" }); 

Es hat keinen Sinn, die 3. Parametereinstellung bei Verwendung von entweder die DropDownListFor() oder ListBoxFor() Methoden, weil ihr der Wert der Immobilie auf Ihre Bindung (SelectedAssignees), die bestimmt, welche Optionen ausgewählt sind (der dritte Parameter wird von den Methoden ignoriert). Wenn Sie die Optionen für: diese Guid Werte wollen gewählt werden, dann in der GET-Methode verwendet

vm.TasksFilterGroup.SelectedAssignees= new string[]{ "51b6f06a-e04d-4f98-88ef-cd0cfa8a2757", "51b6f06a-e04d-4f98-88ef-cd0cfa8a2769" }; 
+1

Diese gründliche und sachkundig Antwort wird sehr geschätzt. Vielen Dank. – RJBreneman

+0

Dies ist eine großartige und eingehende Antwort. Sehr aufschlussreich. – CodingYoshi

Verwandte Themen