Friday, May 4, 2012

Displaying data with <%# %>, OnDataItemBound or use OnDataBinding in ASP.net?

This has been on my mind for years and I have seen both and used both in different projects the last 10 years. But which is better or preferred?

As an example consider a ListView which will bind to a poco called Employee which has properties Name and EmployedSince. The ListView will display the name of the employee as well as how long the user has been employed in years.

public class Employee
{
    public string Name { get; set; }
    public DateTime EmployedSince { get; set; }
}

A simple template for displaying this using <%# %> syntax is show below.

<asp:ListView runat="server" ID="employeeList">
    <LayoutTemplate>
        <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        <div>
        Name: <%#((Employee)Container.DataItem).Name%>
        - Years Employed: <%# (int)((DateTime.Now - ((Employee)Container.DataItem).EmployedSince).TotalDays / 365)  %>
        </div>
    </ItemTemplate>
</asp:ListView>

There are two other alternatives. One is to use the OnItemDataBound event on the ListView, which I don’t like myself as you have to use FindControl to find and bind each specific control. It sort of goes against my nature to look for controls by a name. I like my code strongly typed.

The other approach is to use OnDataBinding per element in the ItemTemplate as shown below.

<asp:ListView runat="server" ID="employeeList">
    <LayoutTemplate>
        <asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
    </LayoutTemplate>
    <ItemTemplate>
        <div>
            Name: <asp:literal runat="server" OnDataBinding="NameOnDataBinding" />
            - Years Employed: <asp:literal runat="server" OnDataBinding="YearsOnDataBinding" />
        </div>
    </ItemTemplate>
</asp:ListView>

And with the following code behind.

protected void NameOnDataBinding(object sender, EventArgs e)
{
    ListViewDataItem bindingContainer = (ListViewDataItem)(((Control)sender).BindingContainer);
    Employee employee = (Employee)bindingContainer.DataItem;
    Literal literal = (Literal)sender;
    literal.Text = employee.Name;
}

protected void YearsOnDataBinding(object sender, EventArgs e)
{
    ListViewDataItem bindingContainer = (ListViewDataItem)(((Control)sender).BindingContainer);
    Employee employee = (Employee)bindingContainer.DataItem;
    Literal literal = (Literal)sender;
    literal.Text = ((DateTime.Now - employee.EmployedSince).TotalDays/365).ToString("0");
}

So, even though the latter requires more lines of code I prefer it above the first one. The reason why is that adding controls with good binding names clearly states the intent, which is lost when writing code logic in the markup.

This is especially true for the number of years which have logic in it. I can agree that the Name property works for the first approach as well.

I know that there is quite a lot of casting going on in the code behind, but this is boilerplate code which you get used to both reading and writing after a while, and in my eyes it’s still readable.

What are your take on binding data in markup or in code behind, and which approach do you prefer?