假设我有类似视图模型
public class AnotherViewModel
{
public string Name { get; set; }
}
public class MyViewModel
{
public string Name { get; set; }
public AnotherViewModel Child { get; set; }
public AnotherViewModel Child2 { get; set; }
}
在视图中我可以呈现的局部用
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
在部分我会做
<%= Html.TextBox("Name", Model.Name) %>
or
<%= Html.TextBoxFor(x => x.Name) %>
然而,问题是,这两个将呈现NAME =“姓名”,而我需要的名字=“Child.Name”为了让模型绑定才能正常工作。 或者,名称=“Child2.Name”当我渲染使用相同的局部视图的第二属性。
如何让我的局部视图自动识别所需要的前缀? 我可以把它作为一个参数,但这是太不方便了。 当我想例如递归使其这更是雪上加霜。 有没有一种方法来呈现一个前缀,或者甚至更好的局部视图,与调用lambda表达式,这样的自动reconition
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
会自动添加正确的“孩子”。 前缀生成的名称/ ID字符串?
我可以接受任何的解决方案,其中包括3-第三方视图引擎和库 - 实际上我用星火视图引擎(我“解决”使用其宏问题)MvcContrib和,但没有找到一个解决方案在那里。 XForms的,InputBuilder,MVC V2 - 任何工具/洞察力提供此功能的将是巨大的。
目前,我认为这个编码自己,但它似乎是在浪费时间,我无法相信这个小东西是不是已经实现。
很多手册可能解决方案的存在,所有的人都欢迎。 例如,我可以强制我的泛音是基于离IPartialViewModel <T> {公共前缀串; T型车; }。 但我宁愿更喜欢一些现有/认可的解决方案。
更新:有没有回答类似的问题在这里 。
Answer 1:
您可以通过此扩展HTML辅助类:
using System.Web.Mvc.Html
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(model => model.Child, "_AnotherViewModelControl") %>
你会看到一切正常!
Answer 2:
到目前为止,我正在寻找我发现这个最近的文章同样的事情:
http://davybrion.com/blog/2011/01/prefixing-input-elements-of-partial-views-with-asp-net-mvc/
<% Html.RenderPartial("AnotherViewModelControl", Model.Child, new ViewDataDictionary
{
TemplateInfo = new System.Web.Mvc.TemplateInfo { HtmlFieldPrefix = "Child1" }
})
%>
Answer 3:
我的回答的基础上,马哈茂德Moravej的答案,包括伊万·勒蒂文的评论。
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;
StringBuilder htmlFieldPrefix = new StringBuilder();
if (helper.ViewData.TemplateInfo.HtmlFieldPrefix != "")
{
htmlFieldPrefix.Append(helper.ViewData.TemplateInfo.HtmlFieldPrefix);
htmlFieldPrefix.Append(name == "" ? "" : "." + name);
}
else
htmlFieldPrefix.Append(name);
var viewData = new ViewDataDictionary(helper.ViewData)
{
TemplateInfo = new System.Web.Mvc.TemplateInfo
{
HtmlFieldPrefix = htmlFieldPrefix.ToString()
}
};
return helper.Partial(partialViewName, model, viewData);
}
编辑:马哈茂德的答案是不正确的嵌套部分呈现。 您需要将新的前缀追加到旧的前缀,只有当它是必要的。 这不是在最新的答案(明确:
Answer 4:
使用MVC2就可以实现这一点。
这里是强类型的视图:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<MvcLearner.Models.Person>" %>
<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
Create
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
<h2>Create</h2>
<% using (Html.BeginForm()) { %>
<%= Html.LabelFor(person => person.Name) %><br />
<%= Html.EditorFor(person => person.Name) %><br />
<%= Html.LabelFor(person => person.Age) %><br />
<%= Html.EditorFor(person => person.Age) %><br />
<% foreach (String FavoriteFoods in Model.FavoriteFoods) { %>
<%= Html.LabelFor(food => FavoriteFoods) %><br />
<%= Html.EditorFor(food => FavoriteFoods)%><br />
<% } %>
<%= Html.EditorFor(person => person.Birthday, "TwoPart") %>
<input type="submit" value="Submit" />
<% } %>
</asp:Content>
下面是子类(必须存储在一个称为EditorTemplates视图目录的子文件夹)的强类型的视图:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<MvcLearner.Models.TwoPart>" %>
<%= Html.LabelFor(birthday => birthday.Day) %><br />
<%= Html.EditorFor(birthday => birthday.Day) %><br />
<%= Html.LabelFor(birthday => birthday.Month) %><br />
<%= Html.EditorFor(birthday => birthday.Month) %><br />
这里是控制器:
public class PersonController : Controller
{
//
// GET: /Person/
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Index()
{
return View();
}
[AcceptVerbs(HttpVerbs.Get)]
public ActionResult Create()
{
Person person = new Person();
person.FavoriteFoods.Add("Sushi");
return View(person);
}
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Person person)
{
return View(person);
}
}
下面是自定义类:
public class Person
{
public String Name { get; set; }
public Int32 Age { get; set; }
public List<String> FavoriteFoods { get; set; }
public TwoPart Birthday { get; set; }
public Person()
{
this.FavoriteFoods = new List<String>();
this.Birthday = new TwoPart();
}
}
public class TwoPart
{
public Int32 Day { get; set; }
public Int32 Month { get; set; }
}
和输出源:
<form action="/Person/Create" method="post"><label for="Name">Name</label><br />
<input class="text-box single-line" id="Name" name="Name" type="text" value="" /><br />
<label for="Age">Age</label><br />
<input class="text-box single-line" id="Age" name="Age" type="text" value="0" /><br />
<label for="FavoriteFoods">FavoriteFoods</label><br />
<input class="text-box single-line" id="FavoriteFoods" name="FavoriteFoods" type="text" value="Sushi" /><br />
<label for="Birthday_Day">Day</label><br />
<input class="text-box single-line" id="Birthday_Day" name="Birthday.Day" type="text" value="0" /><br />
<label for="Birthday_Month">Month</label><br />
<input class="text-box single-line" id="Birthday_Month" name="Birthday.Month" type="text" value="0" /><br />
<input type="submit" value="Submit" />
</form>
现在,这是完整的。 设置在创建后控制器动作来验证一个断点。 不要用列表使用此然而,因为它不会工作。 有关使用EditorTemplates与IEnumerable的更多关于我的问题。
Answer 5:
这是一个老问题,但任何人到达此地寻找一个解决方案,可以考虑使用EditorFor
,如在评论建议https://stackoverflow.com/a/29809907/456456 。 从局部视图移动到编辑模板,请按照下列步骤。
验证您的局部视图势必的ComplexType。
移动您的局部视图到子文件夹EditorTemplates当前视图文件夹,或者为共享的文件夹。 现在,它是一个编辑模板。
改变@Html.Partial("_PartialViewName", Model.ComplexType)
到@Html.EditorFor(m => m.ComplexType, "_EditorTemplateName")
编辑模板是可选的,如果它是复杂类型的唯一模板。
HTML输入元素将自动被命名为ComplexType.Fieldname
。
Answer 6:
PartailFor的asp.net的Core 2万一有人需要它。
public static ModelExplorer GetModelExplorer<TModel, TResult>(this IHtmlHelper<TModel> htmlHelper, Expression<Func<TModel, TResult>> expression)
{
if (expression == null)
throw new ArgumentNullException(nameof(expression));
return ExpressionMetadataProvider.FromLambdaExpression(expression, htmlHelper.ViewData, htmlHelper.MetadataProvider);
}
public static IHtmlContent PartialFor<TModel, TResult>(this IHtmlHelper<TModel> helper, Expression<Func<TModel, TResult>> expression, string partialViewName, string prefix = "")
{
var modelExplorer = helper.GetModelExplorer(expression);
var viewData = new ViewDataDictionary(helper.ViewData);
viewData.TemplateInfo.HtmlFieldPrefix += prefix;
return helper.Partial(partialViewName, modelExplorer.Model, viewData);
}
Answer 7:
我碰到这个问题也和许多痛苦后,我发现它更容易重新设计我的接口,这样我也没必要回发嵌套模型对象。 这迫使我改变接口的工作流程:确定我现在要求用户在两个步骤我梦想做一个的事,但这种新方法的实用性和代码的可维护性现在是更大的价值给我。
希望这有助于一些。
Answer 8:
你可以添加一个助手的需要前缀并弹出它的ViewData的的的RenderPartial。
public static void RenderPartial(this HtmlHelper helper,string partialViewName, object model, string prefix)
{
helper.ViewData["__prefix"] = prefix;
helper.RenderPartial(partialViewName, model);
}
则进一步辅助该串接的ViewData的值
public static void GetName(this HtmlHelper helper, string name)
{
return string.Concat(helper.ViewData["__prefix"], name);
}
所以在视图中...
<% Html.RenderPartial("AnotherViewModelControl", Model.Child, "Child.") %>
在部分...
<%= Html.TextBox(Html.GetName("Name"), Model.Name) %>
Answer 9:
和你一样,我加前缀属性(字符串)我的ViewModels,我在我的模型的约束输入名称追加。 (YAGNI防止下面)
一个更优雅的解决方案可能是拥有该物业的基本视图模型和一些HtmlHelpers是检查视图模型在这个基础派生,如果是追加前缀的输入名称。
希望帮助,
和
Answer 10:
如何调用之前的RenderPartial你做
<% ViewData["Prefix"] = "Child."; %>
<% Html.RenderPartial("AnotherViewModelControl", Model.Child) %>
然后在你的部分你有
<%= Html.TextBox(ViewData["Prefix"] + "Name", Model.Name) %>
文章来源: ASP.NET MVC partial views: input name prefixes