I'm writing a custom HTML helper to display a Grid and I'm focussing myself on Telerik and other parties for the syntax I would like to use.
I have a model with 3 properties (Name, DateUpdated and DateCreted) and an IEnumerable of that one is passed to my view:
@model IEnumerable<GridPageFolderViewModel>
Then I have my static HtmlHelperExtensions class:
public static class HtmlHelperExtensions
{
    #region Grid
    public static GridBuilder<TModelEntry> GridFor<TModel, TModelEntry>(this HtmlHelper<TModel> htmlHelper, TModelEntry model)
    {
        return new GridBuilder<TModelEntry>();
    }
    #endregion
}
This class does return a GridBuilder which looks as the following:
public class GridBuilder<TModel> : IGridBuilder
{
    #region Properties
    private string name { get; set; }
    #endregion
    #region Methods
    public GridBuilder<TModel> WithColumns(Action<ColumnBuilder<TModel>> function)
    {
        return this;
    } 
    internal MvcHtmlString Render()
    {
        return new MvcHtmlString("This is a value.");
    }
    #endregion
    #region IGridBuilder Members
    public GridBuilder<TModel> Name(string name)
    {
        this.name = name;
        return this;
    }
    #endregion
    #region IHtmlString Members
    public string ToHtmlString()
    { return Render().ToHtmlString(); }
    #endregion
}
And then I have my ColumnBuilder class.
public class ColumnBuilder<TModel>
{
    public void Bind<TItem>(Func<TModel, TItem> func)
    {
    }
}
With all this code into place (nothing is rendered at this point), I can use the following syntax:
@(Html.GridFor(new GridPageFolderViewModel())
      .Name("PageOverviewGrid")
      .WithColumns(column =>
      {
          column.Bind(c => c.Name);
          column.Bind(c => c.DateCreated);
          column.Bind(c => c.DateUpdated);
      }
)
The 'problem' here is that I need to specify the type of object that a single item in the Grid is holding (the GridPageFolderViewModel), otherwise, I cannot access the properties in the column binder code.
Anyone has some advice on how I can get rid of it?
As the view model is IEnumerable<GridPageFolderViewModel>, you just need to declare your helper like this:
public static GridBuilder<TModelEntry> GridFor<TModelEntry>(this HtmlHelper<IEnumerable<TModelEntry>> htmlHelper)
{
    return new GridBuilder<TModelEntry>();
}
It would mean your helper can only be used on views where the model is an IEnumerable<T>, but I think that makes sense.
Now in your view you can do:
@(Html.GridFor()
      .Name("PageOverviewGrid")
      .WithColumns(column =>
      {
          column.Bind(c => c.Name);
          column.Bind(c => c.DateCreated);
          column.Bind(c => c.DateUpdated);
      }
)
PS. Don't worry if you need to access the model inside your helper. You can still retrieve it from htmlHelper.ViewData.Model, which will be nicely typed as IEnumerable<TModelEntry>
Hope it helps!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With