为什么DropDownListFor会在Submit之后丢失多个选择,而ListBoxFor却没有呢? [英] Why does the DropDownListFor lose the multiple selection after Submit but the ListBoxFor doesn't?

查看:119
本文介绍了为什么DropDownListFor会在Submit之后丢失多个选择,而ListBoxFor却没有呢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了许多有关使用MultiSelectList的文章,但还没有了解我的DropDownListFor出了什么问题.我有一个具有相同View,ViewModel和正常工作数据的ListBoxFor.我想使用DropDownListFor,因为ListBoxFor没有它的optionLabel参数.

I have read many articles about using MultiSelectList and have yet to understand what is going wrong with my DropDownListFor. I have a ListBoxFor with the same View, ViewModel and data that works fine. I want to use the DropDownListFor because of its optionLabel parameter that ListBoxFor doesn't have.

第一次加载View时,DropDownListFor和ListBoxFor都显示多个选定项.

When the View is first loaded, both the DropDownListFor and the ListBoxFor show the multiple selected items.

单击提交"按钮后,选定的项目集合将回传到Controller动作中,并且刷新视图,同时ListBoxFor仍显示两个选定的项目,但DropDownListFor仅显示一个选定的项目.

When the Submit button is clicked, the selected items collection is posted back to the Controller action okay and the view is refreshed with the ListBoxFor still showing both selected items but the DropDownListFor is only showing one selected item.

控制器动作正在像这样构造MultiSelectList:

The controller action is constructing the MultiSelectList like this:

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

查看代码如下所示:

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

为什么DropDownListFor在提交后会丢失多个选择,而ListBoxFor却没有呢?

Why does the DropDownListFor lose the multiple selection after Submit but the ListBoxFor doesn't?

推荐答案

正如方法名称所暗示的那样,DropDownListFor()用于创建<select>(选择1个选项),而ListBoxFor()用于创建<select multiple>(以选择多个选项).虽然这两种方法共享许多通用代码,但它们的确会产生不同的结果.

As the names of the methods imply, DropDownListFor() is for creating a <select> (to select 1 option) and ListBoxFor() is for creating a <select multiple> (to select multiple options). While both methods share a lot of common code, they do produce different results.

添加multiple="multiple"属性会更改显示,但不会更改这些方法执行的代码的功能.

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

如果您检查源代码,您会注意到,DropDownListFor()的所有重载最终都会调用private static MvcHtmlString DropDownListHelper()方法,类似地,ListBoxFor()最终会调用private static MvcHtmlString ListBoxHelper()方法.

If you inspect the source code, you will note that all the overloads of DropDownListFor() ultimately call the private static MvcHtmlString DropDownListHelper() method, and similarly ListBoxFor() ultimately calls the private static MvcHtmlString ListBoxHelper() method.

这两种方法都调用private static MvcHtmlString SelectInternal()方法,但是区别在于DropDownListHelper()通过allowMultiple = falseListBoxHelper()通过allowMultiple = true.

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

SelectInternal()方法中,代码的关键行是

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

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

然后在为<option>元素构建html时使用defaultValue的值,并用于设置selected属性.

The value of defaultValue is then used when building html for the <option> elements and is used to set the selected attribute(s).

对于ListBoxFor()defaultValue的值将是由SelectedAssignees属性定义的数组.对于DropDownListFor(),它返回null,因为您的属性值不能转换为string(它是一个数组).

In the case of ListBoxFor(), the value of defaultValue 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 cast to string (its an array).

因为defaultValuenull,所以所有<option>元素都没有设置selected属性,因此您失去了模型绑定.

Because defaultValue is null, none of the <option> elements have the selected attribute set and you lose model binding.

作为旁注,如果要在将模型传递到视图之前在GET方法中设置SelectedAssignees的值,则出于相同的原因,使用DropDownListFor()时将不会选择任何一个如上所述.

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

还请注意,用于生成SelectList的代码应为

Note also that the code for generating the SelectList should just be

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

使用DropDownListFor()ListBoxFor()方法时没有必要设置第3个参数,因为绑定到(SelectedAssignees)的属性的值决定了选择哪个选项(第3个参数被忽略)通过方法).如果要选择与那些Guid值匹配的选项,则在GET方法中,使用

There is no point setting the 3rd parameter when using either the DropDownListFor() or ListBoxFor() methods because its the value of the property your binding to (SelectedAssignees) that determines which options are selected (the 3rd parameter is ignored by the methods). If you want the options matching those Guid values to be selected, then in the GET method, use

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

这篇关于为什么DropDownListFor会在Submit之后丢失多个选择,而ListBoxFor却没有呢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