Ajax HTML Grid Control for ASP.NET MVC (Part 1)

At work we are starting a major project and I think we have decided to go the ASP.NET MVC route. One of the concerns we had was that we could not use traditional "web controls" (i.e. Telerik, DevExpress) since the all require the <...runat=server> portion. With that said, I thought I would start to take a look at how I would go about doing it! The first "control" I want to get off the ground is a data bound grid that allows asynchronous saves via JavaScript. We'll see how it goes!

Premise

The idea is to use an extension method to any IEnumerable<T> object that generates the grid. I also want to be able to use CSS to stylize any aspect of the grid. Additionally, there should be a way to edit (in place) any of the records in the grid and post the results back using AJAX. I think this should be an interesting project!

Code

For this part I just want to print out the stylized table. Here is the result:

public static string ToAjaxGrid<T, TKey>(this IEnumerable<T> list, 
                                 Func<T, TKey> key, 
                                 string name, 
                                 NameValueCollection attributes)
{
   string format = " style="{0}"";
   StringBuilder sb = new StringBuilder();
   // Build outer table div
   sb.Append(String.Format("<table id="{0}"{1}>n", 
      name, 
      attributes["TableStyle"] != null 
         ? String.Format(format, attributes["TableStyle"]) : ""));
   foreach(T item in list)
   {
      // Build row div
      sb.Append(String.Format("<tr id="{0}_{1}"{2}>nt", 
         name, key(item).ToString(), 
         attributes["RowStyle"] != null 
            ? String.Format(format, attributes["RowStyle"]) : ""));
         
      foreach(var property in typeof(T).GetProperties())
      {
         // Build row item span
         string span = "<td id="{0}_{1}"{3}>{2}&lt;/td&gt;";
         var itm = property.GetValue(item, new object[] { });
         itm = itm != null ? itm : " ";
         sb.Append(String.Format(span, key(item), property.Name, itm, 
            attributes["ItemStyle"] != null 
               ? String.Format(format, attributes["ItemStyle"]) : ""));
      }
      sb.Append("n</tr>n");
   }
   sb.Append("n</table>");
   return sb.ToString();
}

public static string ToAjaxGrid<T, TKey>(this IEnumerable<T> list, 
                              Func<T, TKey> key, 
                              string name)
{
   return list.ToAjaxGrid<T, TKey>(key, name, new NameValueCollection(0));
}

Before scratching your head and calling me names, let's see if I can 'splain what I did. The two methods are the same with the exception of the NameValueCollection. The idea behind the NameValueCollection is to be able to pass in the actual CSS styles for the Table, Row, and Item. Now for the nitty gritty. First the data types passed in generically: ToAjaxGrid<T, TKey>. The T represents the actual entity (or the rows) and the TKey represents the type of the primary key. I figured I would eventually need to know the primary key in later work. The "Func<T, TKey> key" paramter is a lambda that takes the T object and produces a TKey object. When iterating through the rows, it is important to somehow keep track of the primary key (at least I think it is). The name is the DOM identifier for the table that we will use later. So now the looping magic! It uses reflection to infer the properties of type T and then loops through each T in the IEnumerable<T> and then through each property in T. And we are done!

Usage

Here is a snippet of what it looked like when I used it:

<% var col = new NameValueCollection(); %>
<% col.Add("TableStyle", "border: solid 1px #000000; width: 100%"); %>
<% col.Add("ItemStyle", "border: solid 1px #00FF00; spacing: 5px"); %>
<%= ViewData.Model.ToAjaxGrid&lt;studententity , int&gt;(s => s.StudentId, "students", col) %>

And what it looked like:

screen

Disclaimer

I have never done this before! If you think there is a smarter way, let me know so I can fix my stuff!

Your email address will not be published. Required fields are marked *

*