Why does DropDownListFor lose multiple choice after Submit, but ListBoxFor doesn't?

I have read many articles about using MultiSelectList and have not yet understood what is happening with my DropDownListFor. I have a ListBoxFor with the same View, ViewModel and data that work fine. I want to use DropDownListFor because of its optionLabel parameter, which is not in ListBoxFor.

When the view is loaded first, both DropDownListFor and ListBoxFor show several selected items.

Initial View

When you click the Submit button, the selected collection of items is returned to the Controller action, and the view is updated using ListBoxFor while showing both selected items, but DropDownListFor shows only one selected item.

Refreshhed view The controller action creates a MultiSelectList as follows:

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

The view code is as follows:

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

Why does DropDownListFor lose multiple choice after submission, but ListBoxFor doesn't?

+6
source share
1 answer

As follows from the names of the methods, DropDownListFor() intended to create <select> (to select 1), and ListBoxFor() intended to create <select multiple> (to select multiple options). Although both methods have a lot in common, they give different results.

Adding the multiple="multiple" attribute changes the display, but it does not change the functionality of the code executed by these methods.

If you check the source code , you will notice that all DropDownListFor() overloads eventually call the private static MvcHtmlString DropDownListHelper() method and, like ListBoxFor() , they eventually call the private static MvcHtmlString ListBoxHelper() method.

Both of these methods call the private static MvcHtmlString SelectInternal() method private static MvcHtmlString SelectInternal() , but the difference is that DropDownListHelper() passes allowMultiple = false and ListBoxHelper() passes allowMultiple = true .

Within the SelectInternal() method, a key line of code

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

Then, the defaultValue value defaultValue used to build the html for the <option> elements and is used to set the selected attributes.

In the case of ListBoxFor() , the defaultValue value will be the array defined by your SelectedAssignees property. In the case of DropDownListFor() it returns null , because the value of your property cannot be passed to string (its array).

Since defaultValue is null , none of the <option> elements has a selected attribute, and you lose the binding to the model.

As a side note, if you had to set the SelectedAssignees values ​​in the GET method before passing the model to the view, you'll see that none of them were selected when using DropDownListFor() for the same reasons described above.

Please also note that the code for generating SelectList should only be

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

It makes no sense to set the third parameter when using the DropDownListFor() or ListBoxFor() methods, because its property value is associated with ( SelectedAssignees ), which determines which parameters are selected (the third parameter is ignored by the methods). If you want the parameters corresponding to these Guid values ​​to be selected, then use the GET method

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

Source: https://habr.com/ru/post/1012538/


All Articles