[英]How can I get this ASP.NET MVC SelectList to work?
我在控制器中创建了一个 selectList,以显示在视图中。
我正在尝试动态创建它,有点像这样......
myViewData.PageOptionsDropDown =
new SelectList(new [] {"10", "15", "25", "50", "100", "1000"}, "15");
它编译,但输出很糟糕......
<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option>10</option>
<option>15</option>
<option>25</option>
<option>50</option>
<option>100</option>
<option>1000</option>
</select>
注意没有项目被选中?
我怎样才能解决这个问题??
这就是我的做法
IList<Customer> customers = repository.GetAll<Customer>();
IEnumerable<SelectListItem> selectList =
from c in customers
select new SelectListItem
{
Selected = (c.CustomerID == invoice.CustomerID),
Text = c.Name,
Value = c.CustomerID.ToString()
};
乍一看,我不确定我知道你在追求什么......
我使用扩展方法:
用法
var departmentItems = departments.ToSelectList(d => d.Code +
" - " + d.Description,
d => d.Id.ToString(),
" - ");
var functionItems = customerFunctions.ToSelectList(f => f.Description,
f => f.Id.ToString(),
" - ");
和
public static class MCVExtentions
{
public static List<SelectListItem> ToSelectList<T>(
this IEnumerable<T> enumerable,
Func<T, string> text,
Func<T, string> value,
string defaultOption)
{
var items = enumerable.Select(f => new SelectListItem()
{
Text = text(f),
Value = value(f)
}).ToList();
items.Insert(0, new SelectListItem()
{
Text = defaultOption,
Value = "-1"
});
return items;
}
}
使用接受items, dataValueField, dataTextField, selectedValue
作为参数的构造函数:
ViewData["myList"] =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }
.Select(x => new {value = x, text = x}),
"value", "text", "15");
那么在你看来:
<%=Html.DropDownList("myList") %>
基于 Thomas Stock 的回答,我创建了这些重载的ToSelectList
方法:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
public static partial class Helpers
{
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, bool selectAll = false)
{
return enumerable.ToSelectList(value, value, selectAll);
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, object selectedValue)
{
return enumerable.ToSelectList(value, value, new List<object>() { selectedValue });
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, IEnumerable<object> selectedValues)
{
return enumerable.ToSelectList(value, value, selectedValues);
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, bool selectAll = false)
{
foreach (var f in enumerable.Where(x => x != null))
{
yield return new SelectListItem()
{
Value = value(f).ToString(),
Text = text(f).ToString(),
Selected = selectAll
};
}
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, object selectedValue)
{
return enumerable.ToSelectList(value, text, new List<object>() { selectedValue });
}
public static IEnumerable<SelectListItem> ToSelectList<T>(this IEnumerable<T> enumerable, Func<T, object> value, Func<T, object> text, IEnumerable<object> selectedValues)
{
var sel = selectedValues != null
? selectedValues.Where(x => x != null).ToList().ConvertAll<string>(x => x.ToString())
: new List<string>();
foreach (var f in enumerable.Where(x => x != null))
{
yield return new SelectListItem()
{
Value = value(f).ToString(),
Text = text(f).ToString(),
Selected = sel.Contains(value(f).ToString())
};
}
}
}
在您的控制器中,您可以执行以下操作:
var pageOptions = new[] { "10", "15", "25", "50", "100", "1000" };
ViewBag.PageOptions = pageOptions.ToSelectList(o => o, "15" /*selectedValue*/);
最后在您的视图中,输入:
@Html.DropDownList("PageOptionsDropDown", ViewBag.PageOptions as IEnumerable<SelectListItem>, "(Select one)")
它将产生所需的输出——当然,如果您不想要第一个空项目,您可以省略上面的"(Select one)"
选项标签:
<select id="PageOptionsDropDown" name="PageOptionsDropDown">
<option value="">(Select one)</option>
<option value="10">10</option>
<option selected="selected" value="15">15</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
<option value="1000">1000</option>
</select>
更新:可以在此处找到带有 XML 注释的修订代码清单。
问题是, SelectList 按设计工作。 错误在于设计。 您可以在 SelectedItem 中设置 Selected 属性,但是如果您使用 GetEnumerator() 遍历列表(或者如果 Mvc 为您执行此操作),这将完全被忽略。 Mvc 将创建新的 SelectListItems。
您必须将 SelectList ctor 与 SelectListItem[]、Text-Name、Value-Name 和 SelectedValue 一起使用。 请注意将要被选择的 SelectListItem 的 VALUE 作为 SelectedValue 传递,而不是 SelectListItem 本身! 例子:
SelectList sl = new SelectList( new[]{
new SelectListItem{ Text="one", Value="1"},
new SelectListItem{ Text="two", Value="2"},
new SelectListItem{ Text="three", Value="3"}
}, "Text", "Value", "2" );
(没有测试过,但我遇到了同样的问题)
那么第二个选项将获得 selected="selected" 属性。 看起来不错的旧数据集;-)
这是一个选项:
myViewData.PageOptionsDropDown = new[]
{
new SelectListItem { Text = "10", Value = "10" },
new SelectListItem { Text = "15", Value = "15", Selected = true }
new SelectListItem { Text = "25", Value = "25" },
new SelectListItem { Text = "50", Value = "50" },
new SelectListItem { Text = "100", Value = "100" },
new SelectListItem { Text = "1000", Value = "1000" },
}
如果这就是您想要做的所有事情,那么只需将数组声明为字符串即可修复所选项目问题:
myViewData.PageOptionsDropDown =
new SelectList(new string[] {"10", "15", "25", "50", "100", "1000"}, "15");
让 SelectList 和 SelectedValue 一起工作非常简单,即使您的属性不是像 Int、String 或 Double 值这样的简单对象。
例子:
假设我们的 Region 对象是这样的:
public class Region {
public Guid ID { get; set; }
public Guid Name { get; set; }
}
你的视图模型是这样的:
public class ContactViewModel {
public DateTime Date { get; set; }
public Region Region { get; set; }
public List<Region> Regions { get; set; }
}
您可以使用以下代码:
@Html.DropDownListFor(x => x.Region, new SelectList(Model.Regions, "ID", "Name"))
仅当您将 Region 对象的 ToString 方法覆盖为以下内容时:
public class Region {
public Guid ID { get; set; }
public Guid Name { get; set; }
public override string ToString()
{
return ID.ToString();
}
}
这有 100% 保证工作。
但我真的相信在所有情况下让 SelectList 100% 工作的最佳方法是使用 Equals 方法针对项目集合中的每个项目测试 DropDownList 或 ListBox 属性值。
似乎如果您有一个强类型视图,您需要更改下拉列表的 ID,以便它不是继承类上的属性名称。 然后,您需要在您的编辑 (POST) 方法中放入一些逻辑,以从 FORMCollection 中提取选定的值,并将其放在您的实例中,然后再提交您的更改。
这当然有点奇怪,但我试过了,它有效。
因此,如果您的班级有一个名为 CountryId 的字段,并且您正在显示一个国家/地区名称列表,请使下拉列表的 ID 为 CountryName 而不是 CountryId,然后在帖子中,您可以使用 Collection["CountryName"] 做一些事情.
我有同样的问题。 解决方法很简单。 只需将传递给 DropDownList 助手的“名称”参数更改为与您的 ViewModel 中现有的任何属性都不匹配的内容。 在此处阅读更多信息: http : //www.dotnetguy.co.uk/post/2009/06/25/net-mvc-selectlists-selected-value-does-not-get-set-in-the-view
我引用丹·沃森的话:
在 MVC 中,如果视图是强类型的,selectlist 的 selected 选项将被覆盖,并且在构造函数上设置的 selected option 属性将永远不会到达视图,而是选择下拉列表中的第一个选项(为什么仍然有点神秘) .
干杯!
所有这些答案看起来都不错,但似乎控制器正在以众所周知的结构化格式为视图准备数据,而不是让视图简单地迭代通过模型传递的 IEnumerable<> 并构建标准选择列表,然后让 DefaultModelBinder通过操作参数将所选项目返回给您。 是的,不,为什么不呢? 关注点分离,是吗? 让控制器构建特定于 UI 和视图的东西似乎很奇怪。
简单的:
string[] someName = new string[] {"10", "15", "25", "50", "100", "1000"};
myViewData.PageOptionsDropDown = new SelectList(someName, "15");
我就是这样运行的,没有任何问题,
public class myViewDataObj
{
public SelectList PageOptionsDropDown { get; set; }
}
public ActionResult About()
{
myViewDataObj myViewData = new myViewDataObj();
myViewData.PageOptionsDropDown =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
ViewData["myList"] = myViewData.PageOptionsDropDown;
return View();
}
和
<%=Html.DropDownList("myList") %>
如果你这样做,它也有效,
public ActionResult About()
{
myViewDataObj myViewData = new myViewDataObj();
myViewData.PageOptionsDropDown =
new SelectList(new[] { "10", "15", "25", "50", "100", "1000" });
ViewData["myListValues"] = myViewData.PageOptionsDropDown;
ViewData["myList"] = "15";
return View();
}
和
<%=Html.DropDownList("myList",(IEnumerable<SelectListItem>)ViewData["myListValues"]) %>
使用你的例子这对我有用:
控制器:
ViewData["PageOptionsDropDown"] = new SelectList(new[] { "10", "15", "25", "50", "100", "1000" }, "15");
看法:
<%= Html.DropDownList("PageOptionsDropDown")%>
MonthRepository monthRepository = new MonthRepository();
IQueryable<MonthEntity> entities = monthRepository.GetAllMonth();
List<MonthEntity> monthEntities = new List<MonthEntity>();
foreach(var r in entities)
{
monthEntities.Add(r);
}
ViewData["Month"] = new SelectList(monthEntities, "MonthID", "Month", "Mars");
如果您想将一些随机文本传递给 DropDownList,例如--Select--您可以使用以下代码轻松完成此操作:
@Html.DropDownListFor(x => x.CategoryId, new SelectList(Model.Categories, "Id", "Name"), "--Select--", new { @class = "form-control" })
我这样做:
List<SelectListItem> list = new List<SelectListItem>{
new SelectListItem {Selected = true, Text = "Select", Value = "0"},
new SelectListItem {Selected = true, Text = "1", Value = "1"},
new SelectListItem {Selected = true, Text = "2", Value = "2"}
};
return list.ToArray();
ToArray() 负责处理这些问题。
模型中选择的值代替了默认项。 (我同意我没有阅读所有帖子)
我不记得 mvc 1 是如何设置的,但它似乎希望选择列表与其所属的字段名称相同......
我发现,正如上面所说的那样,当它们发送的 ViewData 与字段名称相同时,我的选择列表在 mvc2 中不起作用。
例如:
<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForName"]) %>
什么时候工作
<%= Html.DropDownListFor((model => model.ForID), (SelectList)ViewData["ForID"]) %>
不起作用,因为 ViewData 名称“ForID”与它正在工作的字段的名称相同
一种可能的解释是您绑定到的选择列表值不是字符串。
那么在那个例子中,参数 'PageOptionsDropDown' 在你的模型中是一个字符串吗? 因为如果不是,则不会显示列表中的选定值。
如果您在 Html.DropDownList 扩展方法中查看 MVC 2 的源代码,它从不检查 SelectList 类 SelectedValue 属性。 它只会尝试与您的模型匹配。
以上所有都是主题的变体,即如何将一堆数据发送到视图以获取下拉列表&它们都一样好(或多或少)。
问题出在视图上。 创建您自己的 DropDownList 扩展方法,该方法确实尊重您设置的选择值,或者手动迭代。 哪个最适合你。
如果您的模型中有一个集合并且您的 View 是强类型的,则此方法的一些变体将起作用:
@Html.DropDownListFor(x => x.RegionID,
new SelectList(Model.Regions,"RegionID", "RegionName", Model.RegionID))
-要么-
@Html.DropDownList("RegionID",
new SelectList(Model.Regions, "RegionID", "RegionName", Model.RegionID))
可能是您的 ViewData 中存在一些歧义:
看看这里
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.