Simple little things. Placing dynamic images in databound controls

Sometimes there’s these really little things that hardly seem worth the effect blogging about. But when you start googling for the apparent solution, there’s a million-and-one blogs, forum questions that at the least are contradicting.

In this particular case I wanted to set different images in different rows in a Repeater or GridView depending on some property of the domain object I’m binding to. This seems to be pretty straigtforward. And it is. However it’s all these little details that still take up some much time googling, trying them out, debugging that makes it nasty enough.

So a live example. I have a class called ValidationResult. This class has a number of properties, such as Name, Description, but also a Severity. The type of Severity is the following enum.

public enum ValidationResultSeverity
{
    Success = 0,
    Informational = 1,
    Warning = 2,
    Error = 3
}

Nothing fancy here.

Now I’ve created small iconic images that match the names of the elments in the enum. So there’s an image informational.gif, warning.gif, etc. You get the picture. The images resides in a sub-directory called Images in my web project.

image

Next I’ve defined a user control with a Repeater control on it. In code this Repeater is databound to a List<ValidationResult>, using the following code.

List<ValidationResult> views = FormatMessages(validationResults);
 
repException.DataSource = views;
repException.DataBind();

This straightforward code causes the individual items (rows) in the Repeater to bind to the properties of one of the ValidationResult items in the list.

The Repeater is defined as follows. Most noteworthy is the construct I’ve used to bind the images of course. After googling and puzzling a bit I came up with the following simple solution.

<asp:Repeater ID="repException" runat="server">
      <ItemTemplate>
      <tr>
         <td valign="middle">
              <asp:Image ID="imbIcon" runat="server" Width="11" ImageUrl='<%# "~/images/" + DataBinder.Eval(Container.DataItem, "Severity") + ".gif" %>'></asp:Image>
          </td>
          <td valign="middle">
              <asp:Label runat="server"><%#DataBinder.Eval(Container.DataItem, "Message") %></asp:Label>
          </td>
      </tr>
      </ItemTemplate>
  </asp:Repeater>

Nothing too difficult use of DataBinder.Eval() constructions. I’m not very fond of Eval(), simply because of it’s use of strings, which make binding very type unsafe, but it this case I stuck to it.

But note the most interesting code fragmet in here.

ImageUrl='<%# "~/images/" + DataBinder.Eval(Container.DataItem, "Severity") + ".gif" %>'

This very little fragment took me about 20 minutes to get it right. Why? Well, first you will try to use the literals "~/images/" and ".gif" outside of the Eval() expression, just because it seems more logical. Doesn’t work – at least not how I like it. Compiling renders invalid tag errors. Next you find all kinds of blogs that put these literals inside of the expression. Still no result. You will have to be really careful here. And only then I thought of putting the whole expression between single quotes instead of double quotes, which you would do normally. And then it works, as you can see below.

image