通过 ViewData 将 SelectList 传递到编辑器模板 - 未正确显示
这有点复杂,所以请耐心等待。
假设我有一个控制器编辑操作的示例,其定义如下:
Node nd = _repo.getNode(id);
List<Category> ac = new List<Category>();
ac.AddRange(_repo.getCategories());
SelectList acl = new SelectList(ac, "category_id", "category_name", ac.Where(cat => cat.category_id == nd.category_id).First());
ViewData["category_id"] = acl;
return View(nd);
视图的模板化如下:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Myapp.Models.Node>" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1)
{ %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% }
else
{ %>
<table cellpadding="0" cellspacing="0" border="0">
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
{ %>
<% if (prop.HideSurroundingHtml)
{ %>
<%= Html.Editor(prop.PropertyName) %>
<% }
else
{ %>
<tr>
<td>
<div class="editor-label" style="text-align: right;">
<%= prop.IsRequired ? "*" : ""%>
<%= Html.Label(prop.PropertyName)%>
</div>
</td>
<td>
<div class="editor-field">
<% if (ViewData.Keys.Contains(prop.PropertyName))
{
if ((ViewData[prop.PropertyName]).GetType().Name == "SelectList")
{ %>
<%= Html.DropDownList(prop.PropertyName, (SelectList)ViewData[prop.PropertyName])%>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<%= Html.ValidationMessage(prop.PropertyName, "*")%>
</div>
</td>
</tr>
<% } %>
<% } %>
</table>
<% } %>
因此,模板的作用是为 ViewData["property_name"]存在。
我还为 Node 类的每个属性定义了 DisplayName
元数据属性。
现在,下拉列表显示良好并且已正确填充,但是:
- 始终选择列表中的第一个值,即使 SelectList 选择值谓词很好并且确实设置了正确的值(至少在调试器中)。
- 模板中的 Html.Label 为属性返回正确的 DisplayName,但是当我为它们定义 ViewData 以显示下拉列表时,标签将重置为正常属性名称(即
category_id
而不是 <代码>类别)。
什么给?您能想到任何“更简洁”的方式来完成此功能吗?
It's a bit complicated so bear with me.
Let's say I've got an example of a controller edit action defined like:
Node nd = _repo.getNode(id);
List<Category> ac = new List<Category>();
ac.AddRange(_repo.getCategories());
SelectList acl = new SelectList(ac, "category_id", "category_name", ac.Where(cat => cat.category_id == nd.category_id).First());
ViewData["category_id"] = acl;
return View(nd);
The view is templated like so:
<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Myapp.Models.Node>" %>
<% if (ViewData.TemplateInfo.TemplateDepth > 1)
{ %>
<%= ViewData.ModelMetadata.SimpleDisplayText %>
<% }
else
{ %>
<table cellpadding="0" cellspacing="0" border="0">
<% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForEdit && !ViewData.TemplateInfo.Visited(pm)))
{ %>
<% if (prop.HideSurroundingHtml)
{ %>
<%= Html.Editor(prop.PropertyName) %>
<% }
else
{ %>
<tr>
<td>
<div class="editor-label" style="text-align: right;">
<%= prop.IsRequired ? "*" : ""%>
<%= Html.Label(prop.PropertyName)%>
</div>
</td>
<td>
<div class="editor-field">
<% if (ViewData.Keys.Contains(prop.PropertyName))
{
if ((ViewData[prop.PropertyName]).GetType().Name == "SelectList")
{ %>
<%= Html.DropDownList(prop.PropertyName, (SelectList)ViewData[prop.PropertyName])%>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<% }
else
{ %>
<%= Html.Editor(prop.PropertyName)%>
<% } %>
<%= Html.ValidationMessage(prop.PropertyName, "*")%>
</div>
</td>
</tr>
<% } %>
<% } %>
</table>
<% } %>
So, what the template does is display a dropdown list for every property for which ViewData["property_name"]
exists.
I've also defined DisplayName
metadata attributes for every property of my Node class.
Now, the dropdown lists display fine and are being populated correctly, but:
- The first value from a list is always selected, even though the SelectList selected value predicate is fine and does set a proper value (in the debugger at least).
- Html.Label in the template returns a proper DisplayName for properties, but when I define a ViewData for them so as to display the dropdown list, the label resets to normal property name (ie.
category_id
instead ofCategory
).
What gives? Can you think of any "neater" way to accomplish this functionality?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
好吧,没有人回答,所以这就是我的答案,也许它对某人有用:
不要使用 ViewData 键的属性名称!它会扰乱视图模型,因此您的视图会变得混乱并开始表现奇怪。
实际上,最好完全避免魔法字符串的混乱,但如果您坚持的话,只需使用
例如:ViewData[prop.PropertyName+"_list"]
之类的东西。你的观点现在会很好。Allright, no one's answering so there's my answer, maybe it comes in handy for someone:
Do not use your property names for ViewData keys! It messes up with the view model, so your views get confused and start to behave strangely.
Actually, best avoid the magic strings mess entirely, but if you insist, just use something like
ex.: ViewData[prop.PropertyName+"_list"]
. Your views are going to be fine now.