Подсказка для каждого элемента в поле со списком
Я просто хочу добавить всплывающую подсказку для каждого элемента в поле со списком. Я использую приложение С#.net windows.
Нет такого параметра, как
combobox.items [1].tooltip();
Есть ли способ добавить всплывающую подсказку?
Ответы
Ответ 1
На самом деле есть несколько разумных решений этого вопроса. В форуме MSDN есть Сообщение об экспонировании статьи ComboBox, которое содержит две возможности,
один из nobugz и один от agrobler. Каждый из них предоставляет код для подкласса ComboBox, который должен обрабатывать подсказки инструментов для отдельных элементов в выпадающем списке ComboBox. Решение Agrobler выглядит более отполированным, поскольку он даже содержит некоторые приятные иллюстрации, но, к сожалению, неясно (по крайней мере мне), как заполнить ключевое свойство ToolTipMember элемента управления.
Оба этих решения позволяют разрешить любые всплывающие подсказки, назначенные отдельным элементам. Более конкретный, но более распространенный случай - это то, где вы просто хотите, чтобы всплывающая подсказка отражала текст элемента, когда вы знаете, что у вас могут быть элементы, которые слишком длинны, чтобы соответствовать ширине ComboBox. В моем случае у меня есть экземпляр ComboBox, который содержит полные пути к файлам, поэтому легко увидеть, где содержимое может превышать ширину ComboBox.
Zhi-Xin Ye, на форуме форума MSDN вопрос о распаковке Windows, предоставляет решение, которое решает эту более конкретную проблему и намного проще. Я воспроизвожу код здесь целиком. (Обратите внимание, что этот код предполагает, что вы создали форму под названием Form1 и подключили обработчик нагрузки, а также добавили ComboBox с именем comboBox1 и 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): при перемещении мыши (без щелчка) из одного раскрывающегося списка в следующий, только каждый другой один показывает постоянную подсказку! Исправление только намечено еще одной записью в этом потоке, поэтому я подумал, что было бы полезно предоставить полный исправленный код здесь:
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 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, и все готово. Перейдите к ComboBoxWithTooltip на моей странице или download моя открытая библиотека С# для начала работы. (Обратите внимание, что патч для ошибки, которую Андрей поймал, будет выпущен в версии 1.1.04, вскоре должен выйти.)
Ответ 2
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()) ;
}
Ответ 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);
Ответ 4
Основываясь на решении Майкла Соренса (исправлено несколько ошибок и добавленных функций). Это несколько вещей:
- Отобразится предварительный просмотр файла, связанного с выпадающим (в данном случае названием книги из файла XML, или вы можете добавить дополнительные описания в
всплывающая подсказка или отображение чего-то совершенно другого).
- Он не отображает всплывающую подсказку для позиции "0" в раскрывающемся списке (у меня был заполнитель, но вы можете просто удалить
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();
}
Ответ 5
Вам нужно будет создать собственный UserControl.
Наличие всплывающей подсказки для каждого элемента в combobox является необычным требованием; возможно, вы могли бы использовать вместо столбца 2 столбца?
Ответ 6
Если вы загружаетесь из источника данных, получите данные в datatable и установите их в combobox.
У моего datatable есть три идентификатора столбца, 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();
}
Ответ 7
Мое решение:
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
}
Ответ 8
Ниже приведен код С#, чтобы показать подсказку инструмента на элементе поля со списком, ширина которого больше ширины управления полем со списком. Инструмент подскажет, как только пользователь наведет на такой поле со списком:
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
Ответ 9
С 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>