Context: Since we are developing in C # MVC3, we wanted to have some classes designed to handle tables on a web page. (Pagination / search / etc.).
So, we finally found out that it is best to have the following classes:
A table object that will hold all other objects and knows the current search on pages / current data, etc .... (odd information)
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; }
A column object that knows which property should be displayed, and the value of the header
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; } }
Other classes are not very interesting, so I will not publish them here.
In the controller, we use the following classes:
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); }
Now we are writing an assistant that will correctly display the table. It works well for the header, but we run into a problem with expressions when we want to use the @ Html.DisplayFor () helper.
This is what we currently have for 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());
For this to work, we must set the value of the Person parameter from the expression stored in the column to the current element.
new Column<Person>(Person => Person, "Person"));
How should we do this? Should we (if possible) change the expression to set the value? Should we recreate the new expression using the old as the main expression?
I searched for 3 days and can not find the answers.
Thank you for your help.
UPDATE:
The problem is that the Helper is of type HtmlHelper>, not HtmlHelper (as @Groo and @Darin Dimitrov said). Any idea how I can get HtmlHelper from HtmlHelper>?
UPDATE:
The Person class is as follows:
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; } }