asp.net-mvc EditorTemplate 中的 DropDownListFor 未选择值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1916462/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
DropDownListFor in EditorTemplate not selecting value
提问by kmehta
I have an editor template for a custom object. Inside that editor template I use a couple of DropDownListFor helpers. In each of them I specify a unique model property (with the pre-selected value) and the select list containing all the select options.
我有一个自定义对象的编辑器模板。在该编辑器模板中,我使用了几个 DropDownListFor 助手。在它们中的每一个中,我指定了一个唯一的模型属性(带有预选值)和包含所有选择选项的选择列表。
Example:
例子:
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
I know that the option values are being populated (from viewing source) and that my Model is passed in with the correct ID value (DocumentCategoryType).
我知道正在填充选项值(来自查看源)并且我的模型使用正确的 ID 值 (DocumentCategoryType) 传入。
When the view is rendered, there is no selected item in my dropdown and therefore it defaults to the first (non-selected) value.
呈现视图时,我的下拉列表中没有选定的项目,因此它默认为第一个(未选定的)值。
Does anyone have any ideas?
有没有人有任何想法?
Thanks.
谢谢。
采纳答案by kmehta
Yuck. I ended up solving it like this. I hope this gets fixed for RTM.
哎呀。我最终是这样解决的。我希望这可以为 RTM 解决。
<%if(Model!=null){ %>
<%= Html.DropDownListFor(m => m.DocumentCategoryType, new SelectList(Model.DocumentCategoryTypeList,"Value","Text", Model.DocumentCategoryType))%>
<%}else{%>
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
<%}%>
回答by Curtis Buys
We also solved the solution by populating a new SelectListthat has the appropriate SelectListItemselected, but created this extension method to keep the call to DropDownListFora little cleaner:
我们还通过填充SelectList具有相应SelectListItem所选的新功能,但创建了此扩展方法以将呼叫保持DropDownListFor一点清洁:
public static SelectList MakeSelection(this SelectList list, object selection)
{
return new SelectList(list.Items, list.DataValueField, list.DataTextField, selection);
}
Then your DropDownListForcall becomes:
然后你的DropDownListFor电话变成:
<%= Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList.MakeSelection(Model.DocumentCategoryType)) %>
回答by Russ Cam
Looking through the ASP.NET MVC 2 source code reveals some solutions to this problem. Essentially, any SelectListItemin the SelectListpassed in the helper extension method that has the Selectedproperty set to true does not have any bearing over the <option>element rendered with the selectedattribute applied for the item.
查看 ASP.NET MVC 2 源代码揭示了此问题的一些解决方案。从本质上讲,任何SelectListItem在SelectList在具有辅助扩展方法传递Selected属性设置为true没有在任何方位<option>与所呈现的元素selected属性适用于该项目。
The selectedattribute on <option>elements is determined by
元素的selected属性<option>由
1) checking that the helper extension method was passed a SelectList. If this is null, the framework will look in the ViewData for a value corresponding to the key that is the view model property for which you wish to render the drop down list for. If the value is a SelectList, this will be used to render the <select>including taking any selected values, so long as the model state for the model property is null.
1) 检查辅助扩展方法是否通过了SelectList. 如果这是 null,框架将在 ViewData 中查找与键对应的值,该键是您希望为其呈现下拉列表的视图模型属性。如果值为 a SelectList,则这将用于呈现<select>包含任何选定值的内容,只要模型属性的模型状态为 null。
2) If a SelectListhas been passed in the helper extension method and the model state for the model property is null, the framework will look in the ViewData for a default value, using the model property name as the key. The value in view data is converted to a string and any items in the SelectListpassed to the helper extension method that have a value (if no value is set, then the Text will be checked) that matches the default value will have the Selectedproperty set to true which in turn will render an <option>with the attribute selected="selected".
2) 如果SelectList在辅助扩展方法中传入了a并且模型属性的模型状态为空,则框架将在 ViewData 中查找默认值,使用模型属性名称作为键。视图数据中的值被转换为字符串,并且SelectList传递给辅助扩展方法的任何具有与默认值匹配的值(如果未设置值,则将检查文本)的项目都将Selected属性设置为true 反过来将呈现<option>具有属性的selected="selected"。
Putting this together, there are two plausible options that I can see to have an option selected and use the strongly typed DropDownListFor:
将这些放在一起,我可以看到有两个合理的选项可以选择一个选项并使用强类型DropDownListFor:
Using the following view model
使用以下视图模型
public class CategoriesViewModel
{
public string SelectedCategory { get; private set ; }
public ICollection<string> Categories { get; private set; }
public CategoriesViewModel(string selectedCategory, ICollection<string> categories)
{
SelectedCategory = selectedCategory;
Categories = categories;
}
}
Option 1
选项1
Set a value in the ViewData in the controller rendering your view keyed against the property name of the collection used to render the dropdown
在控制器中的 ViewData 中设置一个值,根据用于呈现下拉列表的集合的属性名称呈现您的视图
the controller action
控制器动作
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
this.ViewData["Categories"] = selectedCategory;
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
and in the strongly typed view
并且在强类型视图中
<%: Html.DropDownListFor(m => m.Categories, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>
Option 2
选项 2
Render the dropdown using the name of the property of the selected item(s)
使用所选项目的属性名称呈现下拉列表
the controller action
控制器动作
public class CategoriesController
{
[HttpGet]
public ViewResult Select()
{
/* some code that gets data from a datasource to populate the view model */
ICollection<string> categories = repository.getCategoriesForUser();
string selectedCategory = repository.getUsersSelectedCategory();
CategoriesViewModel model = new CategoriesViewModel(selectedCategory, categories);
return View(model);
}
[HttpPost]
public ActionResult Select(CategoriesViewModel model)
{
/* some code that does something */
}
}
and in the strongly typed view
并且在强类型视图中
<%: Html.DropDownListFor(m => m.SelectedCategory, Model.Categories.Select(c => new SelectListItem { Text = c, Value = c }), new { @class = "my-css-class" }) %>
回答by Alexander Taran
It is confirmed as a bug @ aspnet.codeplex.com and only behaves like this for strongly typed views.
它被确认为一个错误 @ aspnet.codeplex.com 并且只对强类型视图表现得像这样。
Workaround: populate your SelectList in the view code
解决方法:在视图代码中填充您的 SelectList
like
喜欢
<%= Html.DropDown("DocumentCategoryType", new SelectList(Model.Categories,"id","Name",Model.SelectedCategory")) =>
回答by Brett Allred
Make sure you have a value assigned to m.DocumentCategoryType when you send it to the view.
确保在将 m.DocumentCategoryType 发送到视图时为其分配了一个值。
Generally this value will get reset when you do a post back so you just need to specify the value when returning to your view.
通常,该值会在您回发时重置,因此您只需在返回视图时指定该值。
When creating a drop down list you need to pass it two values. 1. This is where you will store the selected value 2. Is the actual List
创建下拉列表时,您需要传递两个值。1. 这是您将存储所选值的位置 2. 是实际列表
Example
例子
<%=Html.DropDownListFor(m => m.DocumentCategoryType, Model.DocumentCategoryTypeList) %>
I made the mistake of setting the select list item Selected value to True. This won't do anything. Instead just assign a value to m.DocumentCategoryType in your controller and this will actually do the selection for you.
我犯了将选择列表项 Selected 值设置为 True 的错误。这不会做任何事情。相反,只需为控制器中的 m.DocumentCategoryType 分配一个值,这实际上会为您进行选择。
回答by MrDustpan
Here's another good solution if the source for your drop down list is an IEnumerable instead of a SelectList:
如果下拉列表的源是 IEnumerable 而不是 SelectList,这是另一个很好的解决方案:
public static SelectList MakeSelection(this IEnumerable<SelectListItem> list, object selection, string dataValueField = "Value", string dataTextField = "Text")
{
return new SelectList(list, dataValueField, dataTextField, selection);
}
回答by Jeremy Meyer
I also had this problem with a field ProgramName. Turns out we used ViewBag.ProgramName in the BaseController and Layout.cshtml, and this was for a different purpose. Since the value in ViewBag.ProgramName was not found in the dropdownlist, no value was selected even though the SelectListItem.Selected was true for one item in the list. We just changed the ViewBag to use a different key and the problem was resolved.
我的程序名字段也有这个问题。原来我们在 BaseController 和 Layout.cshtml 中使用了 ViewBag.ProgramName,这是出于不同的目的。由于在下拉列表中未找到 ViewBag.ProgramName 中的值,因此即使 SelectListItem.Selected 对于列表中的一项为真,也未选择任何值。我们只是将 ViewBag 更改为使用不同的键,问题就解决了。
回答by DaveMorganTexas
Here is a drop-in DropDownListFor replacementthat varies only slightly from the original MVC source.
这是一个 DropDownListFor 替代品,与原始 MVC 源代码仅略有不同。
Example:
例子:
<%=Html.FixedDropDownListFor(m => m.DocumentCategoryType,
Model.DocumentCategoryTypeList) %>
回答by willman
I was worried about the performance of making so many copies of my selectList, so instead, I added the selectedvalue as a custom attribute, then used jquery to actually perform the item select:
我担心制作如此多的 selectList 副本的性能,因此,我将 selectedvalue 添加为自定义属性,然后使用 jquery 实际执行项目选择:
@Html.DropDownListFor(item => item.AttendeeID, attendeeChoices, String.Empty, new { setselectedvalue = Model.AttendeeID })
........
jQuery("select[setselectedvalue]").each(function () { e = jQuery(this); e.val(e.attr("setselectedvalue")); });
回答by nfplee
I managed to solve the same problem by saying the folling:
我通过说以下内容设法解决了同样的问题:
new SelectList(sections.Select(s => new { Text = s.SectionName, Value = s.SectionID.ToString() }), "Value", "Text")
This trick is converting to the value to a string. I know this has been mentioned in previous answers but i find my solution a little cleaner :). Hope this helps.
这个技巧是将值转换为字符串。我知道这在之前的答案中已经提到过,但我发现我的解决方案更简洁:)。希望这可以帮助。

