Asp.net mvc 我可以在具有添加/删除功能的MVC4视图中显示复杂对象的列表吗?
我已经在这个问题上绞尽脑汁好几天了,现在还想不出来。我需要创建一个视图,允许用户添加和删除复杂的层次对象。假例子: 型号Asp.net mvc 我可以在具有添加/删除功能的MVC4视图中显示复杂对象的列表吗?,asp.net-mvc,asp.net-mvc-4,partial-views,nested,mvc-editor-templates,Asp.net Mvc,Asp.net Mvc 4,Partial Views,Nested,Mvc Editor Templates,我已经在这个问题上绞尽脑汁好几天了,现在还想不出来。我需要创建一个视图,允许用户添加和删除复杂的层次对象。假例子: 型号 public class ParentModel { public int ParentId { get; set; } public string ParentText { get; set; } public IList<ChildModel> Children { get; set; } } public class ChildMo
public class ParentModel
{
public int ParentId { get; set; }
public string ParentText { get; set; }
public IList<ChildModel> Children { get; set; }
}
public class ChildModel
{
public int ChildId { get; set; }
public string ChildText { get; set; }
public IList<GrandChildModel> GrandChildren { get; set; }
}
public class GrandChildModel
{
public int GrandChildId { get; set; }
public string GrandChildText { get; set; }
}
除非我添加孙子并提交表单,否则此视图工作正常,在这种情况下,它不会绑定到孙子模型的列表。职位空缺:
因此,我尝试使用模型的编辑器模板
,只是想看看它是否有效。这对于简单地显示对象非常有用,但我不知道如何将孙子添加到列表中并在编辑器模板中显示它。我还尝试嵌套加载了$.ajax
调用的部分视图,但这变成了一场噩梦
在实际应用程序中,层次结构比本例更深,每个连续的子对象都需要具有此添加/删除功能。当用户每次想要添加或删除对象时,如果没有表单的完整帖子,这是可能的吗?使用上述示例中的方法,是否可以让新添加的孙子绑定到POST上的IList
?或者,是否有一种方法可以在客户端添加一个对象,并将其显示在编辑器模板中和绑定到POST上的IList
?如果两种选择都不是正确的方法,那么正确的方法是什么
更新
我已经想出了一些可能有效的黑客方法,但我仍然很想知道是否有更简单的方法来做到这一点。我将上述视图代码更改为:
@model EditorTemplateCollectiosns.Models.ParentModel
@using (@Html.BeginForm())
{
<div>
@Html.TextBoxFor(m => m.ParentId)
@Html.TextBoxFor(m => m.ParentText)<br/>
Children:<br/>
<button type="button" id="addChild" onclick="addChildRow()">Add Child</button>
<table id="children">
<tbody class="childTableBody">
@for (var i = 0; i < Model.Children.Count; i++)
{
<tr>
<td colspan="3">Child @i</td>
</tr>
<tr class="childInfoRow">
<td>
@Html.TextBoxFor(m => Model.Children[i].ChildId)
</td>
<td>
@Html.TextBoxFor(m => Model.Children[i].ChildText)
</td>
<td>
<button type="button" id="removeChild@(i)" onclick="removeChildRow(this)">Delete</button>
</td>
</tr>
<tr>
<td colspan="3">
Grandchildren:<br/>
<button type="button" id="addGrandchild@(i)" onclick="addGrandchildRow(this)">Add Grandchild</button>
<table id="grandChildren@(i)">
<tbody>
@for (var j = 0; j < Model.Children[i].GrandChildren.Count; j++)
{
<tr>
<td>@Html.TextBoxFor(m => @Model.Children[i].GrandChildren[j].GrandChildId)</td>
<td>@Html.TextBoxFor(m => @Model.Children[i].GrandChildren[j].GrandChildText)</td>
<td><button type="button" id="removeGrandchild@(i)_@(j)" onclick="removeGrandchildRow(this)">Delete</button></td>
</tr>
}
</tbody>
</table>
</td>
</tr>
}
</tbody>
</table>
</div>
<input type="submit" value="submit"/>
}
@model editorTemplateCollectionsNS.Models.ParentModel
@使用(@Html.BeginForm())
{
@Html.TextBoxFor(m=>m.ParentId)
@Html.TextBoxFor(m=>m.ParentText)
儿童:
添加子项
@对于(var i=0;iModel.Children[i].ChildId)
@Html.TextBoxFor(m=>Model.Children[i].ChildText)
删除
孙辈:
加孙
@对于(var j=0;j@Model.Children[i].孙子[j].孙子ID)
@Html.TextBoxFor(m=>@Model.Children[i].孙子[j].孙子文本)
删除
}
}
}
然后,我添加了以下javascript。我不能使用类和jQuery click事件处理程序在每次添加/删除操作似乎不正常后重新绑定处理程序:
<script type="text/javascript">
function addChildRow() {
var newRowIndex = $("#children tr.childInfoRow").length;
var newRow = '<tr><td colspan="3">Child ' + newRowIndex + '</td></tr><tr class="childInfoRow"><td><input type="text" name="Children[' + newRowIndex + '].ChildId" /></td>' +
'<td><input type="text" name="Children[' + newRowIndex + '].ChildText" /></td>' +
'<td><button type="button" id="removeChild' + newRowIndex + '" onclick="removeChildRow(this)">Delete</button></td></tr>' +
'<td colspan="3">Grandchildren: <br/><button type="button" id="addGrandchild' + newRowIndex + '" onclick="addGrandchildRow(this)">Add Grandchild</button>' +
'<table id="grandChildren' + newRowIndex + '"><tbody></tbody></table></td></tr>';
$("#children tbody.childTableBody:last").append(newRow);
}
function addGrandchildRow(elem) {
var childIndex = $(elem).attr('id').replace('addGrandchild', '');
var newRowIndex = $("#grandChildren" + childIndex + " tr").length;
var newRow = '<tr><td><input type="text" name="Children[' + childIndex + '].GrandChildren[' + newRowIndex + '].GrandChildId" /></td>' +
'<td><input type="text" name="Children[' + childIndex + '].GrandChildren[' + newRowIndex + '].GrandChildText" /></td>' +
'<td><button type="button" id="removeGrandchild' + childIndex + '_' + newRowIndex + '" onclick="removeGrandchildRow(this)">Delete</button></td></tr>';
$("#grandChildren" + childIndex + " tbody:last").append(newRow);
}
function removeChildRow(elem) {
$(elem).closest('tr').prev().remove();
$(elem).closest('tr').next().remove();
$(elem).closest('tr').remove();
}
function removeGrandchildRow(elem) {
$(elem).closest('tr').remove();
}
</script>
函数addChildRow(){
var newRowIndex=$(“#childrentr.childInfoRow”).length;
var newRow='Child'+newRowIndex+''+
'' +
“删除”+
'孙辈:
添加孙辈'+
'';
$(“#childrentbody.childTableBody:last”).append(newRow);
}
函数行(elem){
var childIndex=$(elem).attr('id').replace('add孙子','');
var newRowIndex=$(“#孙子辈”+childIndex+tr”)。长度;
var newRow=''+
'' +
“删除”;
$(“#孙辈”+childIndex+“tbody:last”).append(newRow);
}
函数删除Childrow(elem){
$(elem).closest('tr').prev().remove();
$(elem).closest('tr').next().remove();
$(elem).最近('tr').remove();
}
函数removeGrandchildRow(elem){
$(elem).最近('tr').remove();
}
到目前为止,这是可行的,数组值似乎绑定正确。然而,我不太喜欢在两个表中都添加一行所需的大量内容。有谁有更好的主意吗?如果只使用一种型号,这将更容易实现。与ParentModel不同,ChildModel和孙子Model只是有一个HierarchyChalPersonModel
这样,您只需要一个视图和一个自定义编辑器模板。Ajax会有点困难,但不是您描述的后勤噩梦
更新:添加示例
public class ParentModel
{
public int ParentId { get; set; }
public string ParentText { get; set; }
public IList<ChildModel> Children { get; set; }
}
public class ChildModel
{
public int ChildId { get; set; }
public string ChildText { get; set; }
public IList<GrandChildModel> GrandChildren { get; set; }
}
public class GrandChildModel
{
public int GrandChildId { get; set; }
public string GrandChildText { get; set; }
}
人物模型:
public class Person
{
public int Id { get; set; }
public string Text { get; set; }
public List<Person> Children { get; set; }
}
公共类人物
{
公共int Id{get;set;}
公共字符串文本{get;set;}
公共列表子项{get;set;}
}
假存储库:
public static List<Person> PersonCollection { get; set; }
public static Person FindById(int id, List<Person> list = null)
{
if (list == null)
list = PersonCollection;
foreach (var person in list)
{
if (person.Id == id)
return person;
if (person.Children != null)
return FindById(id, person.Children);
}
return null;
}
公共静态列表PersonCollection{get;set;}
public static Person FindById(int-id,List=null)
{
if(list==null)
列表=个人收集;
foreach(列表中的var人员)
{
if(person.Id==Id)
返回人;
if(person.Children!=null)
返回FindById(id,person.Children);
}
返回null;
}
我在编辑我的原始帖子时使用了解决方案。这是一个吨的javascript,测试花费了很长时间,但它工作正常,是我能找到的唯一方法。如果有人对完整的解决方案感兴趣,请在此处发表评论,我将发布它。我不关心存储库代码,但是