asp.net-mvc SelectListItem 中的选定属性从不工作 (DropDownListFor)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9792581/
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
Selected property in SelectListItem never works (DropDownListFor)
提问by Jacob
I have problems when selecting a value of a DropDownList. I've been reading all the similar posts and I can't get a solution.
选择 DropDownList 的值时遇到问题。我一直在阅读所有类似的帖子,但找不到解决方案。
The actual approach seemed very good to me, because I can inspect the fields that will be inside the SelectList:
实际方法对我来说似乎非常好,因为我可以检查 SelectList 中的字段:
var selectList = new List<SelectListItem>(
from variable in someKindOfCollection
select new SelectListItem
{
Selected = variable.Property == selection,
Text = variable.Property,
Value = variable.Property
});
Supposedly, this gives me total control. After the selectList has been built I can inspect the variables with the debugger. Everything is OK and one of them has the "Selected" attribute marked.
据说,这给了我完全的控制权。构建 selectList 后,我可以使用调试器检查变量。一切正常,其中一个标记了“已选择”属性。
Then I use DropDownListFor in order to show on the view:
然后我使用 DropDownListFor 来显示在视图上:
@Html.DropDownListFor(
g => g.SomePropertyInModel , selectList, new { @class = "cssClass" })
But It doesn't work, never... "Renders" the dropdown, but nothing is selected.
但它不起作用,永远不会......“渲染”下拉列表,但没有选择任何内容。
Thanks a lot :)
非常感谢 :)
NEW EXAMPLE First of all I want to apologize. I've been hiding information, of course totally unintentionally. All the code happens inside a Razor For Loop:
新示例 首先,我想道歉。我一直在隐藏信息,当然完全是无意的。所有代码都发生在 Razor For 循环中:
@foreach (var loopVariable in Model.Collection)
{
if (Model.SomeCondition != null)
{
selection = someValue;
}
var selectList = new List<SelectListItem>(
from variable in someKindOfCollection
select new SelectListItem
{
Selected = variable.Property == selection,
Text = variable.Property,
Value = variable.Property
});
@Html.DropDownListFor(
g => g.SomePropertyInModel , selectList, new { @class = "cssClass" })
}
So, It's the fact of selectList is a local variable causing the behavior?. Sorry, I didn't thought it was that.
那么,事实上 selectList 是导致行为的局部变量吗?。抱歉,我没想到是这样。
回答by nfplee
I think you are having the same problem i did. I looked through the source code to find my solution and it appears this is a bug to me. The following DropDownListFor should help, the key to it is that you pass the selected value into the html helper. Hope this helps.
我想你遇到了和我一样的问题。我查看了源代码以找到我的解决方案,这对我来说似乎是一个错误。下面的 DropDownListFor 应该会有所帮助,它的关键是您将选定的值传递给 html 助手。希望这可以帮助。
public static class SelectExtensions {
public static IHtmlString DropDownListFor<TModel, TProperty>(this HtmlHelper<TModel> helper, Expression<Func<TModel, TProperty>> expression, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes = null) {
return DropDownListHelper(helper, ExpressionHelper.GetExpressionText(expression), selectList, selectedValue, optionLabel, htmlAttributes);
}
/// <summary>
/// This is almost identical to the one in ASP.NET MVC 3 however it removes the default values stuff so that the Selected property of the SelectListItem class actually works
/// </summary>
private static IHtmlString DropDownListHelper(HtmlHelper helper, string name, IEnumerable<SelectListItem> selectList, string selectedValue, string optionLabel, object htmlAttributes) {
name = helper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(name);
// Convert each ListItem to an option tag
var listItemBuilder = new StringBuilder();
// Make optionLabel the first item that gets rendered
if (optionLabel != null)
listItemBuilder.AppendLine(ListItemToOption(new SelectListItem() { Text = optionLabel, Value = String.Empty, Selected = false }, selectedValue));
// Add the other options
foreach (var item in selectList) {
listItemBuilder.AppendLine(ListItemToOption(item, selectedValue));
}
// Now add the select tag
var tag = new TagBuilder("select") { InnerHtml = listItemBuilder.ToString() };
tag.MergeAttributes(HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes));
tag.MergeAttribute("name", name, true);
tag.GenerateId(name);
// If there are any errors for a named field, we add the css attribute
ModelState modelState;
if (helper.ViewData.ModelState.TryGetValue(name, out modelState)) {
if (modelState.Errors.Count > 0)
tag.AddCssClass(HtmlHelper.ValidationInputCssClassName);
}
// Add the unobtrusive validation attributes
tag.MergeAttributes(helper.GetUnobtrusiveValidationAttributes(name));
return tag.ToHtmlString(TagRenderMode.Normal);
}
private static string ListItemToOption(SelectListItem item, string selectedValue) {
var tag = new TagBuilder("option") { InnerHtml = HttpUtility.HtmlEncode(item.Text) };
if (item.Value != null)
tag.Attributes["value"] = item.Value;
if ((!string.IsNullOrEmpty(selectedValue) && item.Value == selectedValue) || item.Selected)
tag.Attributes["selected"] = "selected";
return tag.ToString(TagRenderMode.Normal);
}
}
回答by Darin Dimitrov
I'd recommend the usage of a view model:
我建议使用视图模型:
public ActionResult Index()
{
var model = new MyViewModel
{
// this will preselect the item with value = "2.400 " in the collection
SelectedValue = "2.400 ",
Values = someKindOfCollection
};
return View(model);
}
and in the view:
并在视图中:
@Html.DropDownListFor(
g => g.SelectedValue,
new SelectList(Model.Values, "SomePropertyForValue", "SomePropertyForText"),
new { @class = "cssClass" }
)
回答by Brandon
You should debug your select list again.
您应该再次调试您的选择列表。
None of your option values have a selected=selectedon them.
您的任何选项值都没有selected=selected。
Try hard coding your list to something like
尝试将您的列表硬编码为类似
SelectList = new List<SelectListItem>
{
new SelectListItem{Text = "600 ", Value="600 " , Selected = false},
new SelectListItem{Text = "1.200 ", Value="1.200 " , Selected = false},
new SelectListItem{Text = "2.400 ", Value="2.400 " , Selected = false},
new SelectListItem{Text = "3.000 ", Value="3.000 " , Selected = true},
};
Using this code, and your Html.DropDownForthe SelectList works fine and generates this HTML
使用此代码,您Html.DropDownFor的 SelectList 工作正常并生成此 HTML
<select id="TheID" name="TheName" class="cssClass">
<option value="600 ">600 </option>
<option value="1.200 ">1.200 </option>
<option value="2.400 ">2.400 </option>
<option value="3.000 " selected="selected">3.000 </option>
</select>
From your code, I can't tell if your comparison is setting one of the Selected attributes to true or not, but that is probably why your code is not working.
从您的代码中,我无法判断您的比较是否将 Selected 属性之一设置为 true ,但这可能是您的代码不起作用的原因。
回答by jaltiere
I don't know if this will help anyone, but this solved it for me....
我不知道这是否会帮助任何人,但这为我解决了它......
I had both the collection and the selected value in my model.
我的模型中既有集合又有选定的值。
I changed my view from:
我改变了我的看法:
@Html.DropDownListFor(
g => g.CollectionName,
new SelectList(Model.CollectionName, "SomePropertyForValue", "SomePropertyForText", Model.SelectedValue),
new { @class = "cssClass" }
)
to
到
@Html.DropDownListFor(
g => g.SelectedValue,
new SelectList(Model.CollectionName, "SomePropertyForValue", "SomePropertyForText", Model.SelectedValue),
new { @class = "cssClass" }
)
When my first parameter to the DropDownListFor referenced the collection, I would get the drop down list but the selected value would never stick.
当我给 DropDownListFor 的第一个参数引用集合时,我会得到下拉列表,但选定的值永远不会粘住。
回答by EdsonF
The solution for this problem is simpler that we all think...
这个问题的解决方案比我们都认为的更简单......
All we need to do, when return the view from the controller, is set the property on the view model for the element that the dropdown is bound to - i.e: model.SomePropertyInModel = '5' for example
当从控制器返回视图时,我们需要做的就是在视图模型上为下拉绑定到的元素设置属性 - 例如:model.SomePropertyInModel = '5'
this way when we do this
这样当我们这样做时
@Html.DropDownListFor(
g => g.SomePropertyInModel , selectList, new { @class = "cssClass" })
the HtmlHelper will automatically pick up the default value to display on the DropDownList
HtmlHelper 会自动选取默认值显示在 DropDownList 上
simples!
简单!
Hope it may help you and all the others - like me! - that have lost a lot of time searching for a solution for this apparent issue.
希望它可以帮助你和所有其他人 - 像我一样!- 已经浪费了很多时间来寻找这个明显问题的解决方案。
回答by bytetheorist
I had a similar problem and the cause was that I was not setting the value for the property on my view model that was sourced by the SelectListItems. You actually don't need to set the "Selected" property at all. To use you the wording from the original example, just set "SomePropertyOnModel" to whatever the current selection is. DropDownListFor will bind the "Selected" property appropriately.
我遇到了类似的问题,原因是我没有在由 SelectListItems 获取的视图模型上设置属性的值。您实际上根本不需要设置“Selected”属性。要使用原始示例中的措辞,只需将“SomePropertyOnModel”设置为当前选择的任何内容。DropDownListFor 将适当地绑定“Selected”属性。
回答by diegosasw
My recommendation for DropDownListFor is,
我对 DropDownListFor 的建议是,
have an IEnumerable property the model (or viewmodel) that is being passed to the View. In your case for example:
private IEnumerable<SelectListItem> GetListItems() { var selectList = db.YourDBThings .Where(t => t.IsCool == true) .Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }); return new SelectList(issues, "Value", "Text"); }And then add this IEnumerable to your object, assuming you also have a property in your object that has ONE item (the one that will be set as selected) that matches one of the "value" in the list:
FancyViewModel myFancyViewModel = new FancyViewModel(); myFancyViewModel.ListOptions = GetListItems(); myFancyViewModel.SelectedThingId = 3; //this 3 would match one of the value in the list //.... return View(myFancyViewModel);Then in the view where you receive the FancyViewModel instance that contains the list of items:
@model Project.ViewModels.FancyViewModel @*...*@ @Html.DropDownListFor(x=>x.SelectedThingId, Model.ListOptions)
传递给视图的模型(或视图模型)有一个 IEnumerable 属性。例如,在您的情况下:
private IEnumerable<SelectListItem> GetListItems() { var selectList = db.YourDBThings .Where(t => t.IsCool == true) .Select(x => new SelectListItem { Value = x.Id.ToString(), Text = x.Name }); return new SelectList(issues, "Value", "Text"); }然后将此 IEnumerable 添加到您的对象中,假设您的对象中还有一个属性,该属性具有一个与列表中的“值”之一匹配的项目(将设置为选定的项目):
FancyViewModel myFancyViewModel = new FancyViewModel(); myFancyViewModel.ListOptions = GetListItems(); myFancyViewModel.SelectedThingId = 3; //this 3 would match one of the value in the list //.... return View(myFancyViewModel);然后在您收到包含项目列表的 FancyViewModel 实例的视图中:
@model Project.ViewModels.FancyViewModel @*...*@ @Html.DropDownListFor(x=>x.SelectedThingId, Model.ListOptions)
The first argument in DropDownListFor specifies the TProperty that contains the field that will be selected within the list. The second is the list itself that comes from the model (although it could be retrieved from anywhere!)
DropDownListFor 中的第一个参数指定包含将在列表中选择的字段的 TProperty。第二个是来自模型的列表本身(尽管它可以从任何地方检索!)
回答by user2787190
There is a problem, g.SelectedValuemust be the nullable type in your model.
有问题,g.SelectedValue必须是你模型中的可为空类型。

