3

当使用 Razor 为具有子模型的复杂模型渲染表单时,我们通常会使用局部视图来渲染子模型。

简单示例模型:

public class BlogPost
{
    public string Content { get; set; }
    public List<Comment> Comments { get; set; }
}

public class Comment
{
    public string Content { get; set; }
}

BlogPost.cshtml:

@model BlogPost

@Html.TextAreaFor(x => x.Content)

@for (int i = 0; i < Model.Comments.Count; i++)
{
    @Html.Partial('Comment', Model.Comments[i])
}

评论.cshtml:

@model Comment

@Html.TextAreaFor(x => x.Content)

现在解决这个问题:

假设我们想将所有字段的值发送到BlogPost作为参数的控制器操作。这些字段将被发布回控制器,如下所示:

Content=The+content+of+BlogPost&Content=The+first+Comment&Content=The+second+Comment

但是我们需要让 MVC 将它们正确映射到BlogPost视图模型,我们需要这个命名约定:

Content=The+content+of+the+BlogPost&Comments[0].Content=The+first+Comment&Comments[1].Content=The+second+Comment

如何以干净的方式实现这一目标?我们只能想到两种似乎都会影响设计的方法:

  • 我们将BlogPost作为模型传递给局部视图,以便我们可以像这样定义文本区域@Html.TextAreaFor(x => x.Comments[i].Content):但这意味着我们将用于注释的局部视图耦合到父视图模型 - 您可以考虑在不同的上下文中使用相同的局部视图的场景,如果局部视图依赖于父视图模型,这是不可能的。此外,i必须以某种方式将其传递给局部视图。
  • 或者我们回退到用字符串明确定义每个字段的名称:@Html.TextArea(ViewBag.Prefix + ".Content")

有没有办法告诉局部视图将某个前缀应用于所有字段名称?

4

1 回答 1

2

奇科多罗,

如果您创建和 EditorFor 类型的模板Comment,mvc 将为您处理所有这些。但是,这只适用于数据库中已经存在行的情况。来自 SO 的示例:

在剃须刀中提交父母和孩子

如果您需要即时创建新行,那么您将不得不使用一些技巧来允许字段按要求操作。我使用了 steven sandersons 网站上的一篇文章,它允许您在运行时添加集合项目,并且仍然保留不显眼的验证等。请参阅这个 SO 问题和相关文章参考:

编辑可变长度列表,带有表格的 ASP.NET MVC 3 样式

于 2012-07-13T16:29:50.640 回答