Thursday, January 15, 2009

How to Add a Tooltip to a Dropdown List

It is common in most web pages that whole text in dropdown lists cannot be seen due to width limitation. One solution for this would be adding tooltip for the dropdown, so that when selecting a value from dropdown, whole text will be appear as a tooltip. For most of browsers implementing tooltip on dropdown control is not a big deal. We can simply add tooltip text with 'title' attribute. C# implementation for this would be as follows;

public static void BindTooltip(DropDownList ddl) {
for (int i = 0; i < ddl.Items.Count; i++)
{
ddl.Items[i].Attributes.Add("title", ddl.Items[i].Text);
}
}

But this will not work in Internet Explorer version 6, as IE V6 does not support the 'title' attribute on the <select> control. (IE 7, Firefox … support the 'title' attribute). This is because IE 6 creates a separate window/layer for the <select> tag that is above the rest of the browser window. And Tooltip property is also not working in IE V6.

A partial solution for this issue is add a separate <div> to the form, set the required text, and show/hide that <div> based on mouse activity over dropdown list. Anyway this method will not show the tooltip when selecting an item from the dropdown list. But once you selected an item and move the mouse over dropdown list, it will show the tool tip. Here is the implementation;

DropDown
ddlNames.ID = "DDL_NAMES_ID";
ddlNames.Width = 100;
ddlNames.DataSource = dtNames;
ddlNames.DataTextField = "Full_Name";
ddlNames.DataValueField = "Reg_ID";
ddlNames.DataBind();
ddlNames.Attributes.Add("onmouseover", "showDropDownToolTip(this);");
ddlNames.Attributes.Add("onmouseout", "hideDropDownToolTip();");

DIV
<div id="divDropDownToolTip" style="position:absolute; display:none; background:lightyellow; border:1px solid gray; padding:2px; font-size:8pt; font-family:Verdana;" onMouseOut
="hideDropDownToolTip()">
<span id="toolTipText"></span>
</div>

Java Script
protected override void OnPreRender(EventArgs e)
{
string script = string.Concat(@"
<script type=""text/javascript"" language=""javascript"">
function showDropDownToolTip(ddl){
if ( ddl.options[ddl.selectedIndex].value == '')
return;
var toolTipSpan = document.getElementById('toolTipText');
toolTipSpan.innerHTML = ddl.options[ddl.selectedIndex].text;
var toolTipDiv = document.getElementById('divDropDownToolTip');
toolTipDiv.style.top = window.event.clientY + 140;
toolTipDiv.style.left = window.event.clientX;
toolTipDiv.style.display = 'block';
}

function hideDropDownToolTip()
{
document.getElementById('divDropDownToolTip').style.display = 'none';
}
</script>");

Page.ClientScript.RegisterClientScriptBlock(this.GetType(), "NamesToolTipControl", script);
}

Thursday, January 1, 2009

Passing an Event to the Parent Control by Using Delegates

For the purpose implementation of inner control should implement event handler, custom argument class and delegate. Custom argument class is used to pass inner control specific values to the container control.

using System.Web.UI.WebControls;

namespace InteractiveControls{
// Interactive Control
public class MyInteractiveControl : CompositeControl
{
/// <summary>
/// Event for delegate method
/// </summary>
public event ShowClickEventHandler ShowClicked;

/// <summary>
/// Button control
/// </summary>
private Button btnShow;

/// <summary>
/// CreateChildControls is responsible for creating the controls to form this composite control
/// </summary>
protected override void CreateChildControls()
{
this.btnShow = new
Button();
this.btnShow.Text = "Show";
this.btnShow.Click += new
EventHandler(btnShow_Click);
this.Controls.Add(btnShow);
}

private void btnShow_Click(object sender, EventArgs e)
{
OnShowClick(new ShowClickEventArgs(25, 100));
}
void OnShowClick(ShowClickEventArgs e)
{
ShowClicked(this, e);
}
}

/// <summary>
/// Delegate method for Show button clicked event handler
/// </summary>
public delegate void ShowClickEventHandler(object sender, ShowClickEventArgs e);
/// <summary>
/// Event argument class for ShowClickEventArgs
/// </summary>
public class ShowClickEventArgs : EventArgs
{
private int m_From;
private int m_To;
public ShowClickEventArgs(int from, int to)
{
this.m_From = from;
this.m_To = to;
}
public int From
{
get { return m_From; }
}
public int To
{
get { return m_To; }
}
}
}

'MyInteractiveControl_ShowClicked' method in the container control will be invoked in 'Show' button click, which is residing in the inner control. By implementing custom argument class appropriately, can access values in the interactive control from container control.

namespace ContainerControls
{
// Container Control
public class MyInteractiveControl : CompositeControl
{
protected override void CreateChildControls()
{
MyInteractiveControl ctrl = new MyInteractiveControl();
ctrl.ShowClicked += new ShowClickEventHandler(MyInteractiveControl_ShowClicked);
this.Controls.Add(ctrl);
}

/// <summary>
/// Event fires when the Show button clicked
/// </summary>
private void MyInteractiveControl_ShowClicked(object sender, ShowClickEventArgs e)
{
Controls.Add(new
LiteralControl(string.Concat("From:", e.From.ToString(), " - To:", e.To.ToString())));
}
}
}

More about delegates.....