【问题标题】:ASP.NET MVC Edit CheckBoxList values in DatabaseASP.NET MVC 编辑数据库中的 CheckBoxList 值
【发布时间】:2016-11-02 23:04:06
【问题描述】:

我无法理解如何根据 CustId 值从数据库中的 CustomerDevice 表中检索和编辑 DevId 值到 CheckBoxList。

CustomerDeviceController 的我的索引操作方法显示我的客户表中的客户列表。我有一个标有“Edit”的 ActionLink,它将 CustId 值传递给 CustomerDeviceController [HttpGet] Edit(int? id) Action Method,该方法当前显示 Devices 表中的所有 CheckBoxListItem 值。但是,CheckBoxList 不会显示从数据库中的 CustomerDevice 表到与 CustId 相关的 CheckBoxList 中检查的 DevId 值,而是显示对每个 CheckBoxList 值的检查。

我无法理解和弄清楚的部分是,如何根据 CustId 将数据库中 CustomerDevice 表中选定的 DevId 值显示到 CheckBoxList,然后在 [ HttpPost] 如果需要,将操作方法​​编辑回我的数据库中的 CustomerDevice 表。

请看下面我到目前为止的以下代码。

模型

public class CheckBoxListItem
{
    public int ID { get; set; }
    public string Display { get; set; }
    public bool IsChecked { get; set; }
}

public class Customer
{
    public int CustId { get; set; }
    public string CustDisplayName { get; set; }
    public string CustFirstName { get; set; }
    ....
}

public class Device
{
    public int DevId { get; set; }
    public string DevType { get; set; }
}

public class CustomerDevice
{
    public int CustId { get; set; }
    public int DevId { get; set; }
    public Customer Customer { get; set; }
    public Device Device { get; set; }
}

视图模型

public class CustomerDeviceFormViewModel
{
    public int CustId { get; set; }
    public string CustDisplayName { get; set; }
    public List<CheckBoxListItem> Devices { get; set; }
}

客户设备控制器

