20 Jul, 2009 in Programming by

Assigning images to enums for databinding in ASP.NET

;

I jazzed up a boring event log table in an ASP.NET web application by replacing an INT property with an image representation. The INT property is also mapped to an Enum for easy access to the logical record types.

Take this MS SQL 2005 Table for example:

Logs:

ID int, primary key, auto increment,

Timestamp datetime,

Type int,

Message varchar(255)

I’m using SubSonic to generate the data access layer, so there is a corresponding Log class.

However, when setting the Type property, I use this enum for convenience:

enum LogType:

    public enum LogType
    {
        Information,      
        RecordCreated,
    }

So now when I wire up a DataList to an ObjectDataSource to connect to the SubSonic LogController, I get this simple table:

event log datagrid

But the “Type” field is not very useful and an icon could simply describe what type of event occurred.

Now we get to the point of this post. :)

After recently playing with basic databinding to enums and discovering an easy trick for displaying custom descriptions for each enum element, I simply applied the same logic to this problem. I created my own attribute class to keep track of image filenames for each element of the LogType enum.

class EnumImageAttribute:

public class EnumImageAttribute : Attribute
    {
        private string _imageName;
        
        ///<summary>
        /// Constructor
        /// </summary>
        /// <param name="imageName">A  string</param>
        public EnumImageAttribute(string imageName)
        {
            _imageName = imageName;
        }
        
        public string ImageName
        {
            set {
                _imageName = value;
            }
            
            get {
                return _imageName;
            }
        }
 
        public static string GetImageName(Enum logType)
        {
            if (logType == null)
            {
                throw new ArgumentNullException("logType");
            }
 
            string r = null;
 
            FieldInfo fieldInfo = logType.GetType().GetField(logType.ToString());
            EnumImageAttribute[] attribs = (EnumImageAttribute[])fieldInfo.GetCustomAttributes(typeof(EnumImageAttribute), false);
 
            if (attribs != null && attribs.Length > 0)
            {
                r = attribs[0].ImageName;
            }
 
            return r;            
        }
    }

Then I applied this attribute to the LogType enum:

    public enum LogType
    {
        [EnumImage("information.png")]
        Information,
        [EnumImage("page_add.png")]
        RecordCreated,
    }

Now I had to override the DataList ItemDataBound event to lookup the attribute for the value of the Log.Type property.

        protected void DataList1_ItemDataBound(object sender, DataListItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Header || e.Item.ItemType == ListItemType.Footer)
                return;
 
            Log log = (Log)e.Item.DataItem;
            LogType logType = (LogType)Enum.Parse(typeof(LogType), log.LogType.ToString());
 
            Image imgLogType = (Image)e.Item.FindControl("imgLogType");
            imgLogType.AlternateText = log.Message;
            imgLogType.ImageUrl = string.Format("~/Images/{0}", EnumImageAttribute.GetImageName(logType));
        }

The real magic is in the EnumImageAttribute class. A better idea would probably be to separate the GetImageName method out into a generic EnumHelper class. But since this is the only attribute I’m using, I just stuck in all in one class for less clutter.

Here is the ASP.NET code for the DataList templates:

    <asp:DataList ID="DataList1" runat="server" DataSourceID="ObjectDataSource1" RepeatLayout="Flow" OnItemDataBound="DataList1_ItemDataBound">
        <HeaderTemplate>
            <table cellpadding="5" width="100%" border="1">
            <tr><th>Timestamp</th><th>Message</th></tr>
        </HeaderTemplate>
        <ItemTemplate>            
            <tr>
            <td>
            <asp:Label ID="TimestampLabel" runat="server" Text='<%# Eval("Timestamp") %>'></asp:Label>
            </td>            
            <td>
            <asp:Image ID="imgLogType" runat="server" ImageAlign="AbsMiddle" />&nbsp;<asp:Label ID="MessageLabel" runat="server" Text='<%# Eval("Message") %>'></asp:Label>
            </td>
            </tr>
        </ItemTemplate>
        <FooterTemplate>
        </table>
        </FooterTemplate>

This is the final result:

event log datalist

Icons now simply represent the type of event that occurred.

If you found this post useful, let me know with a comment! 🙂

Share on Twitter

No Responses so far | Have Your Say!

Comments are closed.