C# 将复选框列表传递到视图中并拉出IEnumerable

C# 将复选框列表传递到视图中并拉出IEnumerable,c#,asp.net-mvc,razor,asp.net-mvc-5,C#,Asp.net Mvc,Razor,Asp.net Mvc 5,我有一个将与用户关联的项目列表。这是一对多的关系。我希望将整个项目列表传递到视图中,以便它们可以从尚未关联的项目中进行选择(也可以查看已关联的项目)。我想从这些中创建复选框。然后,我想将所选内容发送回要关联的控制器。我如何才能传入所有这些文件的列表,包括那些尚未关联的文件,并可靠地将它们传递回要关联的文件 这是我第一次尝试的,但很明显,这不起作用,因为我是基于通过AllItems集合传入的项来输入的,该集合与用户本身的项没有连接 <div id="item-list"> @f

我有一个将与用户关联的项目列表。这是一对多的关系。我希望将整个项目列表传递到视图中,以便它们可以从尚未关联的项目中进行选择(也可以查看已关联的项目)。我想从这些中创建复选框。然后,我想将所选内容发送回要关联的控制器。我如何才能传入所有这些文件的列表,包括那些尚未关联的文件,并可靠地将它们传递回要关联的文件

这是我第一次尝试的,但很明显,这不起作用,因为我是基于通过
AllItems
集合传入的项来输入的,该集合与用户本身的项没有连接

<div id="item-list">
    @foreach (var item in Model.AllItems)
    {
        <div class="ui field">
            <div class="ui toggle checkbox">
                <input type="checkbox" id="item-@item.ItemID" name="Items" value="@item.Active" />
                <label for="item-@item.ItemID">@item.ItemName</label>
            </div>
        </div>
    }
</div>

@foreach(Model.AllItems中的var项)
{
@item.ItemName
}

看起来您不会动态删除复选框,从而使此问题更容易解决。注意:如果允许客户端或脚本从页面中动态删除复选框,则以下解决方案将无法按预期工作,因为索引将不再是连续的

MVC模型绑定并不是万无一失的,所以有时候你必须帮助它。模型绑定器知道它需要绑定到名为Items的属性,因为输入字段的名称是Items,但它不知道Items是列表。因此,假设在控制器中有一个要建模的项列表绑定到调用的项,那么您需要做的是帮助MVC识别您正在绑定到一个列表。为此,请指定列表的名称和索引

<div id="item-list">
    @for (var i = 0; i < Model.AllItems.Count; i++)
    {
        <div class="ui field">
            <div class="ui toggle checkbox">
                <input type="checkbox" id="item-@Model.AllItems[i].ItemID" name="Items[@i]" value="@Model.AllItems[i].Active" />
                <label for="item-@Model.AllItems[i].ItemID">@Model.AllItems[i].ItemName</label>
            </div>
        </div>
    }
</div>

@对于(var i=0;i
这里的关键是:


注意到这些项目[@i]?这告诉模型绑定器查找名为Items的属性,并将此值绑定到Items的i处的索引。

不能使用
foreach
循环绑定到集合。您也不应该手动生成html,在本例中,由于未选中的复选框不会发回,因此无法生成html。始终使用强类型html帮助程序,以便获得正确的双向模型绑定

您没有指出您的模型是什么,但是假设您有一个
用户
,并且希望为该用户选择
角色
,然后创建视图模型来表示您希望在视图中显示的内容

public class RoleVM
{
  public int ID { get; set; }
  public string Name { get; set; }
  public bool IsSelected { get; set; }
}
public class UserVM
{
  public UserVM()
  {
    Roles = new List<RoleVM>();
  }
  public int ID { get; set; }
  public string Name { get; set; }
  public List<RoleVM> Roles { get; set; }
}
看法


这是可行的,因为它在项索引中传递,但是每个项的实际值都是null。有没有办法在中传递更多关于对象的信息?所以我假设你的项目列表不是布尔值列表?处理这种情况的方法是向模型绑定器提供更多信息。因此,如果项目列表中的对象具有名为“Active”的属性,则复选框的名称应为items[@i].Active。然后,对于要填充的任何其他字段,例如name,您将有另一个输入,名称为Items[@i].name。我想我很困惑-您是说一个复选框需要多个输入吗?如果我只想将项目ID传递回控制器,该怎么办?编辑:另外,为了选中复选框,您可能打算使用
checked
属性。您想绑定到什么?如果您要绑定到一个列表,那么不,您只需要一个复选框,并且您不必担心为模型绑定器提供比项目[@i]更多的信息。如果要绑定到列表,则需要多个输入字段来填写列表中每个对象的每个属性。基本类型(bool、int、char等)不需要额外的点表示法。对象类型可以。除非选中每个复选框,否则这不起作用。
DefaultModelBinder
要求集合索引器从零开始并连续。由于未选中的复选框不会发回,因此如果第一个复选框未选中,那么模型绑定将失败,
项将为空。这实际上与我最后所做的类似(有一些小的差异)。不过,我可能会根据你的建议做一些调整。谢谢
public ActionResult Edit(int ID)
{
  UserVM model = new UserVM();
  // Get you User based on the ID and map properties to the view model
  // including populating the Roles and setting their IsSelect property
  // based on existing roles
  return View(model);
}
@model UserVM
@using(Html.BeginForm())
{
  @Html.HiddenFor(m => m.ID)
  @Html.DisplayFor(m => m.Name)
  for(int i = 0; i < Model.Roles.Count; i++)
  {
    @Html.HiddenFor(m => m.Roles[i].ID)
    @Html.CheckBoxFor(m => m.Roles[i].IsSelected)
    @Html.LabelFor(m => m.Roles[i].IsSelected, Model.Roles[i].Name)
  }
  <input type"submit" />
}
[HttpPost]
public ActionResult Edit(UserVM model)
{
  // Loop through model.Roles and check the IsSelected property
}