将复选框选择传递给操作

时间:2011-11-11 04:06:08

标签: .net asp.net-mvc

我有一堆复选框,供用户指定他们想要在网格上看到哪些列:

columnselector

目前,每个复选框都有自己的密钥(基本上是它的标签名称),并在我的视图中声明如下:

@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,因为此功能在具有不同列的其他屏幕上使用,我希望保持通用。

关于如何以干净简单的方式实现此列选择的任何想法?

1 个答案:

答案 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'" : "") />

我强烈建议您将此功能纳入扩展方法,以便您还可以合并ModelStatehtmlAttributes。这是我未经考验的尝试:

    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));
    }