One of the drawbacks of the standard ASP.NET GridView control is that you can’t use the “dot” convention to bind object graphs when using the BoundField columns. This article explains how to do it with a new inherited column.
Suppose you have a typical object graph from the AdventureWorks model consisting of objects of the Order, OrderDetail, Product, ProductCategory, and ProductSubcategory classes as shown on the figure below. It’s not important how you get the graph, be it as a result of a LINQ-to-SQL or LINQ-to-Entities query or you have created it manually from a direct SQL query through ADO.NET. Our task is to create a simple grid of all items on a given order (represented by a collection of OrderDetail objects). The user is interested in the name of the product placed on the order, it’s category and subcategory and quantity ordered and unit price it was sold for. Note that the product name, category and subcategory are attributes of the Product object while quantity and unit price are attributes of the OrderDetail object itself. In the object world the standard way of getting information from “subordinate” objects is by traversing via object references (while in the relational world we would be issuing a JOIN statement).
If we were binding a single OrderDetail object to a FormView control, for example, we could use a perfectly valid Eval statements:
<%# Eval("Product.Name") %>
<%# Eval("Product.Subcategory.Name ") %>
<%# Eval("Product.Subcategory.Category.Name ") %>
However, a first try to use a BoundField column within a regular ASP.NET GridView control:
<asp:BoundField HeaderText="Product" DataField="Product.Name" />
results in the HttpException "field or property with the name 'Product.Name' was not found on the selected data source."
The problem is that a BoundField column looks up only for properties of the object it’s bound to and does not analyze the DataField string if it contains a navigation path to the property.
The solution is simple: in the attached sample project you find the NavigationBoundField class which inherits from the standard BoundField class and overrides the key method GetValue.
The code uses TypeDescriptors to retrieve object properties (via GetProperties method) and PropertyDescriptors to get value of a property (GetValue method).
Disclaimer: This article and its enclosed sample just demonstrates a single technical aspect. It by no means shows how to create a properly designed multi-layered application or how to write a properly designed code in a complex application.