我的问题是:
假设我有一个父模型,它有许多子模型(一对多)。
父模型
public class Parent
{
public int ID {get; set;}
public string Name {get; set;}
public virtual Icollection<Child> Child {get: set:}
}
儿童模特
public class Child
{
public int ID {get; set;}
public string Name {get; set;}
public int ParentID {get; set;}
public virtual Parent parent {get: set:}
}
我有一个“创建”视图(通过ParentController),我希望用户在同一视图中说明他想要为该特定父创建多少个孩子。 (点击“添加儿童”并获取儿童创建部分视图。
我认为会发生这种情况的方法是使用子视图的局部视图,并在父/创建视图中使用ajax调用它,然后获取输入并将其保存在父创建(后)视图中,但是我不知道如何完成这件事。
这个链接最接近我想要的,但由于某种原因它不适合我。
http://www.itorian.com/2013/04/nested-collection-models-in-mvc-to-add.html
答案 0 :(得分:0)
使用AJAX加载部分不是处理此方案的最佳方式。特别是,在使用集合时,您的字段名称需要以ListProperty[index].Property
的格式结束,以便模型绑定器正确解释发布数据。如果只为Child
的实例呈现部分表单,则您的字段名称将只是属性,而不包含父项列表属性名称或正确索引的任何上下文。渲染字段现有实例时,您只需使用for
循环:
@for (var i = 0; i < Model.Child.Count(); i++)
{
@Html.EditorFor(m => m.Child[i].Name)
...
}
根据m.Child[i].Name
的上下文,Razor可以生成正确的字段名称。但是,由于您通过JavaScript在客户端添加了新条目,因此没有与Razor合作。
因此,一种更好的方法是使用某种JS库,它允许与UI进行数据绑定并支持模板化。在大多数情况下,我使用Knockout.js作为这种东西,但Angular或类似Backbone的东西也可以。只要使用适合你的任何东西。
例如,使用Knockout,我实际上可以构建一个客户端&#34;视图模型&#34;用于我的MVC视图模型的JSON编码版本的JavaScript:
var data = Html.Raw(Json.Encode(Model));
var MyViewModel = function (data) {
var self = ko.mapping.fromJS(data);
// additional observables, etc.
return self;
}
var viewModel = MyViewModel(data);
ko.applyBindings(viewModel);
有了这个,我可以实例化一个JS数据结构,它实际上有一个子列表,我可以添加或删除它们来动态地影响页面上的HTML。
<div data-bind="template: { name: 'ChildTemplate', foreach: Child }"></div>
<script type="text/html" id="ChildTemplate">
<input type="text" data-bind="value: Name, attr: { name: 'Child[' + $index() + '].Name' }">
<!-- other fields -->
</script>
然后,Knockout会自动为该列表中的每个子项呈现该模板中的所有HTML集。
在如何添加新子项,处理子项的可观察项等方面,还有更多内容,但很多都取决于您最终使用的库。我在这里真正做的只是说明如何使用JavaScript基本上使用客户端视图模型和一些模板将正确索引的项目动态添加到页面。与使用AJAX拼凑一些解决方案来获取一些呈现的HTML相比,这将变得更加容易和强大。