i trying write customer htmlhelper allows easy creation of html table view being passed ienumerable <tmodel>
tmodel model object type. calling syntax view of style:
@html.tablefor(model => model.addeduserid, model => model.clientid......., model model => anothrefildiwantdisplayed));
i starting off trying working 1 expression being passed first e.g.
@html.tablefor(model => model.addeduserid)
once works comma separated list working using params , taking more 1 expression.
my view code looks this
@using mynamespacetomyhelper @model ienumerable<user> @{ viewbag.title = "index"; } <p> </p> @html.tablefor(model => model.addeduserid));
my attempt @ writing htmlhelper is:
using system; using system.collections.generic; using system.io; using system.linq; using system.linq.expressions; using system.text; using system.threading.tasks; using system.web; using system.web.mvc; using system.web.mvc.html; using system.web.ui; namespace mynamespacetomyhelper { public static class gridextensions { public static mvchtmlstring tablefor<tmodel, tvalue>(this htmlhelper<ienumerable<tmodel>> html, expression<func<tmodel, tvalue>> expression) { var writer = new htmltextwriter(new stringwriter()); writer.renderbegintag(htmltextwritertag.table); writer.renderbegintag(htmltextwritertag.thead); writer.renderbegintag(htmltextwritertag.th); writer.renderbegintag(htmltextwritertag.td); //colum headers writer.write(html.displaynamefor(expression)); writer.renderendtag(); writer.renderendtag(); writer.renderendtag();//close thead //column data //html.displayfor((expression<func<tmodel, tvalue>>)expression); foreach (viewdatadictionary<tmodel> vdm in html.viewdata.values) { writer.renderbegintag(htmltextwritertag.tr); writer.renderbegintag(htmltextwritertag.td); //doesn't compile html.displayfor(expression); writer.renderendtag(); writer.renderendtag(); } writer.renderendtag(); //close header return new mvchtmlstring(writer.innerwriter.tostring()); } } }
this not compile because of:
html.displayfor(expression);
as far understanding goes because htmlhelper passed method htmlhelper<ienumerable<tmodel>>
whereas when using displayfor
needs htmlhelper<tmodel>
.
because of error seems feasible working splitting table header , data 2 separate method calls , view call header method have loop inside actual view calls method each row or something. this
@using mynamespacetomyhelper @model ienumerable<user> @{ viewbag.title = "index"; } <p> </p> @html.tableheadersfor(model => model.addeduserid)); @foreach (var item in model) { @html.tablerowsfor(model => model.addeduserid)); }
this should work because tableheadersfor
can call displaynameextensions.displaynamefor
takes htmlhelper<ienumerable<tmodel>>
, tablerowsfor
take htmlhelper<tmodel>
, call displayextensions.displayfor
htmlhelper<tmodel>
incompatible htmlhelper types problem go away.
however not ideally want if @ possible want calling syntax simple possible. basic premise of question try , maintain simple calling syntax without writing loop in view , duplicating expressions choosing columns. entire purpose here design re-usable , easy use others possible
i had in ilspy @ how displaynameextensions.displaynamefor
works handles htmlhelper<ienumerable<tmodel>>
looks somehow exstension method taking htmlhelper<ienuermable<tmodel>>
calling internally extension method on htmlhelper<tmodel>
code ilspy producing doesn't recompile getting no understanding how .net able this.
is possible in 1 extension method or forced split compromising calling syntax?
update 1 have managed following working quite lot of work:
@html.begintablefor(model => model.addeduserid , model => model.active , new { @class = "grid" }) @foreach (var item in model) { @html.displayrowfor(model => item.addeduserid , model => item.active) } @html.endtablefor()
it's not concise , involves heap of work because each expression begintablefor , displayrowfor can return different type meaning have had implement method overload number of expressions (i've done 100 work upto 100 columns!). same problem had in .net action , func delegates had write different versions different numbers of parameters e.g. action t1, t2,..,t16. it's extremely messy rather have nice calling syntax avoid many method overloads.
have @ this article direction , modify according needs.
first need html extensions this:
public static class razorextensions { public static helperresult list<t>(this ienumerable<t> items, func<t, helperresult> template) { return new helperresult(writer => { foreach (var item in items) { template(item).writeto(writer); } }); } }
then in html can following:
{ var comics = new[] { new comicbook {title = "groo", publisher = "dark horse comics"}, new comicbook {title = "spiderman", publisher = "marvel"} }; } <table> @comics.list( @<tr> <td>@item.title</td> <td>@item.publisher</td> </tr>) </table>
Comments
Post a Comment