1

I am trying to create a generic method for HTML table building.

As part of the functionality I need, I'd like the user to be able to specify the properties that will be turned into columns.

As this is a generic method, I had thought that the user could pass in the properties they need as some sort of LINQ expression, and from that I would apply this select to the dataset, and loop through the properties to build the table data up:

  public static string BuildCollapsibleHtmlTable<T>(
        IEnumerable<T> dataSet,
        Func<T, object> tableDataColumnDefinitions,
        KeyValuePair<string, string>[] tableColumnNames,
        Func<T, object> groupByQuery,
        Func<T, decimal> groupSumQuery) where T : class, new() {

      ... implementation ..
   }

The 'tableColumnDefinitions' part is where I'm struggling (2nd parameter). I can get this to work for grouping and summing, but not for selecting columns/properties to use in the table:

var test = HtmlBuilders.BuildCollapsibleHtmlTable<Client>(
               Model.Clients,
               (clients => clients.ClientName),
               new KeyValuePair<string, string>[] { 
                   new KeyValuePair<string, string> ("Client", "tdCSSLeft"),
                   new KeyValuePair<string, string> ("Debt", "tdCSSCenter")
                },
               (client => client.ClientName),
               (client => client.TotalDebt)
           );

I seem only to be able to get it to work for pulling one property a time (and thus I'd need an array of expression). I'm not against this, but wondered if I'm going about this all wrong? Is there a easier/better way to pass an arbitrary select query as a parameter?

pierre
  • 1,235
  • 1
  • 13
  • 30

1 Answers1

1

Yes, you'll need to use an array. Note that you seem to already have a similar array: KeyValuePair<string, string>[] tableColumnNames, so I don't see where the problem is.

Technically you could change the signature of your method in this way:

public static string BuildCollapsibleHtmlTable<T>(
    IEnumerable<T> dataSet,
    KeyValuePair<string, string>[] tableColumnNames,
    Func<T, object> groupByQuery,
    Func<T, decimal> groupSumQuery,
    params Func<T, object>[] tableDataColumnDefinitions
) where T : class, new() {

so that you wouldn't need to create an array when calling the method, but you could call it like

var test = HtmlBuilders.BuildCollapsibleHtmlTable<Client>(
           Model.Clients,
           //new KeyValuePair<string, string>[] { 
           new[] {  // Shorter
               new KeyValuePair<string, string> ("Client", "tdCSSLeft"),
               new KeyValuePair<string, string> ("Debt", "tdCSSCenter")
           },
           (client => client.ClientName),
           (client => client.TotalDebt),

           // tableDataColumnDefinitions
           (clients => clients.ClientName),
           (clients => clients.ClientSurname),
           (clients => clients.ClientAddress)
       );
xanatos
  • 109,618
  • 12
  • 197
  • 280
  • How would I select all properties at once using this method? (dataSet.Select(xxxxxx)) – pierre Mar 06 '15 at 12:08
  • @pierre What do you want to do with all the properties together? Normally instead of using LINQ you should/would use a `foreach (var row in dataSet) { for (int i = 0; i< tableDataColumnDefinitions.Length; i++) { object data = tableDataColumnDefinitions[i](row);`. Now, if you want this expression can be changed to a LINQ expression, but what you'll have will be a `IEnumerable` (a "list" of rows, each row an array of `object[]`) – xanatos Mar 06 '15 at 12:21