我有一堆复选框,供用户指定他们想要在网格上看到哪些列:
目前,每个复选框都有自己的密钥(基本上是它的标签名称),并在我的视图中声明如下:
@Html.CheckBox(column.Key,
(Request.Form[column.Key] == null ? true :
Request.Form[column.Key].Contains("true")),
new { @class = "columnSelector" })
@Html.Label(column.HeaderText)
问题是我必须在我的操作中从表单集合中获取值,否则我必须为每个列选择器复选框都有一个bool
参数。或者,我认为我可以将它们全部命名为“columnselection”或者其他东西,然后它将作为值数组传递给我的操作,但是由于我没有列键,因此我丢失了值的上下文。
我不想为每个复选框创建一个带有属性的viewmodel,因为此功能在具有不同列的其他屏幕上使用,我希望保持通用。
关于如何以干净简单的方式实现此列选择的任何想法?
答案 0 :(得分:1)
Html.CheckBox
方法有一个奇怪的实现。复选框将具有唯一的name
,并且基本上为true/false
值。这样,该值很容易映射到Action中的bool
参数。
正如您已经注意到的那样,当您的复选框是动态的时,这会让您感到棘手。
解决方案是生成您自己的复选框,所有复选框都使用共同的name
并具有唯一的value
。这些将很好地映射到你的行动!
See this question too, for some great examples and explanations
这是所需的行动:
public ActionResult SetSelectedColumns(string[] selectedColumns) {
// selectedColumns will contain the keys of all the checked columns.
}
以下是如何让您的HTML正确映射:
<input type="checkbox" name="selectedColumns" value="@column.Key" @(column.Selected ? "checked='checked'" : "") />
我强烈建议您将此功能纳入扩展方法,以便您还可以合并ModelState
和htmlAttributes
。这是我未经考验的尝试:
public static HtmlString CheckBoxAlt(this HtmlHelper html, string name, string value, bool selected, object htmlAttributes)
{
var tag = new TagBuilder("input");
if (htmlAttributes != null)
tag.MergeAttributes(new RouteValueDictionary(htmlAttributes));
tag.MergeAttribute("type", "checkbox");
tag.MergeAttribute("name", name);
tag.MergeAttribute("value", value);
// Determine if this check should be selected:
var state = html.ViewData.ModelState[name];
if (state != null)
{
var values = (string[])state.Value.ConvertTo(typeof(string[]));
selected = Array.IndexOf(values, value) != -1;
}
if (selected)
tag.MergeAttribute("checked", "checked");
return new HtmlString(tag.ToString(TagRenderMode.SelfClosing));
}