public Parentviewmodel { public int Id { get; set; } public string Name { get; set; } public List<Childviewmodel> Child { get; set; } } public Childviewmodel { public int Id { get; set; } public string FirstName { get; set; } }
在我的一个视图中,我将Parentviewmodel作为模型传递,然后使用
<%: Html.EditorFor(x => x) %>
当用户单击一个按钮时,我通过Ajax调用一个动作来加载一个局部视图,该视图包含一个Child的集合:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Child>>" %> <%: Html.EditorFor(x => x) %>
我遇到的问题是由Child自定义模板创建的表单不使用DefaultModelBinder使用的命名约定.
即字段名称(由Ajax加载时):
[0].FirstName
代替:
Child[0].FirstName
所以我的控制器中的编辑操作:
[HttpPost] public virtual ActionResult Edit(int id,FormCollection formValues) { Parentviewmodel parent = new Parentviewmodel(); UpdateModel(parent); return View(parent); }
从提交的表单重新创建Parentviewmodel不起作用.
解决方法
所以,首先使用模型,这里没什么不同..
public class Parentviewmodel { public int Id { get; set; } public string Name { get; set; } public List<Childviewmodel> Child { get; set; } } public class Childviewmodel { public int Id { get; set; } public string FirstName { get; set; } }
父部分视图 – 这将采用Parentviewmodel的实例
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Parentviewmodel>" %> <h2>Parent</h2> <%: Html.TextBox("parent.Name",Model.Name) %> <%: Html.Hidden("parent.Id",Model.Id) %> <% foreach (Childviewmodel childviewmodel in Model.Child) { Html.RenderPartial("Child",childviewmodel); } %>
子部分视图 – 这需要Childviewmodel的单个实例
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Childviewmodel>" %> <h3>Child</h3> <%: Html.Hidden("parent.Child.index",Model.Id) %> <%: Html.Hidden(string.Format("parent.Child[{0}].Id",Model.Id),Model.Id)%> <%: Html.TextBox(string.Format("parent.Child[{0}].FirstName",Model.FirstName) %>
此时需要注意的是索引值是用于计算列表中唯一记录的值.这不需要是增量值.
那么,你怎么称呼这个?好吧,在Index动作中,它将显示需要传入的数据.我已经设置了一些演示数据并将它在ViewData字典中返回到索引视图.
控制器动作……
public ActionResult Index() { ViewData["Message"] = "Welcome to ASP.NET MVC!"; ViewData["Parent"] = GetData(); return View(); } private Parentviewmodel GetData() { var result = new Parentviewmodel { Id = 1,Name = "Parent name",Child = new List<Childviewmodel> { new Childviewmodel {Id = 2,FirstName = "first child"},new Childviewmodel {Id = 3,FirstName = "second child"} } }; return result; }
在现实世界中,您可以称之为数据服务等.
最后是Index视图的内容:
<form action="<%: Url.Action("Edit") %>" method="post"> <% if (ViewData["Parent"] != null) { %> <% Html.RenderPartial("Parent",ViewData["Parent"]); %> <% } %> <input type="submit" /> </form>
保存
那么现在我们有数据显示我们如何将其恢复为动作?那么这是默认模型绑定器将在相对复杂的结构中为简单数据类型执行的操作.因此,您可以将要发布的操作的基本格式设置为:
[HttpPost] public ActionResult Edit(Parentviewmodel parent) { }
这将为您提供原始ID(来自隐藏字段)的更新详细信息,以便您可以根据需要进行更新/编辑.
通过Ajax的新孩子
你在问题中提到通过ajax加载自定义模板,你的意思是如何让用户选择在没有回发的情况下添加另一个孩子吗?
如果是这样,你会做这样的事……
添加操作 – 需要一个将返回新的Childviewmodel的操作
[HttpPost] public ActionResult Add() { var result = new Childviewmodel(); result.Id = 4; result.FirstName = "** to update **"; return View("Child",result); }
为了方便演示,我给它一个id.
然后,您需要一种调用代码的方法,因此您需要更新的唯一视图是主索引视图.这将包括用于获取操作结果的javascript,用于调用代码的链接以及要附加到的html的目标HTML标记.另外,不要忘记在母版页或视图顶部添加对jQuery的引用.
索引视图 – 已更新!
<script type="text/javascript"> function add() { $.ajax( { type: "POST",url: "<%: Url.Action("Add","Home") %>",success: function(result) { $('#newchild').after(result); },error: function(req,status,error) { } }); } </script> <form action="<%: Url.Action("Edit") %>" method="post"> <% if (ViewData["Parent"] != null) { %> <% Html.RenderPartial("Parent",ViewData["Parent"]); %> <% } %> <div id="newchild"></div> <br /><br /> <input type="submit" /> <a href="#" onclick="JavaScript:return add();">add child</a> </form>
这将调用add动作,并在返回到提交按钮上方的newChild div时附加响应.
我希望长篇文章很有用.
请享用 :-)