我如何创建一个基于复选框为模型创建的对象列表
本文关键字:创建 模型 复选框 列表 对象 何创建 一个 | 更新日期: 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_Name
和m_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>
所以,你真的应该学习两件事:
- 当绑定到列表时,默认模型绑定器期望的
naming convention
- 如何使用javascript调试工具(如FireBug和/或Chrome Developper工具栏),它将允许您检查发送到服务器的所有值,并立即识别您是否尊重您在1中学到的约定。