我知道ListBoxFor
ASP.NET MVC Html 辅助扩展方法中有一个扩展方法,但我一直认为复选框列表比列表框更用户友好。
旧的 WebForms 中有一个非常方便的CheckBoxList
控件,但显然现在已经不存在了。
问题是,为什么在 ASP.NET MVC 中没有办法创建复选框列表?如何编写自己的扩展方法来创建复选框列表并以类似的方式ListBoxFor
运行?
我知道ListBoxFor
ASP.NET MVC Html 辅助扩展方法中有一个扩展方法,但我一直认为复选框列表比列表框更用户友好。
旧的 WebForms 中有一个非常方便的CheckBoxList
控件,但显然现在已经不存在了。
问题是,为什么在 ASP.NET MVC 中没有办法创建复选框列表?如何编写自己的扩展方法来创建复选框列表并以类似的方式ListBoxFor
运行?
这是 CheckBoxListFor 的强类型 HtmlHelper,它将所选项目作为视图数据模型中的数组处理。我选择不包装 Html.CheckBox 或 Html.CheckBoxFor 方法,因为我不想在我的复选框列表中隐藏“假”字段。
请随时对此进行改进并重新发布:-)
//View
<%: Html.CheckBoxListFor(model => model.FreightTypeIds, FreightTypeMultiSelectList) %>
//Controller
public ActionResult SomeAction(int[] FreightTypeIds)
{
//...
return View();
}
//Extension
public static MvcHtmlString CheckBoxListFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper, Expression<Func<TModel, IEnumerable<TProperty>>> expression, MultiSelectList allOptions, object htmlAttributes = null)
{
ModelMetadata modelMetadata = ModelMetadata.FromLambdaExpression<TModel, IEnumerable<TProperty>>(expression, htmlHelper.ViewData);
// Derive property name for checkbox name
string propertyName = htmlHelper.ViewContext.ViewData.TemplateInfo.GetFullHtmlFieldName(modelMetadata.PropertyName);
// Get currently select values from the ViewData model
IEnumerable<TProperty> list = expression.Compile().Invoke(htmlHelper.ViewData.Model);
// Convert selected value list to a List<string> for easy manipulation
IList<string> selectedValues = new List<string>();
if (list != null)
{
selectedValues = new List<TProperty>(list).ConvertAll<string>(delegate(TProperty i) { return i.ToString(); });
}
// Create div
TagBuilder divTag = new TagBuilder("div");
divTag.MergeAttributes(new RouteValueDictionary(htmlAttributes), true);
// Add checkboxes
foreach (SelectListItem item in allOptions)
{
divTag.InnerHtml += string.Format(
"<div><input type=\"checkbox\" name=\"{0}\" id=\"{1}_{2}\" " +
"value=\"{2}\" {3} /><label for=\"{1}_{2}\">{4}</label></div>",
propertyName,
TagBuilder.CreateSanitizedId(propertyName),
item.Value,
selectedValues.Contains(item.Value) ? "checked=\"checked\"" : string.Empty,
item.Text);
}
return MvcHtmlString.Create(divTag.ToString());
}
我仍在尝试,但这似乎与默认活页夹相处融洽,并在发布后保留用户选择。隐藏字段,真的吗?..这会在html5中飞行吗?这感觉很疯狂,但我宁愿这样做,也不愿仅仅因为 ModelState.IsValid 为假而点击我的数据库以获取下拉列表和复选框列表。
public static MvcHtmlString CheckBoxList(this HtmlHelper htmlHelper, List<SelectListItem> list, string ModelCollectionName)
{
var sb = new StringBuilder();
if (list != null)
{
int i = 0;
foreach (var l in list)
{
string collectionNameIndex = String.Format("{0}[{1}]", ModelCollectionName, i);
var hiddenName = new TagBuilder("input");
hiddenName.Attributes.Add(new KeyValuePair<string, string>("type", "hidden"));
hiddenName.Attributes.Add(new KeyValuePair<string, string>("name", String.Format("{0}.{1}", collectionNameIndex, "Text")));
hiddenName.Attributes.Add(new KeyValuePair<string, string>("value", l.Text));
var hiddenValue = new TagBuilder("input");
hiddenValue.Attributes.Add(new KeyValuePair<string, string>("type", "hidden"));
hiddenValue.Attributes.Add(new KeyValuePair<string, string>("name", String.Format("{0}.{1}", collectionNameIndex, "Value")));
hiddenValue.Attributes.Add(new KeyValuePair<string, string>("value", l.Value));
var checkBoxTag = htmlHelper.CheckBox(String.Format("{0}.{1}", collectionNameIndex, "Selected"), l.Selected);
var labelTag = new TagBuilder("label");
labelTag.Attributes.Add(new KeyValuePair<string, string>("for", String.Format("{0}.{1}", collectionNameIndex, "Name")));
labelTag.SetInnerText(l.Text);
sb.Append(hiddenName);
sb.Append(hiddenValue);
sb.Append(checkBoxTag);
sb.Append(labelTag);
sb.Append("<br/>");
i++;
}
}
return MvcHtmlString.Create(sb.ToString());
}
虽然微软员工可能是唯一可以回答为什么不存在这种帮助方法的人,但您可以尝试:
模型:
public class MyViewModel
{
public bool[] Values { get; set; }
}
控制器:
public class HomeController : Controller
{
public ActionResult Index()
{
return View(new MyViewModel
{
Values = new[] { true, false, true, false }
});
}
[HttpPost]
public ActionResult Index(MyViewModel model)
{
return View(model);
}
}
看法:
<% using (Html.BeginForm()) { %>
<%: Html.EditorFor(x => x.Values) %>
<input type="submit" value="OK" />
<% } %>
如您所见EditorFor
,它将处理所需的一切。
您可能对Jeremiah Clark的 MVC 文章 CheckBoxList Helper感兴趣(不幸的是,它的日期为 2008 年 11 月并且关注 MVC 1)。