我只想为组合框中的每个项添加工具提示。我正在使用c#.net windows应用程序。
没有像
这样的选项combobox.items [1] .tooltip();
有没有办法添加工具提示呢?
答案 0 :(得分:30)
这个问题实际上有几个合理的解决方案。 MSDN论坛有一个ComboBox Item highlight event帖子,其中包含两种可能性, 一个来自nobugz,另一个来自agrobler。它们中的每一个都提供了一个代码,用于子类化ComboBox,该ComboBox应该处理ComboBox下拉列表中各个项目的工具提示。 Agrobler的解决方案看起来更加精致,因为他/她甚至包含了一些不错的插图,但不幸的是,至少对我来说,如何填充控件的关键ToolTipMember属性并不清楚。
这两种解决方案似乎都允许为各个项目分配任意工具提示。更具体但更常见的情况是,当您知道可能有太长的项目无法适应ComboBox的宽度时,您只需要工具提示镜像项目的文本。在我自己的情况下,我有一个ComboBox实例,它包含完整的文件路径,因此很容易看到内容可能超出ComboBox宽度的位置。
Ye-Xin Ye,在MSDN论坛帖子Windows Dropdown question中,提供了解决这个更具体问题的解决方案,并且更加简单。我在这里完整地重现了代码。 (请注意,此代码预先假定您已创建一个名为Form1的Form并连接显示的加载处理程序,并且还添加了一个名为comboBox1的ComboBox和一个工具提示处理程序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();
}
虽然简单明了,但这段代码确实存在一个缺陷(正如上面MSDN线程的回复中所指出的):当你将鼠标(不点击)从一个下拉项移动到下一个时,只有每个< em>其他一个显示持久的工具提示!修复只是通过该线程上的另一个条目暗示,所以我认为在这里提供完整的,更正的代码是有用的:
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();
}
除了删除一些冗余的代码部分(例如“this”限定符)之外,主要区别在于将toolTip1.Hide调用移动到DropDownClosed事件处理程序中。从DrawItem处理程序中取出它可以消除上面提到的缺陷;但是当你下拉关闭时你需要关闭它,否则最后显示的工具提示将保留在屏幕上。
2012.07.31附录
只是想提一下,我已经创建了一个包含这个工具提示功能的复合ComboBox,所以如果你使用我的库,你根本就没有代码可以编写。只需将ComboBoxWithTooltip拖到Visual Studio设计器上即可完成。在我的API page或download我的开源C#库上深入查看ComboBoxWithTooltip以开始使用。 (请注意,Andrew捕获的bug的补丁将在1.1.04版本中发布,即将发布。)
答案 1 :(得分:7)
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()) ;
}
答案 2 :(得分:3)
我的解决方案:
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);
答案 3 :(得分:1)
基于Michael Sorens的解决方案(修复了一些错误并增加了功能)。这样做的一些事情:
e.index>0
语句中的if
)。当下拉列表已关闭时,它不会显示工具提示。
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();
}
答案 4 :(得分:0)
您需要创建自己的UserControl。
对组合框中的每个项目使用工具提示是一项不寻常的要求;也许你可以使用2列组合框来代替?
答案 5 :(得分:0)
如果要从数据源加载,请将数据导入数据表并将其设置为组合框。 我的数据表有三列ID,NAME,DEFINITION。以下是我的代码:
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();
}
答案 6 :(得分:0)
我的解决方案:
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
}
答案 7 :(得分:0)
下面是c#代码,用于显示组合框项目的工具提示,其宽度大于组合框控件的宽度。用户将鼠标悬停在此组合框上时,将显示工具提示:
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);
}
}
以下链接了解更多详情 - http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html
答案 8 :(得分:0)
使用WPF使用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>