c# - Writing a HtmlHelper 'Table' method, which uses the model DisplayName's -
i have decided write generic table html helper generate tables models , other objects, have used reflection make more generic taking ienumerable argument table data , dictionary .
i want use reflection or other method properties [displayname()] attribute models metadata not need specified in dictionary. methods have tried seem return null, have removed them code.
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 ? propinfo in objectdatatype.getproperties() 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 there no data displayed. { tagbuilder tfoottd = new tagbuilder("td") { innerhtml = "there nothing 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 pager & filter navigating through large amounts of data. { // button navigating 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;"); // button navigating 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;"); // button navigating 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;"); // button navigating 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;"); // display field 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%;"); // select 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%;"); (int = 10; <= 100; += 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()); } // 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%;"); // 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()); }
so looking use reflection possible eliminate many arguments method possible.
thanks, alex.
i'm not sure why display attribute retrieval isn't working. here's use. it's method retrieves display attribute enum field values, it's same basic pattern use retrieve attribute object:
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(); }
Comments
Post a Comment