Monday, July 27, 2009

Showing a Separate Tooltip for Each Item in a ListBox

http://www.codeproject.com/KB/combobox/ToolTipForListBox.aspx

Introduction

ListBox is a very common control used in Windows Forms. Most often we would need to show some information on each item in the ListBox when the user places the mouse pointer above that item. Sadly there is no straight forward way to do that. The reasons are:

  1. There is no separate mouse hover event for individual items in the list.
  2. As each item in the list is not a control (of course!!), we cannot set a tool tip for items of the list separately. A tooltip can be set only for the ListBox as such.

But don't give up!! If there is a will, there is a way…

Using the Code

The steps required are explained below:

  1. Drag and drop a ToolTip control into the form having the ListBox. I am calling it ListToolTip.

  2. We have to know the ToolTip text for each item in the ListBox. I have an array of strings as items in the ListBox. So I maintain the ToolTip text for each item in another string array. So if I know the index of the Item in the array of items, I can get the corresponding ToolTip text from the ToolTip array using the same index.

  3. Create a handler for the Mouse Move event of the ListBox. Calculate the index of the item over which the mouse pointer is placed now. (This is the tricky part!!)

    1. Calculate the Offset of the item from the top of the list box. This can be obtained by dividing the Y coordinate of the house position by the height of each item. Height of each item is a property of the list box:

      Collapse
      itemIndex = e.Y / objListBox.ItemHeight; 
    2. But the topmost item will not always be the first item in the list. If there is a scrollbar and user scrolls down, then the topmost item visible will change. This means that the index obtained above is not the index of the required item in the list of items. Fortunately ListBox has another property called TopIndex. If we add the TopIndex with the index obtained in the above step, then we will get the correct index.

      Collapse
      itemIndex += objListBox.TopIndex;
  4. Now we know the index of the item over which the mouse pointer is placed. Just take the Tooltip of that item from the Tooltip array and associate it with the ToolTip control.

    Collapse
     if ((itemIndex >= 0) && (itemIndex < m_arrItemToolTips.Length))
    {
    ListToolTip.SetToolTip(objListBox, m_arrItemToolTips[itemIndex]);

    }
  5. If the calculated index is out of the range of valid indexes, hide the ToolTip.

    Collapse
      else
    {
    ListToolTip.Hide(objListBox);
    }

The entire code for the mouse move event handler is given below:

Collapse
private void ItemsListBox_MouseMove(object sender, MouseEventArgs e)

{
try
{
ListBox objListBox = (ListBox)sender;
int itemIndex = -1;
if (m_arrItemToolTips != null)

{
if (objListBox.ItemHeight != 0)
{
itemIndex = e.Y / objListBox.ItemHeight;

itemIndex += objListBox.TopIndex;
}
if ((itemIndex >= 0) && (itemIndex < m_arrItemToolTips.Length))

{
ListToolTip.SetToolTip(objListBox, m_arrItemToolTips[itemIndex]);
}
else
{
ListToolTip.Hide(objListBox);

}
}
}
catch (Exception ex)
{
}
}

No comments: