c# - 编写一个 HtmlHelper 'Table' 方法,它使用模型 DisplayName 的

标签 c# asp.net-mvc html-helper

我最近决定编写一个通用的 Table html 帮助程序来为我的模型和其他对象生成表格,我使用反射通过将 IEnumerable 参数作为表格数据并将 .

我想使用反射或其他一些方法从模型元数据中获取属性 [DisplayName()] 属性,这样就不需要在字典中指定它了。然而,我尝试过的所有方法似乎都返回 null,因此我已将它们从我的代码中删除。

public static MvcHtmlString Table(this HtmlHelper htmlHelper, Dictionary<string, string> boundColumns, IEnumerable<object> objectData, string tagId, string className, string controllerName, string idProperty)
        {
            bool hasAction = !String.IsNullOrEmpty(idProperty);
            bool hasData = objectData.Count() > 0;
            UrlHelper urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);

            Type objectDataType = hasData ? objectData.First().GetType() : null;
            IEnumerable<PropertyInfo> objectDataProperties = hasData ? from propInfo in objectDataType.GetProperties()
                                                                       where boundColumns.ContainsKey(propInfo.Name)
                                                                       select propInfo : null;

            // Thead
            TagBuilder theadtr = new TagBuilder("tr");
            foreach (string col in boundColumns.Values)
                theadtr.InnerHtml = String.Format("{0}\n{1}", theadtr.InnerHtml, (new TagBuilder("th") { InnerHtml = col }).ToString());
            if (hasAction)
                theadtr.InnerHtml = String.Format("{0}\n{1}", theadtr.InnerHtml, new TagBuilder("th") { InnerHtml = "Action" });
            TagBuilder thead = new TagBuilder("thead") { InnerHtml = theadtr.ToString() };

            // Tfoot
            TagBuilder tfoot = new TagBuilder("tfoot");
            if (!hasData) // Warn that there was no data to be displayed.
            {
                TagBuilder tfoottd = new TagBuilder("td") { InnerHtml = "There is currently nothing to display." };
                tfoottd.MergeAttribute("colspan", (hasAction ? (boundColumns.Count + 1) : boundColumns.Count).ToString());
                tfoottd.MergeAttribute("style", "text-align:center");
                tfoot.InnerHtml = (new TagBuilder("tr") { InnerHtml = tfoottd.ToString() }).ToString();
            }
            else // Display a pager & filter for navigating through large amounts of data.
            {
                // The button for navigating to the first page.
                TagBuilder pagefirst = new TagBuilder("img");
                pagefirst.MergeAttribute("id", String.Format("{0}-page-first", tagId));
                pagefirst.MergeAttribute("class", "first");
                pagefirst.MergeAttribute("alt", "First Page");
                pagefirst.MergeAttribute("src", urlHelper.Content("~/Content/Style/Tables/Themes/Blue/resultset_first.png"));
                pagefirst.MergeAttribute("style", "cursor:pointer; vertical-align:middle;");

                // The button for navigating to the previous page.
                TagBuilder pageprev = new TagBuilder("img");
                pageprev.MergeAttribute("id", String.Format("{0}-page-prev", tagId));
                pageprev.MergeAttribute("class", "prev");
                pageprev.MergeAttribute("alt", "Previous Page");
                pageprev.MergeAttribute("src", urlHelper.Content("~/Content/Style/Tables/Themes/Blue/resultset_previous.png"));
                pageprev.MergeAttribute("style", "cursor:pointer; vertical-align:middle;");

                // The button for navigating to the next page.
                TagBuilder pagenext = new TagBuilder("img");
                pagenext.MergeAttribute("id", String.Format("{0}-page-next", tagId));
                pagenext.MergeAttribute("class", "next");
                pagenext.MergeAttribute("alt", "Next Page");
                pagenext.MergeAttribute("src", urlHelper.Content("~/Content/Style/Tables/Themes/Blue/resultset_next.png"));
                pagenext.MergeAttribute("style", "cursor:pointer; vertical-align:middle;");

                // The button for navigating to the last page.
                TagBuilder pagelast = new TagBuilder("img");
                pagelast.MergeAttribute("id", String.Format("{0}-page-last", tagId));
                pagelast.MergeAttribute("class", "last");
                pagelast.MergeAttribute("alt", "Last Page");
                pagelast.MergeAttribute("src", urlHelper.Content("~/Content/Style/Tables/Themes/Blue/resultset_last.png"));
                pagelast.MergeAttribute("style", "cursor:pointer; vertical-align:middle;");

                // The display field for the pager status.
                TagBuilder pagedisplay = new TagBuilder("input");
                pagedisplay.MergeAttribute("id", String.Format("{0}-page-display", tagId));
                pagedisplay.MergeAttribute("type", "text");
                pagedisplay.MergeAttribute("class", "pagedisplay");
                pagedisplay.MergeAttribute("disabled", "disabled");
                pagedisplay.MergeAttribute("style", "width:12%;");

                // The select for changing page size.
                TagBuilder pagesize = new TagBuilder("select");
                pagesize.MergeAttribute("id", String.Format("{0}-page-size", tagId));
                pagesize.MergeAttribute("class", "pagesize");
                pagesize.MergeAttribute("style", "width:12%;");
                for (int i = 10; i <= 100; i += 10)
                {
                    TagBuilder option = new TagBuilder("option") { InnerHtml = i.ToString() };
                    if (i == 10)
                        option.MergeAttribute("selected", "selected");
                    option.MergeAttribute("value", i.ToString());

                    pagesize.InnerHtml = String.Format("{0}\n{1}", pagesize.InnerHtml, option.ToString());
                }

                // The pager container.
                TagBuilder pagediv = new TagBuilder("div") { InnerHtml = (new TagBuilder("form") { InnerHtml = String.Format("{0}\n{1}\n{2}\n{3}\n{4}\n{5}", pagefirst.ToString(), pageprev.ToString(), pagenext.ToString(), pagelast.ToString(), pagedisplay.ToString(), pagesize.ToString()) }).ToString() };
                pagediv.MergeAttribute("id", String.Format("{0}-pager", tagId));
                pagediv.MergeAttribute("style", "float:left; width:50%;");

                // Filter Text Field
                TagBuilder filterfield = new TagBuilder("input");
                filterfield.MergeAttribute("id", String.Format("{0}-filter-field", tagId));
                filterfield.MergeAttribute("type", "text");
                filterfield.MergeAttribute("style", "width:30%;");

                // The filter container.
                TagBuilder filterdiv = new TagBuilder("div") { InnerHtml = (new TagBuilder("form") {InnerHtml = String.Format("Search: {0}", filterfield.ToString())}).ToString() };
                filterdiv.MergeAttribute("id", String.Format("{0}-filter", tagId));
                filterdiv.MergeAttribute("style", "float:right; width:50%;");

                TagBuilder tfoottd = new TagBuilder("td") { InnerHtml = String.Format("{0}\n{1}", pagediv.ToString(), filterdiv.ToString()) };
                tfoottd.MergeAttribute("colspan", (hasAction ? (boundColumns.Count + 1) : boundColumns.Count).ToString());
                tfoottd.MergeAttribute("style", "text-align:center");
                tfoot.InnerHtml = (new TagBuilder("tr") { InnerHtml = tfoottd.ToString() }).ToString();
            }

            // Tbody
            TagBuilder tbody = new TagBuilder("tbody");
            foreach (object o in objectData)
            {
                TagBuilder tbodytr = new TagBuilder("tr");
                foreach (PropertyInfo p in objectDataProperties)
                {
                    string val = "N/A";
                    object pval = p.GetValue(o, null);
                    if (pval != null)
                        val = pval.ToString();
                    tbodytr.InnerHtml = String.Format("{0}\n{1}", tbodytr.InnerHtml, (new TagBuilder("td") { InnerHtml = val }).ToString());
                }

                if (hasAction)
                {
                    string id = objectDataType.GetProperty(idProperty).GetValue(o, null).ToString();
                    tbodytr.InnerHtml = String.Format(
                        "{0}\n{1}",
                        tbodytr.InnerHtml,
                        (new TagBuilder("td") { InnerHtml = Table_ActionLinks(htmlHelper, controllerName, id) }).
                            ToString());
                }

                tbody.InnerHtml = String.Format("{0}\n{1}", tbody.InnerHtml, tbodytr.ToString());
            }

            // Table
            TagBuilder table = new TagBuilder("table") { InnerHtml = String.Format("{0}\n{1}\n{2}", thead.ToString(), tfoot.ToString(), tbody.ToString()) };
            table.MergeAttribute("id", string.IsNullOrEmpty(tagId) ? String.Format("table-{0}", boundColumns.Count.ToString()) : tagId);
            table.MergeAttribute("summary", "Generic data list");
            if (!String.IsNullOrEmpty(className))
                table.MergeAttribute("class", String.Format("{0} {1}", className, "tablesorter"));
            else
                table.MergeAttribute("class", "tablesorter");

            // Enable Sorting/Searching
            if (hasData)
            {
                TagBuilder sortscript = new TagBuilder("script") { InnerHtml = String.Format("$(document).ready(function(){{$(\"#{0}\").tablesorter().tablesorterPager({{container:$(\"#{1}\")}});}});", tagId, String.Format("{0}-pager", tagId)) };
                TagBuilder searchscript = new TagBuilder("script") { InnerHtml = String.Format("$(document).ready(function(){{$(\"#{0}\").keyup(function(){{$.uiTableFilter($(\"#{1}\"), this.value);}})}});", String.Format("{0}-filter-field", tagId), tagId) };
                sortscript.MergeAttribute("type", "text/javascript");
                return new MvcHtmlString(String.Format("{0}\n{1}\n{2}", table.ToString(), sortscript.ToString(), searchscript.ToString()));
            }

            return new MvcHtmlString(table.ToString());
        }

