带有BeginCollectionItem的MVC 5动态行

单击按钮时向表中添加/删除行的最佳方法是什么? 我需要从ChildClass属性创建的行(子类是主类/模型中的列表)。

目前有一个View(模型是MyMain),它使用RenderPartial引用部分视图。

局部视图显示模型的属性,一个名为MyChild的类,它是MyMain中的对象列表。

我想添加和删除按钮来动态添加部分视图中保存的行。

因此,重复添加MyChild以获取列表中的更多行。 这可能吗? 或者我不应该为此使用部分视图?

更新的代码

下面是我正在使用的当前类和视图,我一直在尝试实现BeginCollectionItem帮助器,但是我正在尝试加载部分视图的null ref,尽管if语句说创建一个新实例子类如果不存在 – 为什么会被忽略?

主视图

@using (Html.BeginForm()) {  @Html.ActionLink("Add another", "Add", null, new { id = "addItem" }) 
MyMain First MyChild First
@Html.EditorFor(m => m.First) @if (Model.child != null) { for (int i = 0; i < Model.child.Count; i++) { Html.RenderPartial("MyChildView"); } } else { Html.RenderPartial("MyChildView", new MvcTest.Models.MyChild()); }
}

部分视图

 @model MvcTest.Models.MyChild @using (Html.BeginCollectionItem("myChildren")) { Html.EditorFor(m => m.Second); } 

楷模

 public class MyMain { [Key] public int Id { get; set; } public string First { get; set; } public List child { get; set; } } public class MyChild { [Key] public int Id { get; set; } public string Second { get; set; } } 

