Easy :"NO SCRIPT" DataGrid Tooltips
by Peter A. Bromberg, Ph.D.

Peter Bromberg

“A goal is a dream with a finish line.” --Duke Ellington

A frequent request I've seen here and elsewhere in my travels is the ability to add "tooltips" to various ASP.NET controls. There are a number of solutions to this, usually involving some heavy-duty Javacript, but so far I have never seen the one solution that to me is so obvious: Add a TITLE attribute!



First, let's look at the definition of this attribute:

title

Description
Specifies advisory information for the element.

Remarks
Internet Explorer 4.0 renders the title as a ToolTip when the user hovers the mouse over the element.

This property has read-write permissions and takes a string.

Syntax
object.title[ = "sMyString"]

Applies To:

A, ACRONYM, ADDRESS, APPLET, AREA, B, BASE, BASEFONT, BGSOUND, BIG, BLOCKQUOTE, BODY, BR, BUTTON, CAPTION, CENTER, CITE, CODE, COL, COLGROUP, COMMENT, DD, DEL, DFN, DIR, DIV, DL, DT, EM, EMBED, FIELDSET, FONT, FORM, FRAME, FRAMESET, H1, H2, H3, H4, H5, H6, HEAD, HR, I, IFRAME, IMG, INPUT, INS, KBD, LABEL, LEGEND, LI, LISTING, MAP, MARQUEE, MENU, META, NEXTID, OBJECT, OL, OPTION, P, PLAINTEXT, PRE, Q, S, SAMP, SCRIPT, SELECT, SMALL, SPAN, STRIKE, STRONG, SUB, SUP, TABLE, TBODY, TD, TEXTAREA, TFOOT, TH, THEAD, TITLE, TR, TT, U, UL, VAR, XMP

As we can see in the "Applies To" list of element names, you can stick a TITLE Attribute on just about ANYTHING! So how would we go about adding a TITLE attribute to a cell in a DataGrid? The answer is ItemDataBound. This event fires for every row that is added to a DataGrid control during DataBinding. First, let's look at what this sample grid looks like in the HTML (ASPX) declarative tag portion of the page:

<asp:DataGrid id="DataGrid1" style="Z-INDEX: 101; LEFT: 288px; POSITION: absolute; TOP: 152px"
    runat="server" BorderColor="#CC9966" BorderStyle="None" BorderWidth="1px" BackColor="White"
    CellPadding="4" AutoGenerateColumns="False">
    <SelectedItemStyle Font-Bold="True" ForeColor="#663399" BackColor="#FFCC66"></SelectedItemStyle>
    <ItemStyle ForeColor="#330099" BackColor="White"></ItemStyle>
    <HeaderStyle Font-Bold="True" ForeColor="#FFFFCC" BackColor="#990000"></HeaderStyle>
    <FooterStyle ForeColor="#330099" BackColor="#FFFFCC"></FooterStyle>
    <Columns>
     <asp:BoundColumn DataField="pubDate" HeaderText="pubDate"></asp:BoundColumn>
     <asp:HyperLinkColumn DataNavigateUrlField="link" DataTextField="title" HeaderText="Title" 
NavigateUrl="link"></asp:HyperLinkColumn> </Columns> <PagerStyle HorizontalAlign="Center" ForeColor="#330099" BackColor="#FFFFCC"></PagerStyle> </asp:DataGrid>

All I did above was design two columns. First is a text column assigned to the pubDate field of the datasource, and the other is a Hyperlink column with its DataNavigateUrl field assigned to the "link" column of the Data Source, and its "DataTextField" assigned to the "title" column of the Data Source. You'll see in a moment that I am populating the underlying DataSet using the ReadXml method of the DataSet class pointed to our main eggheadcafe.com RSS feed. Boy, that's an easy way to get a DataSet out of thin air! Now let's take a look at the codebehind and what's required to add a TITLE attribute to each "LINK" column in the grid as it is DataBound:


using System;

using System.Data;

using System.Web.UI;

using System.Web.UI.WebControls;

 

namespace EasyDataGridToolTips

{

    public class WebForm1 : Page

    {

        protected DataGrid DataGrid1;

        private DataSet ds;

 

        private void Page_Load(object sender, EventArgs e)

        {

            ds = new DataSet();

            ds.ReadXml("http://www.nullskull.com/rss.xml");

            this.DataGrid1.DataSource=ds.Tables[2];

            DataGrid1.DataBind();

        }

 

        #region Web Form Designer generated code

        override protected void OnInit(EventArgs e)

        {

            InitializeComponent();

            base.OnInit(e);

        }

 

        private void InitializeComponent()

        {   

            this.DataGrid1.ItemDataBound += new DataGridItemEventHandler(this.DataGrid1_ItemDataBound);

            this.Load += new EventHandler(this.Page_Load);

        }

        #endregion

 

        private void DataGrid1_ItemDataBound(object sender, DataGridItemEventArgs e)

        {

            int i = e.Item.DataSetIndex;

            ListItemType it = e.Item.ItemType;

            if(it == ListItemType.Item || it == ListItemType.AlternatingItem)

            {

                string strB =  (string)ds.Tables[2].Rows[i]["description"];

                e.Item.Attributes.Add("title", strB);

            }

        }

    }

}

 

And the result should look something like this on a mouseover:

 

 

You can see that when you pull an RSS feed directly into a DataSet, the "Items" aggregate normally turns out to be Table "2" - the third table in the DataSet. I hope this little exercise has been useful to you.

Download the Visual Studio.NET 2003 Solution that accompanies this article


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.
Article Discussion: