Reputation:
I'm trying to write my own Html helper methods that accept lambda expressions like the built-in helpers (TextBoxFor, CheckBoxFor, LabelFor, etc). I have found some helpful info on this (How I can use a method of a model in a custom HtmlHelper as well as Scott Allen's http://odetocode.com/blogs/scott/archive/2012/11/26/why-all-the-lambdas.aspx), but I'm having trouble putting the pieces together. I'm getting lost in the interplay between the generics and the lambdas. Or something.
My case is a little different from the examples above -- I'm trying to write a data grid editing feature that allows in-place editing of rows in an HTML table. (I've done such a thing in classic ASP, and am trying to implement in MVC.) A grid editing control needs a little bit of state--a row ID and a URL to post changes to. So, my helper methods won't be static extentions of HtmlHelper. At least I don't think so. So, my question is not about grid editing functionality (I already have a grip on that more or less), but really just about how to setup my helper methods so they accept lambdas that behave like the built-in helpers. (I want the benefit of strong typing from my view. I could use reflection and string args to generate my markup, but I know I can do better.)
What I have so far looks like this where I'm trying to use it in a razor view--note the GridEditor object:
@foreach (var item in Model.Items)
{
var ge = new GridEditor<MyProject.SomethingFromMyDataModel>(item.ID, "someUrl");
<tr>
<td>@ge.CheckBox(x => x.SomeBooleanProperty)</td>
<td>@ge.TextBox(x => x.ATextProperty)</td>
<td>@ge.DropDownList(x => x.SomeForeignKey, ViewBag.MyList as SelectList)</td>
<td>@ge.Controls()</td>
</tr>
}
This does not work, but I hope it gives you an idea of what I'm trying to do. My GridEditor class is setup like this. I'm kind of grasping at straws.... note I did not include everything--but rather just the stuff I thought was relevant.
public class GridEditor<TModel> where <TModel> : class
{
public GridEditor(int rowID, string postUrl)
{
}
public MvcHtmlString CheckBox<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
{
}
}
Anyway, like I said this doesn't work. To boil it down -- my question is -- how do I setup my CheckBox (and similar) methods so that they accept a lambda that's strongly typed with the type passed to my GridEditor?
Upvotes: 0
Views: 139
Reputation:
After sleeping on it, I figured out that the answer is pretty easy.... since the methods on my GridEditor are instance (not static), I should use a TModel generic argument on the class definition (like I started with), but then omit it from subsequent method definitions. For example:
public class GridEditor<TModel> : where TModel : class
{
public MvcHtmlString CheckBox<TValue>(Expression<Func<TModel, TValue>> expression)
{
}
}
In use (inside a foreach loop that builds an html table in razor), it looks like this:
@foreach (var pi in Model.Items)
{
var ge = new GridEditor<AdamOneilSoftware.Models.ProfileItem>("/ServiceProfile/SaveItem", pi.ID);
<tr>
<td>@ge.CheckBox(x => x.AutoAdd)</td>
<td>@ge.DropDownList(x => x.ItemID, ViewBag.ItemID as SelectList)</td>
<td>@ge.TextBox(x => x.UnitPrice)</td>
<td>@ge.Controls()</td>
</tr>
}
Upvotes: 1