调节器

 public class MyMainsController : Controller { // GET: MyMains public ActionResult MyMainView() { return View(); } [HttpPost] public ActionResult MyMainView(IEnumerable myChildren) { return View("MyMainView", myChildren); } public ViewResult Add() { return View("MyChildView", new MyChild()); } } 

更新的答案 – 原始代码不适用于’动态’,但它允许我在问题参数中需要做的所有事情。

最初,我无法在评论工作的问题中得到斯蒂芬的BCI建议,因为那时我已经并且它很棒。 如果您复制+粘贴,则更新部分中的以下代码将起作用,但您需要从GIT手动下载BCI或在Visual Studio中使用PM> Install-Package BeginCollectionItem和Package Manager控制台。

由于复杂性并且之前没有完成MVC,我在使用BCI时遇到了一些问题 – 这里有关于处理访问class.property(type class).property(type class).property更多信息。

原始答案 – 我在下面提供了一个比我的问题更清晰的例子,这很快就让人感到困惑。

使用两个部分视图,一个用于员工列表,另一个用于创建新员工,所有这些视图都包含在companyemployee的viewmodel中,其中包含公司对象和员工对象列表。 这样,可以从列表中添加,编辑或删除多个员工。

希望这个答案可以帮助任何寻找类似东西的人,这应该提供足够的代码来使其工作,并至少推动你朝着正确的方向前进。

我已经省略了我的上下文和初始化类,因为它们只对代码优先,如果需要我可以添加它们。

感谢所有帮助过的人。

模型 – CompanyEmployee是视图模型

 public class Company { [Key] public int id { get; set; } [Required] public string name { get; set; } } public class Employee { [Key] public int id { get; set; } [Required] public string name { get; set; } [Required] public string jobtitle { get; set; } [Required] public string number { get; set; } [Required] public string address { get; set; } } public class CompanyEmployee { public Company company { get; set; } public List employees { get; set; } } 

指数

 @model MMV.Models.CompanyEmployee @{ ViewBag.Title = "Index"; Layout = "~/Views/Shared/_Layout.cshtml"; } 

Index

Company
@Html.LabelFor(m => m.company.name)
@Html.EditorFor(m => m.company.name)
Employees @{Html.RenderPartial("_employeeList", Model.employees);}
@{Html.RenderPartial("_employee", new MMV.Models.Employee());}

员工名单的部分视图

 @model IEnumerable @using (Html.BeginForm("Employees")) {  @foreach (var emp in Model) {  } 
Name Job Title Number Address
@Html.DisplayFor(modelItem => emp.name) @Html.DisplayFor(modelItem => emp.jobtitle) @Html.DisplayFor(modelItem => emp.number) @Html.DisplayFor(modelItem => emp.address)
}

部分视图创建员工

 @model MMV.Models.Employee @using (Html.BeginForm("Create","Employees")) {  @Html.ValidationSummary(true, "", new { @class = "text-danger" }) 
@Html.EditorFor(model => model.name) @Html.ValidationMessageFor(model => model.name, "", new { @class = "text-danger" }) @Html.EditorFor(model => model.jobtitle) @Html.ValidationMessageFor(model => model.jobtitle) @Html.EditorFor(model => model.number) @Html.ValidationMessageFor(model => model.number, "", new { @class = "text-danger" }) @Html.EditorFor(model => model.address) @Html.ValidationMessageFor(model => model.address, "", new { @class = "text-danger" })
}

控制器 – 我使用了多个,但你可以把它们全部合二为一

 public class CompanyEmployeeController : Controller { private MyContext db = new MyContext(); // GET: CompanyEmployee public ActionResult Index() { var newCompanyEmployee = new CompanyEmployee(); newCompanyEmployee.employees = db.EmployeeContext.ToList(); return View(newCompanyEmployee); } [HttpPost, ActionName("Delete")] public ActionResult DeleteConfirmed(int id) { Employee employee = db.EmployeeContext.Find(id); db.EmployeeContext.Remove(employee); db.SaveChanges(); return RedirectToAction("Index", "CompanyEmployee"); } [HttpPost] public ActionResult Create([Bind(Include = "id,name,jobtitle,number,address")] Employee employee) { if (ModelState.IsValid) { db.EmployeeContext.Add(employee); db.SaveChanges(); return RedirectToAction("Index", "CompanyEmployee"); } return View(employee); } } 

更新的代码 – 使用BeginCollectionItem – 动态添加/删除

学生偏爱

 @model UsefulCode.Models.Person 
@using (Html.BeginCollectionItem("students")) {
@Html.TextBoxFor(m => m.firstName)
@Html.TextBoxFor(m => m.lastName)
X
}

老师偏爱

 @model UsefulCode.Models.Person 
@using (Html.BeginCollectionItem("teachers")) {
@Html.TextBoxFor(m => m.firstName)
@Html.TextBoxFor(m => m.lastName)
X
}

注册控制器

 public ActionResult Index() { var register = new Register { students = new List { new Person { firstName = "", lastName = "" } }, teachers = new List { new Person { lastName = "", firstName = "" } } }; return View(register); } 

注册和人员模型

 public class Register { public int id { get; set; } public List teachers { get; set; } public List students { get; set; } } public class Person { public int id { get; set; } public string firstName { get; set; } public string lastName { get; set; } } 

指数

 @{ Layout = "~/Views/Shared/_Layout.cshtml"; } @model UsefulCode.Models.Register 
@using (Html.BeginForm()) {
@foreach (var item in Model.students) { @Html.Partial("StudentView", item) }
@Html.ActionLink("Add", "StudentManager", null, new { id = "addItemStudents", @class = "button" }); }
@using (Html.BeginForm()) {
@foreach (var item in Model.teachers) { @Html.Partial("TeacherView", item) }
@Html.ActionLink("Add", "TeacherManager", null, new { id = "addItemTeachers", @class = "button" }); }
@section scripts { }

StudentManager行动:

 public PartialViewResult StudentManager() { return PartialView(new Person()); } 

您可以使用部分视图,但问题是使用EditorFor生成Id属性会导致生成重复项。

对我var view = @Html.Raw(@Html.Partial('Your partial'))在我的主视图中使用var view = @Html.Raw(@Html.Partial('Your partial'))在javascript里面。

然后,此变量将具有默认ID的视图,然后我将id属性和名称属性替换为id=YourMainListName_{ItemNumber}__Propertyname=YourMainListName_{ItemNumber}__Property

其中{ItemNumber}将是列表中新项目的索引。

需要大量的javascript才能使其正常工作,但只要您正确设置了Id和Name属性,一切都应该正常工作,包括回发页面时的模型绑定。