我如何创建一个基于复选框为模型创建的对象列表

本文关键字:创建 模型 复选框 列表 对象 何创建 一个 | 更新日期: 2023-09-27 18:03:02

我有一个基于模型列表的视图,其中我基于一个布尔值为模型的每个项创建了强类型的复选框。

这是我的观点:

@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>

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

现在我的问题是,我想创建一个列表,该列表将只重新组合列表中已检查并将它们发送给控制器的项目。我怎么能这么做呢?有人能帮助我或建议我一个工作的方法吗?

谢谢!

* EDIT *

这是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]属性(它会显示为" NOT Found");
    • 我应该收到的列表是空的;
    • 与复选框链接的每个隐藏字段的默认值为false,即使选中的值显示为true;
    • 我正在使用一个动作链接,因为我不想使用一个按钮,已经有一个正在做另一个工作。

我是开放的任何意见/帮助可用,谢谢!

我如何创建一个基于复选框为模型创建的对象列表

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

我还建议您使用索引来确保正确的模型绑定。您只需要使用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_Namem_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工具栏),它将允许您检查发送到服务器的所有值,并立即识别您是否尊重您在1中学到的约定。