Fixing BoundField Support for Composite Objects

An entry about asp.net Publication date 15. June 2007 20:24

A few posts ago, I wrote about how one could implement a custom GridView field type to help minimize the markup bloat which is often the result of too many TemplateFields. Here's another great example of how easy it is to implement a custom field type. Assume we have the following objects:

Person and Address classes

As you can see, we have a Person class, which (among a few others) has an Address property of type Address. In Windows Forms, if you wanted to list a set of such Persons in a grid and display the City, PostCode and Street fields in columns, you'd have to implement the interface ITypedList on the collection you would databind against, supplying a custom schema. I might make a post about that later, but for now we're focusing on how to solve this in ASP.NET. You would be forgiven for thinking that just passing "Address.City" as the DataField in a BoundField should work:

<asp:GridView
    ID="_grid"
    runat="server"
    AutoGenerateColumns="false">
    <Columns>
        <asp:BoundField HeaderText="City" DataField="Address.City" />
    </Columns>
</asp:GridView>

After all, DataBinder.Eval would allow this. The BoundField will complain that there is no field or property on Person called "Address.City" however; instead of using the DataBinder internally it has its own more naive property value lookup algorithm, and doesn't realise that you want it to do a recursive lookup. The quick fix? Just use DataBinder.Eval:

<asp:GridView
    ID="_grid"
    runat="server"
    AutoGenerateColumns="false">
    <Columns>
        <asp:TemplateField HeaderText="City">
            <ItemTemplate>
                <%# Eval("Address.City") %>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

But if you're like me, all that extra markup will get tedious really fast - why not just "fix" BoundField instead? Lets create our own extention of it which we'll call CompositeBoundField, and implement it the way the ASP.NET team should have, had they reused their own code instead of reinventing the wheel ;)

public class CompositeBoundField : BoundField
{
protected override object GetValue(Control controlContainer)
{
object item = DataBinder.GetDataItem(controlContainer);
return DataBinder.Eval(item, this.DataField);
}
}

That is merely two lines of code - which does more than the original BoundField.GetValue implementation did, allowing us to clean up the markup again:

<asp:GridView
    ID="_grid"
    runat="server"
    AutoGenerateColumns="false">
    <Columns>
        <cc:CompositeBoundField HeaderText="City" DataField="Address.City" />
    </Columns>
</asp:GridView>

And not only does it support things like "Address.City", but the DataBinder.Eval function will even evaluate expressions indexing into arrays - you could for example set the DataField to "Addresses[0].City", if you had an array of Address objects. Pretty neat! :)

Currently rated 3.9 by 19 people

  • Currently 3.947368/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Comments

Powered by BlogEngine.NET 1.4.5.0

Welcome!

My name is Fredrik Kalseth, and this is my blog - thanks for visiting! I am fortunate enough to work with what I love for a living, and this blog is essentially the biproduct of that.

I work as a senior consultant for Capgemini, and am also an active participant in the Norwegian .NET community, as an avid attendee but also as a speaker (most recently at NNUG and MSDN Live).

As a developer, I have a wide circle of interest. My primary passion is for agile, test-driven development, with focus on best practices and clean code. That said, I also love to work on the frontend, especially with web development.

On Twitter? My handle is fkalseth. On LinkedIn? I`m there too.


Disclaimer

This is a personal blog; any opinions expressed here are my own and do not necessarily reflect those of my employer. All content herein is my own original creation, and as such is protected by copyright law. Unless otherwise stated, all source code posted on this blog is freely usable under the Microsoft Permissive License.

What Readers Talk About

Comment RSS