我正在用C#ASP.NET MVC4(Razor引擎)编程。我需要创建一个局部视图并在多个地方重用它。问题是视图是一个表单,在某些情况下我需要将它与ViewModel一起使用。我的问题是模型绑定将如何工作,因为在ViewModel中它将是属性的属性。例如:
public class PersonModel
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
public class OfficeViewModel
{
public PersonModel Person { get; set; }
// other properties
}
PersonModel的部分视图是:
@model SomeNameSpace.PersonModel
@Html.TextBoxFor(m => m.FirstName)
@Html.TextBoxFor(m => m.LastName)
渲染此视图时,它看起来像这样:
<input type="textbox" id="FirstName" name="FirstName" />
<input type="textbox" id="LastName" name="LastName" />
现在我想在OfficeViewModel中使用相同的视图。在这种情况下,我会在我的Office视图中执行此操作:
@{ Html.RenderPartial("Person", Model.Person); }
渲染此局部视图时,它将如上所示进行渲染。如果我不重用该视图,我的Office视图将如下所示:
@model SomeNameSpace.OfficeViewModel
@Html.TextBoxFor(m => m.Person.FirstName)
@Html.TextBoxFor(m => m.Person.LastName)
那将呈现为:
<input type="textbox" id="Person_FirstName" name="Person.FirstName" />
<input type="textbox" id="Person_LastName" name="Person.LastName" />
请注意 name 属性如何具有 Person 前缀属性。因此,如果我使用RenderPartial选项并传入Model.Person,模型绑定器是否知道在OfficeViewModel中绑定 FirstName 和 LastName 的位置?
如果模型绑定器足够智能以检查属性的属性,那么当我在OfficeViewModel中有 ManagerModel 和 EmployeeModel 并且它们都具有名为FirstName的属性时会发生什么和姓氏?
我希望我已经清楚了,并提前感谢。
答案 0 :(得分:4)
不幸的是,在这种情况下,Html.RenderPartial不会传递提供正确字段名称所需的信息。
如果您想以这种方式重用部分视图,请查看使用带有Html.EditorFor的编辑器模板。与其他*一样*对于助手,EditorFor采用lambda表达式,允许它继承传递给模板的属性的名称。
答案 1 :(得分:2)
RenderPartial
无法理解。虽然您可以编写一个自定义帮助程序来处理该问题:
public static MvcHtmlString PartialFor<TModel, TProperty>(this HtmlHelper<TModel> helper, System.Linq.Expressions.Expression<Func<TModel, TProperty>> expression, string partialViewName)
{
string name = ExpressionHelper.GetExpressionText(expression);
object model = ModelMetadata.FromLambdaExpression(expression, helper.ViewData).Model;
var viewData = new ViewDataDictionary(helper.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo
{
HtmlFieldPrefix = name
}
};
return helper.Partial(partialViewName, model, viewData);
}
在视图中使用它:
@Html.PartialFor(x => x.Person, "Person")
答案 2 :(得分:0)
在这里找到答案:https://stackoverflow.com/a/4807655/78739
基本上我需要设置 ViewData.TemplateInfo.HtmlFieldPrefix 。
所以我在PersonModel中添加了一个属性,并将其命名为 HtmlFieldPrefix 。例如:
public class PersonModel
{
public string HtmlFieldPrefix { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
然后在我的部分视图中我这样做:
@model SomeNameSpace.PersonModel
@{
ViewData.TemplateInfo.HtmlFieldPrefix = Model.HtmlFieldPrefix;
}
@Html.TextBoxFor(m => m.FirstName)
@Html.TextBoxFor(m => m.LastName)
在我的控制器操作中,我可以这样做:
model.HtmlFieldPrefix = "Person";
return View("_Person", model);
现在我的渲染视图将如下所示:
<input type="textbox" id="Person_FirstName" name="Person.FirstName" />
<input type="textbox" id="Person_LastName" name="Person.LastName" />
如果我将model.HtmlFieldPrefix保留为null,则视图将呈现为:
<input type="textbox" id="FirstName" name="FirstName" />
<input type="textbox" id="LastName" name="LastName" />
所以这解决了我的问题,并允许我使用ViewModels的部分视图。