1

我有这个基于模型列表的视图,在该列表中,我根据布尔值为模型的每个项目创建强类型复选框。

这是我的看法:

@using MyApp.Models
@model IList<MyApp.Models.ObjInfo>

@{
    ViewBag.Title = "Obj Inventory";
}

<h2>Search Inventory</h2>

<p>
    @using (Html.BeginForm())
    {
        (Many search filters which are non-relevant)
        <p>
            Send Items: @Html.ActionLink("Click Here", "SendItems")
        </p>
    }
<table>
    <tr>
        <th>
            Obj Name
        </th>
        <th>
            Number In Stock
        </th>
        (...)
        <th>
            Select Item
        </th>
    </tr>
@foreach (var item in Model) {
    <tr>
        <td>
            @Html.DisplayFor(modelItem => item.OtherObj.m_Name)
        </td>
        (...)
        <td>
            @Html.CheckBoxFor(modelItem => item.m_IsSelected)
        </td>
    </tr>
}

</table>

整个过程运行良好,我实际上可以为我的模型列表中的每个项目生成一个带有复选框的视图。

现在我的问题是我想创建一个列表,该列表仅重新组合列表中已检查的项目并将它们发送到控制器。我怎么能那样做?任何人都可以帮助我或建议我的工作方式吗?

谢谢!

* 编辑 *

这是用于获取项目列表的 HttpPost 方法,如下所述:

//
        // GET: /Inventory/SendItems
        [HttpPost]
        public ActionResult SendItems(IList<ObjInfo> listToSend)
        {
            m_ListObjToSend = new List<ObjInfo>();

            foreach (var item in listToSend.Where(item => item.m_IsSelected))
            {
                m_ListObjToSend .Add(item);
            }

            return View(m_ListObjToSend );
        }

但是我遇到了很多问题:

  • 如果我放置 [HttpPost] 属性,此方法不起作用(它将显示为“未找到”);
    • 我应该收到的列表是空的;
    • 即使选中的值显示为 true,与复选框链接的每个隐藏字段的默认值为 false;
    • 我正在使用 actionlink,因为我不想使用按钮,已经有一个按钮正在做另一项工作。

我愿意接受任何可用的评论/帮助,谢谢!

4

1 回答 1

3

如果您使用 CheckBoxFor 帮助器来生成复选框,您会注意到它会随每个复选框生成一个附加隐藏字段。这意味着所有值都将发送到控制器,您必须在控制器中过滤那些被检查的值。

此外,我建议您使用索引来确保正确的模型绑定。在将其传递给视图之前,您只需要使用IList<ObjInfo>或通过在视图模型上ObjInfo[]调用.ToList()或扩展方法即可轻松实现:.ToArray()

@using MyApp.Models
@model IList<ObjInfo>
...
@for (var i = 0; i < Model.Count; i++) 
{
    <tr>
        <td>
            @Html.DisplayFor(x => x[i].OtherObj.m_Name)
        </td>
        (...)
        <td>
            @Html.CheckBoxFor(x => x[i].m_IsSelected)
        </td>
    </tr>
}
...

现在您的控制器操作可以直接获取项目列表:

[HttpPost]
public ActionResult SomeAction(IEnumerable<ObjInfo> model)
{
    ...
}

如果您想找到选定的值,您可以简单地通过 LINQ 获取它们:

[HttpPost]
public ActionResult SomeAction(IEnumerable<ObjInfo> model)
{
    var selectedItems = model.Where(x => x.m_IsSelected);
    ...
}

备注:m_Nameandm_IsSelected是 C# 中属性的一个非常糟糕的命名约定。


更新:

您的代码存在的另一个问题是您的代码Html.BeginForm不包含任何输入字段。它只有一个 ActionLink 显然只做一个 GET 请求。如果你想提交值,你应该用表单包裹你的整个表格并使用提交按钮而不是一些操作链接:

@using MyApp.Models
@model IList<ObjInfo>

@{
    ViewBag.Title = "Obj Inventory";
}

<h2>Search Inventory</h2>

<p>
    @using (Html.BeginForm("SendItems", null, FormMethod.Post))
    {
        (Many search filters which are non-relevant)

        <table>
            <tr>
                <th>Obj Name</th>
                <th>Number In Stock</th>
                (...)
                <th>Select Item</th>
           </tr>
        @for (var i = 0; i < Model.Count; i++) 
        {
            <tr>
                <td>
                    <!-- 
                    This will not be sent to your controller because it's only a label.
                    You will need a corresponding hidden field if you want to get that value back
                    -->
                    @Html.DisplayFor(x => x[i].OtherObj.m_Name)
                </td>
                (...)
                <td>
                    @Html.CheckBoxFor(x => x[i].m_IsSelected)
                </td>
            </tr>
        }
        </table>

        <p>
            Send Items: <button type="submit">Click Here</button>
        </p>
    }
</p>

所以真的,你应该学习两件事:

  1. naming convention绑定到列表时默认模型绑定器所期望的
  2. 如何使用 javascript 调试工具(例如 FireBug 和/或 Chrome Developper Toolbar),它允许您检查发送到您的服务器的所有值,并立即识别您是否遵守您在 1 中学到的约定。
于 2013-03-07T16:55:17.837 回答