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}</td>";
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<studententity , int>(s => s.StudentId, "students", col) %></pre>
And what it looked like:
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 Thoughts?
- Does it make sense?
- Did it help you solve a problem?
- Were you looking for something else?