我最近决定编写一个通用的Table html帮助器来为我的模型和其他对象生成表,我已经使用了反射来使它更通用,将IEnumerable参数作为表数据和一个字典用于。
我想使用反射或其他方法从MetaData模型中获取属性[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());
}
所以基本上我希望尽可能多地使用反射来消除尽可能多的这个方法的参数。
谢谢, 亚历克斯。
答案 0 :(得分:2)
我不确定为什么你的显示属性检索不起作用。这是我使用的。它来自一个从枚举字段值中检索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();
}