1

我正在将动态项目添加到查询表单中。使用部分视图来添加/删除项目,但在提交主视图时,值未绑定。我的问题是如何做同样的事情。

已在此处此处检查了几个类似的问题,但找不到丢失的内容。

使用 2 ViewModels ,用于主视图(查询)和部分视图( LineItems),并使用 BeginCollectionItem 动态添加项目。

代码:

视图模型

public class EnquiryVM
    {
        public int ID { get; set; }

        [Required]
        public string EnquiryNumber { get; set; }
        public int ClientID { get; set; }
        public IEnumerable<SelectListItem> Clients { get; set; }
        public Client Client { get; set; }
        public int ItemID { get; set; }
        public List<EnquiryLineItem> LineItems { get; set; }

    }
 public class EnquiryLineItemVM
    {
        public int ID { get; set; }
        [Required]
        public string ItemDesc { get; set; }
        public int Quantity { get; set; }
        public int ManufacturerId { get; set; }
        public IEnumerable<SelectListItem> ManufacturerList { get; set; }
    }

意见:主要:

@model ViewModel.EnquiryVM

@using (Html.BeginForm("Create", "Enquiries", FormMethod.Post))
{
    @Html.AntiForgeryToken()

    <div class="form-horizontal">

        <hr />
        @Html.ValidationSummary(true, "", new { @class = "text-danger" })



        <div class="form-group">
            @Html.LabelFor(model => model.EnquiryNumber, htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-3">
                @Html.EditorFor(model => model.EnquiryNumber, new { htmlAttributes = new { @class = "form-control" } })
                @Html.ValidationMessageFor(model => model.EnquiryNumber, "", new { @class = "text-danger" })
            </div>
        </div>





        <div class="form-group">
            @Html.LabelFor(model => model.ClientID, "Client", htmlAttributes: new { @class = "control-label col-md-2" })
            <div class="col-md-3">

                @Html.DropDownListFor(u => u.ClientID, (IEnumerable<SelectListItem>)Model.Clients, "--Select--")
                @Html.ValidationMessageFor(model => model.ClientID, "", new { @class = "text-danger" })
            </div>
        </div>

         <div id="LineItems">
          //  @using (Html.BeginForm()) // do we require again here since this will be like nested form? tested commenting still not working
           // {
                <div id="editorRowsLineitems">
                    @foreach (var item in Model.LineItems)
                    {
                        @Html.Partial("_CreateEnquiryItem", item)
                    }
                </div>
                @Html.ActionLink("Add Items", "CreateLineItem", null, new { id = "addItem", @class = "button" });
          //  }
        </div>
        <div class="form-group">
            <div class="col-md-offset-2 col-md-10">
                <input type="submit" value="Create" class="btn btn-default" />
            </div>
        </div>
    </div>
}

<div>
    @Html.ActionLink("Back to List", "Index")
</div>

@section Scripts {
    @Scripts.Render("~/bundles/jqueryval")
<script type="text/javascript">
    $(function () {
        $('#addItem').on('click', function () {
            $.ajax({
                url: '@Url.Action("CreateLineItem")',
                    cache: false,
                    success: function (html) {
                        $("#editorRowsLineitems").append(html);

                        $("form").removeData("validator");
                        $("form").removeData("unobtrusiveValidation");
                        $.validator.unobtrusive.parse("form");
                    }
                });
                return false;
            });
        $('#editorRowsLineitems').on('click', '.deleteRow', function () {
                $(this).closest('.editorRow').remove();
            });
        $('form').data('validator', null);
        $.validator.unobtrusive.parse($('form'));
    });


</script>
}

部分观点:

@model ViewModels.EnquiryLineItemVM

<div class="editorRow">
    @using (Html.BeginCollectionItem("ItemList"))
    {
        <table class="table">

            <tr>
                <td>
                    @Html.EditorFor(model => model.ItemDesc)

                </td>
                <td>
                    @Html.EditorFor(model => model.Quantity)

                </td>

                <td>
                    @Html.DropDownListFor(model => model.ManufacturerId, Model.ManufacturerList, "--Please Select--")

                </td>
                <td>

                    <a href="#" class="deleteRow">Delete</a>
                </td>
            </tr>
        </table>

    }

控制器 :

 public ActionResult Create()
        {
            var viewModel = GetAllCategories();
            return View(viewModel);
        }
  private EnquiryVM GetAllCategories()
        {
            var model = new EnquiryVM();
            var clients = db.Clients.ToList();
            model.Clients = clients.Select(s => new SelectListItem
            {
                Value = s.ID.ToString(),
                Text = s.Name
            });

            var LineItems = new List<EnquiryLineItem>();
            model.LineItems = LineItems;

           return model;
        }
 [HttpPost]
        [ValidateAntiForgeryToken]
        public ActionResult Create( EnquiryVM enquiryVM)
        {
            var enquiry = new Enquiry();
            enquiry.EnquiryNumber = enquiryVM.EnquiryNumber;
            enquiry.ClientID = enquiryVM.ClientID;
            enquiry.EnquiryLineItems = enquiryVM.LineItems; //line items are null
            if (ModelState.IsValid)
            {
                db.Enquiries.Add(enquiry);
                enquiryVM.ID = enquiry.ID;
                foreach (var item in enquiry.EnquiryLineItems)
                {
                    item.EnquiryID = enquiryVM.ID;
                    db.EnquiryLineItems.Add(item);
                }

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

            var viewModel = GetAllCategories();
            return View(enquiryVM);
        }

我应该如何将动态添加的行的值映射到 ViewModel ( EnquiryVM ),以便我可以将它插入到数据库中。感谢您的耐心和时间。

4

1 回答 1

2

您的集合属性的名称是LineItems,因此您生成其控件的代码需要是

@using (Html.BeginCollectionItem("LineItems")) // not ..("ItemList")
{
    ....
}

以便它使用name="LineItems[xxxx].ItemDesc"etc 生成输入,而不是生成的当前使用name="ItemList[xxxx].ItemDesc"(在xxxx哪里Guid

ModelState附带说明一下,如果您的 POST 方法中的代码由于您返回视图并且没有重新填充IEnumerable<SelectListItem> Clients属性而无效,则会引发异常。有关详细说明,请参阅具有键“XXX”的 ViewData 项的类型为“System.Int32”,但必须为“IEnumerable”类型

此外,添加项目的脚本的最后 2 行 ($('form').data('validator', null); $.validator.unobtrusive.parse($('form'));应该被删除(重新解析验证器是昂贵的,而且你做了两次 - 一次在添加 html 之前(上面的 2 行),一次在添加 html 之后

于 2017-09-19T08:53:51.470 回答