Context : Since we are developing in C# MVC3, we wanted to have some classes designed to handle the tables on a web page. (Pagination / search / etc...).
So we finally found that it could be the best to have the following classes :
The table object that will hold all other object and knows the current page / current search etc... (misc informations)
public class Table<T> where T : IPrivateObject
{
...
public ICollection<Column<T>> Columns { get; set; }
public ICollection<Row<T>> Rows { get; set; }
public ICollection<RowMenu<T>> Menus { get; set; }
public ICollection<T> Items { get; set; }
public Table(
ICollection<T> inputItems,
ICollection<Column<T>> columns,
ICollection<RowMenuItem<T>> rowMenuItems,
...)
{
...
this.Columns = columns;
}
The column object that knows which property should be displayed and and a header value
public class Column<T> where T : IPrivateObject
{
public string Value { get; set; }
public Expression<Func<T, object>> Property { get; set; }
public Column(Expression<Func<T, object>> property, string value)
{
this.Property = property;
this.Value = value;
}
}
The other classes are not really interesting so i won't post them here.
In the controller, we use these classes like that :
public ActionResult Index(string search = null, string sort = null, int order = 1, int take = 10, int page = 1)
{
ICollection<Person> people = prismaManager.PersonManager.Search(search);
ICollection<Column<Person>> columns= new List<Column<Person>>();
columns.Add(new Column<Person>(Person => Person, "Person"));
columns.Add(new Column<Person>(Person => Person.LastMembershipApproval, "Last Membership approval"));
Table<Person> table = people.ToTable(columns);
}
We are now writing a helper that will display the table correctly. It works well for the header but we face a problem with the Expressions when we want to use the @Html.DisplayFor() helper.
This is what we currently have for the content :
private static string TableRows<T>(HtmlHelper<Table<T>> helper, Table<T> table) where T : IPrivateObject
{
StringBuilder sb = new StringBuilder();
foreach (var item in table.Items)
{
sb.AppendLine("<tr>");
foreach (var column in table.Columns)
{
sb.AppendLine("<td>");
sb.AppendLine(helper.DisplayFor(obj => ??? ).ToString()); // How should I use the Expression that is stored in the column but for the current element ?
sb.AppendLine("</td>");
}
sb.AppendLine("</tr>");
}
return sb.ToString();
}
For this to work, we should set the value of the "Person" parameter from the Expression stored in the column to the current item.
new Column<Person>(Person => Person, "Person"));
How are we supposed to do that ? Should we (if it is possible) modify the expression to set the value ? Should we recreate a new Expression using the old one as a basic expression ?
I've been searching for 3 days now and I can't find any answers.
Thanks for your help.
UPDATE :
The problem is (as @Groo & @Darin Dimitrov said) that the Helper is of type HtmlHelper> and not HtmlHelper. Any idea how I could get an HtmlHelper from a HtmlHelper> ?
UPDATE :
Person class is as following :
public class Person : IPrivateObject
{
public int Id { get; set; }
public int? AddrId { get; set; }
[DisplayName("First Name")]
[StringLength(100)]
[Required]
public string FirstName { get; set; }
[DisplayName("Last Name")]
[StringLength(100)]
[Required]
public string LastName { get; set; }
[DisplayName("Initials")]
[StringLength(6)]
public string Initials { get; set; }
[DisplayName("Last membership approval")]
public Nullable<DateTime> LastMembershipApproval { get; set; }
[DisplayName("Full name")]
public string FullName
{
get
{
return FirstName + " " + LastName;
}
}
public override string ToString()
{
return FullName;
}
}