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

如何从对象列表创建MVC HTMLHelper表

  •  6
  • David  · 技术社区  · 14 年前

    我正在尝试创建一个特定的htmlhelper表扩展,以减少我视图中的意大利面代码。

    以域对象列表为例,我想显示一个在将域对象的属性用作列时更智能的表。此外,我想禁用将某些属性显示为列。一个想法是用属性来装饰属性,告诉它不要被显示。

    希望这是有道理的,但我到目前为止…

    public static string MyTable(this HtmlHelper helper, string name, 
        IList<MyObject> items, object tableAttributes)
    {
        if (items == null || items.Count == 0)
            return String.Empty;
    
        StringBuilder sb = new StringBuilder();
        BuildTableHeader(sb, items[0].GetType());
    
        //TODO: to be implemented...
        //foreach (var i in items)
        //    BuildMyObjectTableRow(sb, i);
    
        TagBuilder builder = new TagBuilder("table");
        builder.MergeAttributes(new RouteValueDictionary(tableAttributes));
        builder.MergeAttribute("name", name);
        builder.InnerHtml = sb.ToString();
    
        return builder.ToString(TagRenderMode.Normal);
    }
    
    private static void BuildTableHeader(StringBuilder sb, Type p)
    {
        sb.AppendLine("<tr>");
    
        //some how here determine if this property should be shown or not
        //this could possibly come from an attribute defined on the property        
        foreach (var property in p.GetProperties())
            sb.AppendFormat("<th>{0}</th>", property.Name);
    
        sb.AppendLine("</tr>");
    }
    
    //would be nice to do something like this below to determine what
    //should be shown in the table
    [TableBind(Include="Property1,Property2,Property3")]
    public partial class MyObject
    {
       ...properties are defined as Linq2Sql
    }
    

    所以我只是想知道是否有人对这个想法或其他选择有任何意见/建议?

    3 回复  |  直到 14 年前
        1
  •  4
  •   Robert Harvey    14 年前

    到目前为止看起来不错,但吉尔芬克可能已经在这里为您完成了工作: http://blogs.microsoft.co.il/blogs/gilf/archive/2009/01/13/extending-asp-net-mvc-htmlhelper-class.aspx

        2
  •  1
  •   queen3    14 年前

    我强烈建议使用mvcontrib's Grid . 如果您决定不这样做,至少可以看看他们是如何解决表生成接口问题的。

        3
  •  1
  •   David    14 年前

    经过大约一个小时的工作,我能够创造出我想要的东西。我的解决方案是在域对象类上创建一个属性,指定哪些属性在我的表中可见。

    基于MVC1.0中的bindAttribute属性(查看源代码),我创建了一个tableProperty属性。

    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true)]
    public class TableProperty : Attribute
    {
        private string m_include;
        private string[] m_includeSplit;
    
        public TableProperty()
        {
            m_includeSplit = new string[0];
        }
    
        public string Include
        {
            get
            {
                return (m_include ?? string.Empty);
            }
            set
            {
                m_include = value;
                m_includeSplit = value.Split(',');
            }
        }
    
        public bool IsPropertyAllowed(string propertyName)
        {
            return IsPropertyAllowed(propertyName, m_includeSplit);
        }
    
        internal static bool IsPropertyAllowed(string propertyName, string[] includeProperties)
        {
            return ((includeProperties == null) || (includeProperties.Length == 0)) || includeProperties.Contains<string>(propertyName, StringComparer.OrdinalIgnoreCase);
        }
    }
    

    这允许我用这个属性装饰我的域对象…

    [TableProperty(Include="Property1,Property2,Property3")]
    public partial class MyObject
    { ...
    

    然后在buildTableHeader中,我使用反射获取对象的属性,并将每个属性与允许的列表相匹配。

    private static void BuildTableHeader(StringBuilder sb, Type p)
    {
        sb.AppendLine("<tr>");
    
        TableProperty tp = p.GetCustomAttributes(typeof(TableProperty), true)[0];
    
        foreach (var property in p.GetProperties())
            if (tp.IsPropertyAllowed(property.Name))
                sb.AppendFormat("<th>{0}</th>", property.Name);
    

    请注意,这个解决方案在我的小应用程序中对我很有用,但是为了更好地实现,它将更多地关注mvcontrib的网格。