Asp.net mvc MVC can';在EditorFor子对象中使用时,t重写EditorTemplate名称
我试图使用EditorTemplate在父视图的表中显示子集合。我遇到的问题是,只有当模板的名称与子类的名称完全相同时,这似乎才起作用。当我尝试使用名称稍有不同的模板,并将该名称作为templateName参数传递给EditorFor时,会出现运行时错误。我希望我能在同一个儿童收藏中使用不同的儿童编辑器或模板,以达到不同的目的。 以下是一个简化示例: 型号:Asp.net mvc MVC can';在EditorFor子对象中使用时,t重写EditorTemplate名称,asp.net-mvc,mvc-editor-templates,Asp.net Mvc,Mvc Editor Templates,我试图使用EditorTemplate在父视图的表中显示子集合。我遇到的问题是,只有当模板的名称与子类的名称完全相同时,这似乎才起作用。当我尝试使用名称稍有不同的模板,并将该名称作为templateName参数传递给EditorFor时,会出现运行时错误。我希望我能在同一个儿童收藏中使用不同的儿童编辑器或模板,以达到不同的目的。 以下是一个简化示例: 型号: public class Customer { int id { get; set; } public string name {
public class Customer
{
int id { get; set; }
public string name { get; set; }
public List<Order> Orders { get; set; }
}
public class Order
{
public int id { get; set; }
public DateTime orderdate { get; set; }
public decimal amount { get; set; }
public Customer customer { get; set; }
}
public ActionResult Index()
{
Customer customer = new Customer() {id = 1, name = "Acme Corp.", Orders = new List<Order>()};
customer.Orders.Add(new Order() {id = 1, orderdate = DateTime.Now, amount = 100M});
customer.Orders.Add(new Order() { id = 2, orderdate = DateTime.Now, amount = 200M });
return View(customer);
}
@model TemplateTest.Customer
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Customer</title>
</head>
<body>
<div>
@Html.EditorFor(Model=>Model.name)
<table>
<thead>
<tr>
<th>Order ID</th>
<th>Order Date</th>
<th>Amount</th>
</tr>
</thead>
@Html.EditorFor(Model=>Model.Orders)
</table>
</div>
</body>
</html>
当我再次运行它时,会出现以下异常:
传递到字典的模型项的类型为“System.Collections.Generic.List`1[TemplateTest.Order]”,但此字典需要“TemplateTest.Order”类型的模型项
你知道为什么EditorFor不使用我在“templateName”参数中指定的模板“OrderList”吗?否则,这个参数是干什么的
TL;DR>命名模板不适用于集合,请使用foreach循环来解决它-有关原因的详细信息以及示例,请参见下文
你说: 知道为什么EditorFor不使用模板“OrderList”吗 在“templateName”参数中指定?否则,这是什么 争论
EditorFor
实际上正在使用您指定的模板OrderList
,但是您偶然发现了一些非常令人困惑的东西。一些研究发现了很多提示,但我在这篇文章中找到了真正的细节:
简言之,实际情况是,默认情况下有效:@Html.EditorFor(Model=>Model.Orders)
实际上是按照约定在过渡期间调用MVC默认模板,但这一点并不明显
试着这样想:
在工作版本中,您将传入一个类型列表
,其中引用了模型.订单
(多个订单),但模板是使用订单
模型指定的(单个,而不是多个)
有趣。为什么这样做会奏效呢?乍一看,它似乎应该而不是奏效。但它确实奏效,因为幕后发生了什么
摘自上述帖子:
当您使用@Html.EditorFor(c=>c.Orders)
MVC约定选择
IEnumerable的默认模板。此模板是MVC框架的一部分,它的作用是为生成Html.EditorFor()
枚举中的每个项。然后该模板生成
分别为列表中的每个项目设置适当的编辑器模板
-在您的例子中,它们都是订单的实例,因此每个项目都使用订单模板
这就是魔法,它很方便,但因为这是按照惯例发生的,基本上是对我们隐藏的,所以在我看来,这是混乱的根源
现在,当您尝试执行相同的操作,但通过显式地将EditorFor
设置为使用特定的编辑器模板OrderList
,使用命名模板时,最终会将该编辑器模板传递给整个枚举—这就是您发布的错误的来源
换句话说,失败的案例设法跳过了工作案例中的“魔法”部分,这就是它失败的原因。但是,从语义上看,它看起来不错,对吧?有点混乱
工作案例:
失败案例:
有许多方法可以消除错误,但其中许多方法都有问题,因为它们导致HTML控件的呈现方式会阻止您通过POST.uhg上的索引来处理单个控件。(注意:工作案例确实按照预期正确呈现HTML)
要正确呈现HTML控件,似乎必须使用常规的for
循环(而不是foreach
),并将每个Order
对象传递给自定义模板(我称之为OrderEditorTemplateDefault
)
@for(int i=0;iModel.Orders[i],“OrderEditorTemplateDefault”)
}
你的部分问题指出:
我希望我可以使用不同的儿童编辑或模板来处理不同的问题
具有相同子集合的目的
您可以通过在循环中引入一个条件并在那里选择备用模板来实现这一点(对于整个列表或基于顺序,这取决于您如何编写条件)
@for(int i=0;iModel.Orders[i],“OrderEditorTemplateDefault”)
}否则{
@EditorFor(c=>Model.Orders[i],“OrderEditorTemplateALTERNATE”)
}
}
抱歉这么冗长。希望能有帮助。嘿,我注意到了另一件事。你将
颜色:蓝色设置为调试辅助的地方实际上不会显示出来。我太累了,无法解释原因,但如果你将其更改为背景色:蓝色
,我想它会满足你的需要。;)抱歉编辑你的帖子大卫,我只是我想在一开始就做一个简洁的陈述可能会有帮助。如果可以的话,我会给你投票10亿次。这对你来说意味着很多。如果你能管理5亿次投票,那也会很酷。哇,这是一个多么深思熟虑和清晰的回答!非常感谢,这将为我节省大量额外的浪费时间来解决这个问题。我读了很多关于这个主题的帖子,但没有遇到你提到的那篇。我过去曾使用过for循环,但有几篇帖子说最好使用带模板的编辑器,这确实有助于代码更清晰,并将脚本从标记中去掉。我可以尝试创建自己的EditorForColle
@model TemplateTest.Order
<tr>
<td>@Html.DisplayFor(Model=>Model.id)</td>
<td style="color:blue">@Html.EditorFor(Model=>Model.orderdate)</td>
<td>@Html.EditorFor(Model=>Model.amount)</td>
</tr>
@Html.EditorFor(Model=>Model.Orders, "OrderList")
your call default MVC template your template
@Html.EditorFor( Model => Model.Orders) IEnumerable template Order template
your call your template
@Html.EditorFor(Model=>Model.Orders, "OrderList") OrderList template ERROR!!!
@for (int i = 0; i < Model.Orders.Count ; i++)
{
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateDefault")
}
@for (int i = 0; i < Model.Orders.Count ; i++) {
if (someCondition) {
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateDefault")
} else {
@Html.EditorFor(c => Model.Orders[i], "OrderEditorTemplateALTERNATE")
}
}