I just want to add a tooltip for each item in a combo box. i am using c#.net windows application.
There is no option like
combobox.items[1].tooltip();
Is there any way to add tooltip it ?
I just want to add a tooltip for each item in a combo box. i am using c#.net windows application.
There is no option like
combobox.items[1].tooltip();
Is there any way to add tooltip it ?
There are actually a couple reasonable solutions to this question. An MSDN forum has a ComboBox Item highlight event post that contains two possibilities, one from nobugz and one from agrobler. Each of them provides code to subclass a ComboBox that is supposed to handle tool tips on individual items in the ComboBox's dropdown. Agrobler's solution looks more polished, in that he/she even includes some nice illustrations, but unfortunately it is not clear (at least to me) how to populate the crucial ToolTipMember property of the control.
Both of these solutions appear to allow arbitrary tooltips assigned to individual items. A more specific, but more common case, is where you simply want the tooltip to mirror the text of the item, when you know you may have items that are too long to fit the width of the ComboBox. In my own case, I have an instance of a ComboBox that holds complete file paths so it is easy to see where the contents could exceed the ComboBox's width.
Zhi-Xin Ye, in the MSDN forum post Windows Dropdown question, provides a solution that addresses this more specific problem and is much simpler. I reproduce the code here in its entirety. (Note that this code presupposes you have created a Form called Form1 and hooked up the load handler shown, and also added a ComboBox named comboBox1 and a tool tip handler toolTip1.)
private void Form1_Load(object sender, EventArgs e)
{
this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
this.comboBox1.DrawItem += new DrawItemEventHandler(comboBox1_DrawItem);
}
void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
string text = this.comboBox1.GetItemText(comboBox1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{ e.Graphics.DrawString(text, e.Font, br, e.Bounds); }
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{ this.toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
else { this.toolTip1.Hide(comboBox1); }
e.DrawFocusRectangle();
}
While simple and concise, this code does suffer from one defect (as is pointed out in a reply on the above MSDN thread): as you move the mouse (without clicking) from one dropdown item to the next, only every other one shows a persistent tooltip! The fix is only hinted at by yet another entry on that thread, so I thought it would be useful to provide the full, corrected code here:
private void Form1_Load(object sender, EventArgs e)
{
comboBox1.DrawMode = DrawMode.OwnerDrawFixed;
comboBox1.DrawItem += comboBox1_DrawItem;
comboBox1.DropDownClosed += comboBox1_DropDownClosed;
}
private void comboBox1_DropDownClosed(object sender, EventArgs e)
{
toolTip1.Hide(comboBox1);
}
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) { return; } // added this line thanks to Andrew's comment
string text = comboBox1.GetItemText(comboBox1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{ e.Graphics.DrawString(text, e.Font, br, e.Bounds); }
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{ toolTip1.Show(text, comboBox1, e.Bounds.Right, e.Bounds.Bottom); }
e.DrawFocusRectangle();
}
Besides removing a few redundant portions of code (e.g. the "this" qualifier) the primary difference is moving the toolTip1.Hide call into the DropDownClosed event handler. Taking it out of the DrawItem handler eliminates the defect mentioned above; but then you need to close it when the drop down closes, otherwise the last displayed tooltip will remain onscreen.
2012.07.31 Addendum
Just wanted to mention that I have since created a composite ComboBox that incorporates this tooltip capability so if you use my library you have no code to write at all. Just drag a ComboBoxWithTooltip onto the Visual Studio designer and you are done. Drill down to ComboBoxWithTooltip on my API page or download my open-source C# library to get started. (Note that the patch for the bug Andrew caught will be in release 1.1.04, due out soon.)
private void comboBox1_SelectedIndexChanged(object sender, System.EventArgs e)
{
ToolTip toolTip1 = new ToolTip();
toolTip1.AutoPopDelay = 0;
toolTip1.InitialDelay = 0;
toolTip1.ReshowDelay = 0;
toolTip1.ShowAlways = true;
toolTip1.SetToolTip(this.comboBox1, comboBox1.Items[comboBox1.SelectedIndex].ToString()) ;
}
My solution:
ToolTip toolTip = new ToolTip() { AutoPopDelay = 0, InitialDelay = 0, ReshowDelay = 0, ShowAlways = true, };
comboBox.DrawMode = DrawMode.OwnerDrawFixed;
comboBox.DrawItem += (s, e) =>
{
e.DrawBackground();
string text = comboBox.GetItemText(comboBox.Items[e.Index]);
using (SolidBrush br = new SolidBrush(e.ForeColor))
e.Graphics.DrawString(text, e.Font, br, e.Bounds);
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && comboBox.DroppedDown)
toolTip.Show(text, comboBox, e.Bounds.Right, e.Bounds.Bottom + 4);
e.DrawFocusRectangle();
};
comboBox.DropDownClosed += (s, e) =>
toolTip.Hide(comboBox);
Building upon the solution from Michael Sorens (fixed a few bugs and added features). A few things this does:
e.index>0
in the second if
statement).It does not display the tooltip when the dropdown is CLOSED.
private void comboBox1_DrawItem(object sender, DrawItemEventArgs e)
{
ComboBox comboBox1 = (ComboBox)sender;
if (e.Index >= 0)
{//Draws all items in drop down menu
String text = comboBox1.GetItemText(comboBox1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(text, e.Font, br, e.Bounds);
}
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && e.Index > 0 && comboBox1.DroppedDown)
{//Only draws tooltip when item 1+ are highlighted. I had a "--" placeholder in the 0 position
try
{
XmlDocument doc;
XmlNode testNode;
doc = new XmlDocument();
String testXMLDoc = String.Format(@"{0}\{1}.xml", filePath, fileName);//global variables
String toolTip = "---Preview of File---";
doc.Load(testXMLDoc);
testNode = doc.SelectSingleNode("/Books");
if (testNode.HasChildNodes)
{
XmlNodeList nodeList = testNode.SelectNodes("Book");
foreach (XmlNode xmlNode in nodeList)
{
toolTip += "\r\n" + xmlNode.SelectSingleNode("Title").InnerXml;
}
}
this.toolTipHelp.Show(toolTip, comboBox1, e.Bounds.Right, e.Bounds.Bottom);
}
catch (Exception tp)
{
Debug.WriteLine("Error in comboBox1 tooltip: " + tp);
}
}
else
{
this.toolTipHelp.Hide(comboBox1);
}
}
else
{
this.toolTipHelp.Hide(comboBox1);
}
e.DrawFocusRectangle();
}
You will need to create your own UserControl.
Having a ToolTip for each item in a combobox is an unusual requirement; perhaps you could use a 2 column combobox instead?
If you are loading from a datasource, get the data into datatable and set the same to combobox. My datatable has three columns ID,NAME,DEFINITION. Below is my code :
InputQuery = "select * from ds_static_frequency";
TempTable = UseFunc.GetData(InputQuery);
cmbxUpdateFrequency.DataSource = TempTable;
cmbxUpdateFrequency.DataTextField = "NAME";
cmbxUpdateFrequency.DataValueField = "ID";
cmbxUpdateFrequency.DataBind();
foreach (DataRow dr in TempTable.Rows)
{
int CurrentRow = Convert.ToInt32(dr["ID"].ToString());
cmbxUpdateFrequency.Items[CurrentRow - 1].ToolTip = dr["Definition"].ToString();
}
My solution:
public class ToolTipComboBox: ComboBox
{
#region Fields
private ToolTip toolTip;
private bool _tooltipVisible;
private bool _dropDownOpen;
#endregion
#region Types
[StructLayout(LayoutKind.Sequential)]
// ReSharper disable once InconsistentNaming
public struct COMBOBOXINFO
{
public Int32 cbSize;
public RECT rcItem;
public RECT rcButton;
public ComboBoxButtonState buttonState;
public IntPtr hwndCombo;
public IntPtr hwndEdit;
public IntPtr hwndList;
}
public enum ComboBoxButtonState
{
// ReSharper disable once UnusedMember.Global
StateSystemNone = 0,
// ReSharper disable once UnusedMember.Global
StateSystemInvisible = 0x00008000,
// ReSharper disable once UnusedMember.Global
StateSystemPressed = 0x00000008
}
[DllImport("user32.dll")]
public static extern bool GetComboBoxInfo(IntPtr hWnd, ref COMBOBOXINFO pcbi);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool GetWindowRect(IntPtr hwnd, out RECT lpRect);
#endregion
#region Properties
private IntPtr HwndCombo
{
get
{
COMBOBOXINFO pcbi = new COMBOBOXINFO();
pcbi.cbSize = Marshal.SizeOf(pcbi);
GetComboBoxInfo(Handle, ref pcbi);
return pcbi.hwndCombo;
}
}
private IntPtr HwndDropDown
{
get
{
COMBOBOXINFO pcbi = new COMBOBOXINFO();
pcbi.cbSize = Marshal.SizeOf(pcbi);
GetComboBoxInfo(Handle, ref pcbi);
return pcbi.hwndList;
}
}
[Browsable(false)]
public new DrawMode DrawMode
{
get { return base.DrawMode; }
set { base.DrawMode = value; }
}
#endregion
#region ctor
public ToolTipComboBox()
{
toolTip = new ToolTip
{
UseAnimation = false,
UseFading = false
};
base.DrawMode = DrawMode.OwnerDrawFixed;
DrawItem += OnDrawItem;
DropDownClosed += OnDropDownClosed;
DropDown += OnDropDown;
MouseLeave += OnMouseLeave;
}
#endregion
#region Methods
private void OnDropDown(object sender, EventArgs e)
{
_dropDownOpen = true;
}
private void OnMouseLeave(object sender, EventArgs e)
{
ResetToolTip();
}
private void ShowToolTip(string text, int x, int y)
{
toolTip.Show(text, this, x, y);
_tooltipVisible = true;
}
private void OnDrawItem(object sender, DrawItemEventArgs e)
{
ComboBox cbo = sender as ComboBox;
if (e.Index == -1) return;
// ReSharper disable once PossibleNullReferenceException
string text = cbo.GetItemText(cbo.Items[e.Index]);
e.DrawBackground();
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected)
{
TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, SystemColors.Window);
if (_dropDownOpen)
{
Size szText = TextRenderer.MeasureText(text, cbo.Font);
if (szText.Width > cbo.Width - SystemInformation.VerticalScrollBarWidth && !_tooltipVisible)
{
RECT rcDropDown;
GetWindowRect(HwndDropDown, out rcDropDown);
RECT rcCombo;
GetWindowRect(HwndCombo, out rcCombo);
if (rcCombo.Top > rcDropDown.Top)
{
ShowToolTip(text, e.Bounds.X, e.Bounds.Y - rcDropDown.Rect.Height - cbo.ItemHeight - 5);
}
else
{
ShowToolTip(text, e.Bounds.X, e.Bounds.Y + cbo.ItemHeight - cbo.ItemHeight);
}
}
}
}
else
{
ResetToolTip();
TextRenderer.DrawText(e.Graphics, text, e.Font, e.Bounds.Location, cbo.ForeColor);
}
e.DrawFocusRectangle();
}
private void OnDropDownClosed(object sender, EventArgs e)
{
_dropDownOpen = false;
ResetToolTip();
}
private void ResetToolTip()
{
if (_tooltipVisible)
{
// ReSharper disable once AssignNullToNotNullAttribute
toolTip.SetToolTip(this, null);
_tooltipVisible = false;
}
}
#endregion
}
Below is c# code to show tool tip on item of combo box whose width is greater than width of combo box control. Tool tip will be shown once user hover on such combo box:
this.combo_box1.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
this.combo_box1.DrawMode = DrawMode.OwnerDrawFixed;
this.combo_box1.DrawItem += new DrawItemEventHandler(combo_box1_DrawItem);
this.combo_box1.DropDownClosed += new EventHandler(combo_box1_DropDownClosed);
this.combo_box1.MouseLeave += new EventHandler(combo_box1_Leave);
void combo_box1_DrawItem(object sender, DrawItemEventArgs e)
{
if (e.Index < 0) { return; }
string text = combo_box1.GetItemText(combo_box1.Items[e.Index]);
e.DrawBackground();
using (SolidBrush br = new SolidBrush(e.ForeColor))
{
e.Graphics.DrawString(text, e.Font, br, e.Bounds);
}
if ((e.State & DrawItemState.Selected) == DrawItemState.Selected && combo_box1.DroppedDown)
{
if (TextRenderer.MeasureText(text, combo_box1.Font).Width > combo_box1.Width)
{
toolTip1.Show(text, combo_box1, e.Bounds.Right, e.Bounds.Bottom);
}
else
{
toolTip1.Hide(combo_box1);
}
}
e.DrawFocusRectangle();
}
private void combo_box1_DropDownClosed(object sender, EventArgs e)
{
toolTip1.Hide(combo_box1);
}
private void combo_box1_Leave(object sender, EventArgs e)
{
toolTip1.Hide(combo_box1);
}
private void combo_box1_MouseHover(object sender, EventArgs e)
{
if (!combo_box1.DroppedDown && TextRenderer.MeasureText(combo_box1.SelectedItem.ToString(), combo_box1.Font).Width > combo_box1.Width)
{
toolTip1.Show(combo_box1.SelectedItem.ToString(), combo_box1, combo_box1.Location.X, combo_box1.Location.Y);
}
}
Here is the link for more details - http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html
With WPF use a ComboBox.ItemTemplate
<ComboBox
ItemsSource="{Binding Path=ComboBoxItemViewModels}"
SelectedValue="{Binding SelectedComboBoxItem,
SelectedValuePath="Name"
>
<ComboBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Path=Name}" ToolTip="{Binding Path=Description}"/>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>