Pass List of Checkboxes into View and Pull out IEnumerable [duplicate]

喜欢而已 提交于 2019-12-16 18:50:13

问题


I have a list of items that will be associated to a user. It's a one-to-many relationship. I want the entire list of items passed into the view so that they can choose from ones that are not associated to them yet (and also see those that are already associated). I want to create checkboxes from these. I then want to send the selected ones back into the controller to be associated. How can I pass in the list of all of them, including those that aren't yet associated, and reliably pass them back in to be associated?

Here's what I tried first, but it's clear this won't work as I'm basing the inputs off the items passed in via the AllItems collection, which has no connection to the Items on the user itself.

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

回答1:


You cannot bind to a collection using a foreach loop. Nor should you be manually generating your html, which in this case would not work because unchecked checkboxes do not post back. Always use the strongly typed html helpers so you get correct 2-way model binding.

You have not indicated what you models are, but assuming you have a User and want to select Roles for that user, then create view models to represent what you want to display in the view

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

In the GET method

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

View

@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" />
}

Then in the post method, your model will be bound and you can check which roles have been selected

[HttpPost]
public ActionResult Edit(UserVM model)
{
  // Loop through model.Roles and check the IsSelected property
}



回答2:


It doesn't look like you're going to be deleting the checkboxes dynamically so that makes this problem a lot easier to solve. NOTE: The following solution won't work as expected if you allow clients or scripts to dynamically remove the checkboxes from the page because the indexes will no longer be sequential.

MVC model binding isn't foolproof so sometimes you have to help it along. The model binder knows it needs to bind to a property called Items because the input field's name is Items, but it doesn't know Items is a list. So assuming in your controller you have a list of items to model bind to called Items what you need to do is help MVC recognize that you're binding to a list. To do this specify the name of the list and an index.

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

The key line here is this:

<input type="checkbox" id="item-@Model.AllItems[i].ItemID" name="Items[@i]" value="@Model.AllItems[i].Active" />

Notice the Items[@i]? That's telling the model binder to look for a property named Items and bind this value to the index at i for Items.



来源:https://stackoverflow.com/questions/29542107/pass-list-of-checkboxes-into-view-and-pull-out-ienumerable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!