Tobias
Tobias

Reputation: 2985

PropertyInfo to Expression<Func<TModel, TProperty>>

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;}

}

Upvotes: 3

Views: 829

Answers (2)

Dbl
Dbl

Reputation: 5904

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.

Upvotes: 2

Boris B.
Boris B.

Reputation: 5024

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.

Upvotes: 1

Related Questions