代码之家  ›  专栏  ›  技术社区  ›  UpTheCreek

ASP.NETMVC通用模板和集合

  •  2
  • UpTheCreek  · 技术社区  · 14 年前

    可以将属性应用于集合,然后在使用 ViewData.ModelMetadata.Properties

    我想对集合应用一个属性,以指定集合中的项是否应完整显示。我想在对象.ascx(处理未知类型对象的显示)决定要显示的详细程度。

    (请参见 brad wilson's post

    public class Parent
    {
       [SomeAttributeIWantToDetect]        
       public IList<Child> Children{ get; set; }
    }
    
    
    public class Child
    {
        public string Name { get; set; }
        public string Details { get; set; }
    }
    

    对象.ascx: (注意,此代码来自ASP.NETMVC团队,不是我的)

    <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>
    <% if (Model == null) { %>
        <%= ViewData.ModelMetadata.NullDisplayText %>
    <% } else { %>
        <table cellpadding="0" cellspacing="0" border="0">
        <% foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm))) { %>
            <% if (prop.HideSurroundingHtml) { %>
                <%= Html.Display(prop.PropertyName) %>
            <% } else { %>
                <tr>
                    <td>
                        <div class="display-label" style="text-align: right;">
                            <%= prop.GetDisplayName() %>
                        </div>
                    </td>
                    <td>
                        <div class="display-field">
                        <!-- *********** HERE ***************-->
                        <% if (prop.AdditionalValues.ContainsKey(SomeAttributeIWantToDetectAttribute)) 
                            //Do something else.....
                            else
                         %>
                            <%= Html.Display(prop.PropertyName) %>
                        <% } %>
                        </div>
                    </td>
                </tr>
            <% } %>
        <% } %>
        </table>
    <% } %>
    
    4 回复  |  直到 14 年前
        1
  •  1
  •   TFD    14 年前

    这不是MVC,它更接近于传统的ASP模板

    您的ViewModel应该只使用上面的逻辑命令来构建。即

    if (Model == null)
    {
      x = ViewData.ModelMetadata.NullDisplayText
    }
    else
    {
      foreach (var prop in ViewData.ModelMetadata.Properties.Where(pm => pm.ShowForDisplay && !ViewData.TemplateInfo.Visited(pm)))
      {
        if (prop.HideSurroundingHtml)
        {
          x.Items1.Add(prop.PropertyName));
        }
        else
        {
          prop.GetDisplayName()
          if (prop.AdditionalValues.ContainsKey(SomeAttributeIWantToDetectAttribute)) 
          {
            x.Items2.Add( { Text = prop.zzz, Highlight = true} ));
          }
          else
          {
            x.Items2.Add( { Text = prop.PropertyName } ));
          }
        }
      }
    }
    

    上面的代码显然是错误的,我只是想说明你应该用复杂的代码和逻辑来构建一个ViewModel,它不应该出现在视图中

    ViewModel有一个与所使用的呈现技术相关的简单构造(如html属性等)

    视图应该只包含简单的迭代器和布局选择器,由ViewModel提供,而不是实际的模型

        2
  •  1
  •   Ryan    14 年前

    @UpTheCreek,你想让别人帮你,这让你觉得很有对抗性,但我还是会给你2分钱的。

    我的理解是你想在一个模型上有一个子集合。在子模型上,您将包含一些[ScaffoldColumn(“false”)]属性,但您还希望能够在父模型上放置一个属性,该属性将导致渲染器忽略ScaffoldColumn属性而只显示所有内容。如果我的理解是正确的,我认为你这样做是错误的。您应该为希望显示不同属性的情况创建单独的视图模型。

        3
  •  1
  •   Iain Galloway    14 年前

    你已经联系上了 http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html

    我不明白你为什么相信这个。TFD和Ryan说得很对。创建两个不同的ViewModel来包装模型,并将ScaffoldColumn属性放在ViewModel上(或者更好,完全忽略这些字段)。

    对象.ascx然后检测ViewModel上的属性(当然也包括字段的存在与否),并适当地显示(或不显示)字段。

    事实上,你链接的帖子的作者建议即:-

    http://bradwilson.typepad.com/blog/2009/10/aspnet-mvc-2-templates-part-4-custom-object-templates.html#comment-6a00e54fbd8c4988340120a6396c7a970b

    “就个人而言,我建议 视图模型上的注释。 SQL或LINQ to Entities(例如, 如果你不小心,你会毁了 你的联想还是无意间让 坏人把数据绑定到某个东西上 编辑),所以我通常总是 还是推荐视图模型。”

    所以:-

    public class Parent
    {
      public IList<Child> Children{ get; set; }
    }
    
    public class Child
    {
      public String Name { get; set; }
      public String Details { get; set; }
    }
    
    // Pass this one to your "Admin" view.
    public class ParentAdminViewModel
    {
      private Parent _parent;
      public ParentAdminViewModel(Parent parent) { this._parent = parent; }
    
      public IEnumerable<Child> Children
      {
        get
        {
          return _parent.Children.Select(x => new ChildAdminViewModel(x));
        }
      }
    }
    
    public class ChildAdminViewModel
    {
      private Child _child;
      public ChildAdminViewModel(Child child) { this._child = child; }
    
      public String Name { get { return _child.Name; } }
      public String Details { get { return _child.Details; } }
    }
    
    // Pass this one to your "User" view.
    public class ParentUserViewModel
    {
      private Parent _parent;
      public ParentUserViewModel(Parent parent) { this._parent = parent; }
    
      public IEnumerable<Child> Children
      {
        get
        {
          return _parent.Children.Select(x => new ChildUserViewModel(x));
        }
      }
    }
    
    public class ChildUserViewModel
    {
      private Child _child;
      public ChildAdminViewModel(Child child) { this._child = child; }
    
      public String Name { get { return _child.Name; } }
      // ChildUserViewModel doesn't have a Details property,
      // so Object.ascx won't render a field for it.
    }
    

        4
  •  0
  •   Nik    14 年前