I've run into a couple of situations where I need more than simple databinding in ASP.NET. Sometimes I need some to bind a thing conditionally.
Ok, so let's say you have a collection of addresses that you want to bind to a DataList. The markup might look something like this:
<asp:DataList ID="DataList1" runat="server">
<ItemTemplate>
<asp:Panel ID="AddressPanel" runat="server" CssClass="address">
<asp:Label ID="Address" runat="server" Text='<%# Eval("address") %>' /><br />
<asp:Label ID="City" runat="server" Text='<%# Eval("city") %>' /><br />
<asp:Label ID="PostalCode" runat="server" Text='<%# Eval("postalcode") %>' />
</asp:Panel>
</ItemTemplate>
</asp:DataList>
Now, let’s say that you would really like to highlight all addresses where the zip code starts with "902". Let's take the AddressPanel in the ItemTemplate and bind its CssClass property like this:
<asp:Panel ID="AddressPanel" runat="server" CssClass='<%# Eval("postalcode") %>'> ...
That gets us a little closer. It we wanted to brute force it we could create a css class for every possible zip code variation. (Yeah, okay.)
Instead, let’s create a protected method on the containing page:
protected string GetCssForPostalCode(object dataItem)
{
DataRowView row = dataItem as DataRowView;
if (row["postalcode"].ToString().StartsWith("902")) return "highlight-address";
return "normal-address";
}
We can use this method to decide what data should be bound. So how do we connect this back to our ItemTemplate in the DataList?
The first thing to understand is that Eval() is a shortcut function for calling DataBinder.Eval(). To perform the data-binding without Eval() looks like this:
<%#DataBinder.Eval(Container.DataItem, "postalcode")%>
I’m not sure what the proper nomenclature is for this, but the # enables the use of DataBinder as well as Container.
So here’s the trick, instead of calling DataBinder.Eval() you can call your own method. In this case GetCssForPostalCode(). So the end result will look like this:
<asp:DataList ID="DataList1" runat="server">
<ItemTemplate>
<asp:Panel ID="AddressPanel" runat="server" CssClass='<%#GetCssForPostalCode(Container.DataItem)%>'>
<asp:Label ID="Address" runat="server" Text='<%# Eval("address") %>' /><br />
<asp:Label ID="City" runat="server" Text='<%# Eval("city") %>' /><br />
<asp:Label ID="PostalCode" runat="server" Text='<%# Eval("postalcode") %>' />
</asp:Panel>
</ItemTemplate>
</asp:DataList>
Also see Rob Eisenberg's series of posts on .NET 3.0 to learn how WPF addresses this problem (though not for the Web).