通过 ViewData 将 SelectList 传递到编辑器模板 - 未正确显示

发布于 2024-10-06 02:42:10 字数 2766 浏览 0 评论 0原文

这有点复杂,所以请耐心等待。

假设我有一个控制器编辑操作的示例,其定义如下:

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 元数据属性。

现在,下拉列表显示良好并且已正确填充,但是:

  1. 始终选择列表中的第一个值,即使 SelectList 选择值谓词很好并且确实设置了正确的值(至少在调试器中)。
  2. 模板中的 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:

  1. 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).
  2. 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 of Category).

What gives? Can you think of any "neater" way to accomplish this functionality?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

还在原地等你 2024-10-13 02:42:10

好吧,没有人回答,所以这就是我的答案,也许它对某人有用:

不要使用 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文