3
votes

I want to create a kind of WebGrid 2.0 for ASP.NET and Razor.

Defining a ModelClass (TData) the WebGrid should create the HTML for the table on its own.

The Properties of TData should be read via reflection (typeof(TData).GetProperties). The attributes of the properties should define some css and html styling or even some data (DisplayNameAttribute => ColumnHeader).

Now I came to the point, when I want to call htmlHelper.DisplayFor(...propertyInfoToExpression...) to render the datas content.

How could I call DisplayFor, when I only got the data(row)/model and the propertyInfo?


WebGrid-Class:

public class TableModel<TData>{

     private readonly IList<TData> _rows;
     private readonly IList<TableColumn<TData>> _columns = new List<TableColumn<TData>>();


     public TableModel(IList<TData> rows) {
        _rows = rows;

        PropertyInfo[] propertyInfos = typeof(TData).GetProperties();
        foreach (PropertyInfo property in propertyInfos) {
            if (!Attribute.IsDefined(property, typeof(NoColumnAttribute))) {
                _columns.Add(new TableColumn<TData>(property));
            }
        }

    }

    private MvcHtmlString GetCellHtml(HtmlHelper<TData> helper, TableColumn column, TData dataRow){

         TagBuilder cellTagBuilder = new TagBuilder("td");
         cellTagBuilder.InnerHtml = helper.DisplayFor(...propertyInfoToExpression...)

    }

    public MvcHtmlString ToHtml(HtmlHelper helper){
         TagBuilder tableTagBuilder = new TagBuilder("table");
         TagBuilder headTagBuilder = new TagBuilder("thead");
         TagBuilder bodyTagBuilder = new TagBuilder("tbody");

         ...
         return new MvcHtmlString(tableTagBuilder);
    }
}

Sample Class for TData just to catch the idea:

public class UserModel{

      [NoColumnAttribute]
      public int Id{get;set;}

      [CssClass("name")]
      public string Firstname {get;set;}

      [CssClass("name")]
      public string Lastname{get;set;}

      [CssClass("mail")]
      public string Mail{get;set;}

      [CssClass("phone")]
      public string Phone{get;set;}

}
2
what? can you describe it with sample code ( for mode, as well as snippet of desired call structure). might be easy to figure out a solution then. usually with an expression you can solve things without having to deal with PropertyInfo. - Dbl
I added some sample code. - Tobias
I don't think your class concept is right yet? I suppose you want to call it like this (assuming the model you pass to your view is of type UserModel: @Html.WebGridFor(x => x)? Making a list of it would be pointless then. I suppose you're open to heavily modified code of yours? - Dbl
Nice hint. Thanks. But the problem with displayfor() remains, doesn't it? - Tobias
For now yes. I'll have a look at it. I'm waiting for someone else to finish something either way. Might take a while. - Dbl

2 Answers

2
votes

You could try it like this:

        var properties = typeof (TModel).GetProperties();
        foreach (PropertyInfo info in properties)
        {
            ParameterExpression p1 = Expression.Parameter(typeof(TModel), "m");
            ParameterExpression p2 = Expression.Parameter(info.PropertyType, "m."+info.Name);
            Expression<Func<TModel, dynamic>> exResult = Expression.Lambda<Func<TModel, dynamic>>(p1, p2);

            helper.DisplayFor(exResult);
        }

Sorry that it took a while. Had to do some other work.

1
votes

Have you tried...

private MvcHtmlString GetCellHtml(HtmlHelper<TData> helper, TableColumn column, TData dataRow){

     TagBuilder cellTagBuilder = new TagBuilder("td");
     cellTagBuilder.InnerHtml = helper.Display(column.PropertyInfo.Name, dataRow);
     ...
}

...?

If you need DisplayFor only for your method GetCellHtml then you don't really need to build an expression from a PropertyInfo.