.net - otro - Información sobre herramientas para cada elemento en un cuadro combinado
cuadro de lista de selección múltiple excel (9)
Solo quiero agregar una información sobre herramientas para cada elemento en un cuadro combinado. Estoy usando la aplicación de Windows c # .net.
No hay opción como
combobox.items [1] .tooltip ();
¿Hay alguna manera de añadir información sobre herramientas?
A continuación se muestra el código c # para mostrar la información sobre herramientas en el elemento del cuadro combinado cuyo ancho es mayor que el ancho del control del cuadro combinado. La información sobre herramientas se mostrará una vez que el usuario desplace el mouse sobre dicho cuadro combinado:
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);
}
}
Aquí está el enlace para obtener más detalles: http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html
Con WPF use un 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>
Deberá crear su propio UserControl .
Tener una Información sobre herramientas para cada elemento en un cuadro combinado es un requisito inusual; Tal vez podrías usar un combobox de 2 columnas en su lugar?
En realidad, hay un par de soluciones razonables para esta pregunta. Un foro de MSDN tiene una publicación de evento de elemento destacado de ComboBox que contiene dos posibilidades, una de nobugz y otra de agrobler. Cada uno de ellos proporciona un código para crear una subclase de ComboBox que se supone que maneja información sobre herramientas en elementos individuales en el menú desplegable de ComboBox. La solución de Agrobler se ve más pulida, ya que incluso incluye algunas ilustraciones agradables, pero desafortunadamente no está claro (al menos para mí) cómo completar la propiedad crucial ToolTipMember del control.
Ambas soluciones parecen permitir información sobre herramientas arbitraria asignada a elementos individuales. Un caso más específico, pero más común, es cuando simplemente desea que la información sobre herramientas refleje el texto del elemento, cuando sepa que puede tener elementos que sean demasiado largos para ajustarse al ancho del ComboBox. En mi propio caso, tengo una instancia de un ComboBox que contiene rutas de archivo completas, por lo que es fácil ver dónde el contenido podría exceder el ancho del ComboBox.
Zhi-Xin Ye, en la pregunta de Windows Dropdown del foro de MSDN, proporciona una solución que aborda este problema más específico y es mucho más simple. Aquí reproduzco el código en su totalidad. (Tenga en cuenta que este código presupone que ha creado un Formulario denominado Form1 y que conectó el controlador de carga que se muestra, y que también agregó un ComboBox denominado ComboBox1 y una herramienta ToolTip1 del controlador de información sobre herramientas)
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();
}
Aunque es simple y conciso, este código adolece de un defecto (como se señala en una respuesta en el subproceso de MSDN anterior): a medida que mueve el mouse (sin hacer clic) de un elemento desplegable al siguiente, solo cada uno muestra un Tooltip persistente! La solución solo se indica en otra entrada en ese hilo, así que pensé que sería útil proporcionar el código completo y corregido aquí:
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();
}
Además de eliminar algunas partes redundantes de código (por ejemplo, el calificador "this"), la principal diferencia es mover la información sobre la herramienta 1. Ocultar la llamada al controlador de eventos DropDownClosed. Sacarlo del controlador DrawItem elimina el defecto mencionado anteriormente; pero luego debe cerrarlo cuando se cierre el menú desplegable; de lo contrario, la última información sobre herramientas mostrada permanecerá en pantalla.
2012.07.31 Addendum
Solo quería mencionar que desde entonces he creado un ComboBox compuesto que incorpora esta capacidad de información sobre herramientas, por lo que si usa mi biblioteca no tiene ningún código para escribir. Simplemente arrastre un ComboBoxWithTooltip al diseñador de Visual Studio y listo. Desplácese hasta ComboBoxWithTooltip en mi página de API o download mi biblioteca de código abierto de C # para comenzar. (Tenga en cuenta que el parche para el error que Andrew detectó estará en la versión 1.1.04, que saldrá pronto).
Mi solución:
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
}
Mi solución:
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);
Si está cargando desde una fuente de datos, obtenga los datos en datos configurables y configúrelos en el cuadro combinado. Mi datatable tiene tres columnas ID, NOMBRE, DEFINICIÓN. A continuación se muestra mi código:
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();
}
Sobre la base de la solución de Michael Sorens (solucionó algunos errores y añadió características). Algunas cosas que hace esto:
- Mostrará una vista previa de un archivo asociado con el menú desplegable (en este caso, el título de un libro de un archivo XML, o puede agregar más descripciones en la información sobre herramientas, o mostrar algo completamente diferente).
- No muestra información sobre herramientas para la posición "0" en el menú desplegable (tuve un marcador de posición, pero simplemente puedes eliminar el
e.index>0
en la segunda declaraciónif
). No muestra la información sobre herramientas cuando el menú desplegable está CERRADO.
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(); }
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()) ;
}