我是一位经验丰富的.NET C#软件开发人员,但仅在几个月前我开始使用MVC Razor(MVC 5)。
我遇到一个小情况,我无法在网上找到任何答案(经过数小时的搜索)
我有一个模型,其中包含另一个模型的列表,而该模型又包含一个模型列表,如下所示。
public class Parent
{
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public List<Child> Children { get; set; }
}
public class Child
{
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
public List<GrandChild> GrandChildren { get; set; }
}
public class GrandChild
{
public string Name { get; set; }
public string Sex { get; set; }
public int Age { get; set; }
}
我的Controller有2个方法,一个是主要的Get,另一个是post以发布新数据
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult PostParent(Parent parent)
{
if (ModelState.IsValid)
{
//Do an insert to the DB
return View("~/Views/Home/Index.cshtml");
}
return Json("Error");
}
但是在我的表单视图中,我找不到创建添加按钮并将新数据插入Children和GrandChildren列表(包括孩子)的方法
@using (Html.BeginForm("PostParent", "Home", FormMethod.Post, new {@class = "form-horizontal", role = "form"}))
{
@Html.LabelFor(x => x.Name)
@Html.TextBoxFor(x => x.Name)
}
我只能添加原始类型的字段,但不能添加对象。
我真的很感激任何帮助!
答案 0 :(得分:10)
为此你可以使用 Html.BeginCollectionItem https://www.nuget.org/packages/BeginCollectionItem/
你可以做的是拥有一个主表格视图并将Parent
模型传递给它,因为这将代表父,那么你需要一行代表一个孩子,你可以调用它{{ 1}}
因此,对于Parent,我们正在创建ChildRow.cshtml
View,我们将传递父模型。
Create.cshtml
然后这就是ChildRow.cshtml的样子,它会有一个@model Parent
@using(Html.BeginForm())
{
@Html.TextBoxFor(m => m.Name)
<table id="children">
<tbody>
<!-- This here will display the Child Row for existing Rows in the Parent model -->
@foreach (var child in Model.Children )
{
@Html.Partial("ChildRow", child)
}
</tbody>
</table>
<button type="button" id="addChild">Add Child</button>
<button type="submit"> Save</button>
}
模型。
注意:您必须将IsDeleted属性添加到子模型,这将帮助您在控制器中 - 查看Child是否被删除。
Child
现在,当单击按钮@model Child
@using (Html.BeginCollectionItem("Children"))
{
<tr>
<td>
@Html.HiddenFor(m => m.IsDeleted, new { data_is_deleted = "false" })
@Html.HiddenFor(m => m.ChildId)
@Html.TextBoxFor(m => m.Name )
</td>
<td>
<span class="glyphicon glyphicon-trash action-icon" data-action="removeItem"></span>
</td>
<tr>
}
时,您必须在表的末尾添加一行。
为此,您将在Controller中创建一个新动作:
Add Child
然后将此jQuery添加到 public ActionResult AddChild()
{
return PartialView("Child", new Child());
}
Create.cshtml
这将在表中附加一个新的子行
如果你想在同一页面上删除,你也必须隐藏/禁用该行,因为你可以添加这个jQuery:
$("#addChild").on("click", function () {
$.ajax({
url: '@Url.Action("AddChild", "YourController")'
}).success(function (partialView) {
$('#children> tbody:last-child').append(partialView);
});
});
然后当您回到控制器时,您将看到模型中的儿童列表。
$('body').on("click", '*[data-action="removeItem"]', function (e) {
e.stopPropagation();
var btn = $(this);
var row = btn.closest('tr');
var firstCell = $(row.find('td')[0]);
var checkBox = firstCell.find('*[data-is-deleted]');
var checkBoxVal = checkBox.val();
if (checkBoxVal === 'False' || checkBox.val() === 'false') {
checkBox.val('true');
row.find('td').find('input, textarea, select').attr('readonly', 'readonly');
} else {
checkBox.val('false');
row.find('td').find('input, textarea, select').attr("readonly", false);
}
});
你必须为GrandChildren做类似的事情。
答案 1 :(得分:2)
我认为你需要一个通常的标准<input/>
,你应该从HTML5中知道。
如果我理解正确,您希望将数据从视图传递到Controller。现在,您需要在您创建的表单中使用一个按钮。
您需要/应该通过将模型数据从视图传递到Controller来调用Controller。 @Html.ActionLink()
是<Input>
表单中的这样的东西应该可以解决问题:
@Html.ActionLink("Click here to pass", "ActionName", new { ParameterNameOfTheController = Model })
这些东西背后的逻辑应该在Controller中发生。 我希望这可以帮到你。
答案 2 :(得分:2)
我做了一个与您的场景相关的项目。但是,我找不到剃须刀的解决方案。所以我最终使用SheepIt jquery插件来动态添加字段。
https://github.com/mdelrosso/sheepit
确保你坚持使用asp mvc理解的id和name模式。
<input class="form-control text-box single-line" id="sheepItForm_#index#__Field" name="sheepItForm[#index#].Field" type="text" value="" />
<span class="field-validation-valid text-danger" data-valmsg-for="sheepItForm[0].Field" data-valmsg-replace="true"></span>
&#13;
希望这有帮助!