public ActionResult Edit(int? id)
{
    if (id == null)
    {
        return NotFound();
    }
    var customervm = new CustomerDeviceFormViewModel();
    Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
    if (customer == null)
    {
        return NotFound();
    }
    customervm.CustId = customer.CustId;
    customervm.CustDisplayName = customer.CustDisplayName;
    // Retrieves list of Devices for CheckBoxList
    var deviceList = db.Devices.ToList();
    var checkBoxListItems = new List<CheckBoxListItem>();
    foreach (var device in deviceList)
    {
        checkBoxListItems.Add(new CheckBoxListItem()
        {
            ID = device.DevId,
            Display = device.DevType,
            IsChecked = deviceList.Where(x => x.DevId == device.DevId).Any()
        });
    }
    customervm.Devices = checkBoxListItems;
    return View(customervm);
}

        [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Edit(CustomerDeviceFormViewModel vmEdit)
    {
        if (ModelState.IsValid)
        {
            Customer customer = db.Customers.SingleOrDefault(c => c.CustId == vmEdit.CustId);

            if (customer == null)
            {
                return NotFound();
            }

            foreach (var deviceId in vmEdit.Devices.Where(x => x.IsChecked).Select(x => x.ID))
            {
                var customerDevices = new CustomerDevice
                {
                    CustId = vmEdit.CustId,
                    DevId = deviceId
                };

                db.Entry(customerDevices).State = EntityState.Modified;
            }

            db.SaveChanges();
            return RedirectToAction("Index");
        }

        return View(vmEdit);
    }

Edit.chtml

<div class="form-group">
    Please select the Devices to assign to <b>@Html.DisplayFor(c => c.CustDisplayName)</b>
</div>

<div class="form-group">
    @Html.EditorFor(x => x.Devices)
</div>

@Html.HiddenFor(c => c.CustId)

<div class="form-group">
    <button type="submit" class="btn btn-primary">Submit</button>
</div>

Shared/EditorTemplate/CheckBoxListItem.chtml

<div class="checkbox">
<label>
    @Html.HiddenFor(x => x.ID)
    @Html.CheckBoxFor(x => x.IsChecked)
    @Html.LabelFor(x => x.IsChecked, Model.Display)
</label>
<br />

【问题讨论】:

    标签: c# asp.net-core-mvc


    【解决方案1】:

    您用于设置IsChecked 值的代码将始终返回true(您的循环基本上是说如果集合包含我(当然它包含)然后将其设置为true)。

    您需要通过读取CustomerDevice 表中的值来获取每个Customer 的选定值

    Customer customer = db.Customers.SingleOrDefault(c => c.CustId == id);
    if (customer == null)
    {
        return NotFound();
    }
    // Get all devices
    var deviceList = db.Devices.ToList();
    // Get the selected device ID's for the customer
    IEnumerable<int> selectedDevices = db.CustomerDevices
        .Where(x => x.CustId == id).Select(x => x.DevId);
    // Build view model
    var model = new CustomerDeviceFormViewModel()
    {
        CustId = customer.CustId,
        CustDisplayName = customer.CustDisplayName,
        Devices = deviceList.Select(x => new CheckBoxListItem()
        {
            ID = x.DevId,
            Display = x.DevType,
            IsChecked = selectedDevices.Contains(x.DevId)
        }).ToList()
    };
    return View(model);
    

    【讨论】:

    • 当我复制/粘贴您的解决方案时,它说我缺少} expected。这行代码IEnumerable&lt;int&gt; selectedDevices = db.CustomerDevices.Where(x =&gt; x.CustId == id).Select(x =&gt; x.DevId);是否只是为变量selectedDevices创建了一个int数组
    • 查看编辑(缺少最后第二行 ;)。是的,selectedDevices 是一个仅包含 DevId 值的集合
    • 谢谢!我收到了另一条错误消息,但找到了解决方法。我将var deviceList = db.Devices;修改为var deviceList = db.Devices.ToList();
    • 还是不行吗? (如果您仍然有问题,我可以为您创建一个简单的小提琴来展示它是如何工作的)
    • 它现在工作正常。现在只需要弄清楚 [HttpPost] 编辑操作方法,以便在需要时更新 DevId 值。
    【解决方案2】:

    这是我使用的 Razor 代码的 sn-p:

       foreach (SelectListItem p in Model.PositionList)
        {
        @Html.Raw(p.Text + "<input type=checkbox name=\"PositionIDs\" id=\"PositionIDs\" value=" + @p.Value + (Model.Positions != null && Model.Positions.Any(pos => pos.ScoreCardId == Convert.ToInt32(p.Value)) ? " checked />" : " />"));
        }
    

    【讨论】:

    • 我认为我的问题可能出在 CustomerDeviceController 而不是 View 中。
    【解决方案3】:

    您可能想看看 MvcCheckBoxList NuGet 包:

    https://www.nuget.org/packages/MvcCheckBoxList/

    这使得在 MVC 中使用 CheckBoxList 做一些强大的事情变得更加容易 - 并且可能是解决 CheckBox 问题的更好方法。

    【讨论】:

    • 虽然此链接可能会回答问题,但最好在此处包含答案的基本部分并提供链接以供参考。如果链接页面发生更改,仅链接答案可能会失效。 - From Review
    • @OrDuan 我总体上同意你的观点,如果我有一段特定的代码来解决特定问题,我会包含它。但是,由于这是一个 NuGet 包,在答案中解释其全部工作原理可能有点过分?
    • 这与OP的问题无关,即如何根据数据库中的数据正确设置复选框的值
    • 我不同意 - 使用这个工具可以让 OP 以更好的方式做到这一点 - 这就是我发现这个包的方式,我很感激。如果您不知道,这是您不会考虑的事情。这是解决 OP 问题的另一种方法。
    • OP 生成 html 的代码很好。问题是关于如何从数据库中获取正确的数据以及使用不同的工具来生成 html 绝对不能解决问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多