所以基本上我希望使用尽可能多的反射来尽可能多地消除此方法的参数。

谢谢, 亚历克斯。

最佳答案

我不确定为什么您的 Display 属性检索不起作用。这是我用的。它来自从枚举字段值中检索 Display 属性的方法,但它与我用来从对象中检索任何属性的基本模式相同:

public static string GetDisplayName<T>( T toCheck )
{
  Type enumType = typeof(T);
  if( !enumType.IsEnum ) return null;

  MemberInfo[] members = enumType.GetMember(toCheck.ToString());

  if( ( members == null ) || ( members.Length != 1 ) ) return toCheck.ToString();

  foreach( MemberInfo memInfo in members )
  {
      DisplayAttribute[] attrs = (DisplayAttribute[]) memInfo.GetCustomAttributes(typeof(DisplayAttribute), false);

      if( ( attrs != null ) && ( attrs.Length == 1 ) ) return attrs[0].Name;
  }

  return toCheck.ToString();
}

关于c# - 编写一个 HtmlHelper 'Table' 方法,它使用模型 DisplayName 的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4917031/

相关文章:

c# - 多播 OnExceptionAspect 正在记录冒泡异常

c# - EF6 可选 1 :1 include not working

c# - 如何确定分布式架构?

c# - 如何使用 LINQ 组记录和使用 Distinct

c# - "The SMTP host was not specified."- 但它是指定的?

css - 样式化 HTML 助手 ASP.NET MVC

asp.net-mvc - 路由约束破坏了授权属性过滤器 - MVC 4

ajax - 在 ajax 请求中下载文件而不会遇到长查询字符串

c# - 如何读取 html 帮助元素的名称

url - 如何将带有@ url.action的参数传递给 Controller