2009-03-25 13 views

Respuesta

0

Deberá crear su propio UserControl.

Tener una información sobre herramientas para cada elemento en un cuadro combinado es un requisito inusual; quizás podría usar un cuadro combinado de 2 columnas en su lugar?

+0

Cómo hacer que hacer un combo de dos columnas? –

+0

Hay algunos gratuitos alrededor. Encontré este en codeproject pero no lo he usado y no puedo comentar lo bueno que es: http://www.codeproject.com/KB/cpp/multicolumncombo.aspx –

+7

No creo que esto sea inusual en absoluto. La situación común es si el texto del elemento es demasiado largo y no puede ver la cola de la cadena. Una sugerencia de herramienta es una forma muy obvia de mostrar el artículo. Un combo de dos columnas parece torpe y horrible. – Andrew

6
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

Aunque esto funcionará, también creará una fuerte conexión entre la información sobre herramientas (que ahora no tiene forma de acceder, ya que la creó sin asignarla a una variable). Entonces, si intentas eliminar a comboBox. Aunque desaparecerá de la vista. Permanecerá en la memoria. No solo eso, estás combinando vínculos con nueva información sobre herramientas cada vez que cambias de índice. Me gustaría llevar la información sobre herramientas a un alcance más alto y simplemente llamar así: privado void comboBox1_SelectedIndexChanged (remitente del objeto, System.EventArgs e) { myGolbalToolTip.SetToolTip (this.comboBox1, yourString); –

+0

De esta forma, dentro o fuera del alcance, puede llamar a myGlobalToolTip.RemoveAll() para eliminar todas las conexiones y luego quitar el control de la memoria. Pero eso es solo si estás creando objetos dinámicamente. –

26

En realidad, hay algunas soluciones razonables para esta pregunta. Un foro de MSDN tiene una publicación ComboBox Item highlight event que contiene dos posibilidades, una de nobugz y una de agrobler. Cada uno de ellos proporciona código para subclase de un ComboBox que se supone que maneja sugerencias de herramientas sobre elementos individuales en el menú desplegable de ComboBox. La solución de Agrobler parece más pulida, ya que incluso incluye algunas buenas ilustraciones, pero desafortunadamente no está claro (al menos para mí) cómo llenar la propiedad crucial ToolTipMember del control.

Ambas soluciones parecen permitir información de herramientas arbitraria asignada a elementos individuales. Un caso más específico, pero más común, es donde simplemente desea que la información sobre herramientas refleje el texto del elemento, cuando sabe que puede tener elementos demasiado largos para ajustarse al ancho del ComboBox. En mi caso, tengo una instancia de un ComboBox que contiene rutas completas de archivos, por lo que es fácil ver dónde el contenido podría exceder el ancho del ComboBox.

Zhi-Xin Ye, en la publicación del foro MSDN Windows Dropdown question, proporciona una solución que resuelve este problema más específico y es mucho más simple. Reproduzco el código aquí en su totalidad. (Tenga en cuenta que este código presupone que haya creado un formulario llamado Form1 y conectado la carga manejador se muestra, y también se agrega un cuadro combinado llamado comboBox1 y un controlador de punta de la herramienta 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(); 
} 

Mientras que es simple y concisa, este código sufre de un defecto (como se señala en una respuesta del subproceso MSDN anterior): al mover el mouse (sin hacer clic) de un elemento desplegable al siguiente, solo cada otro muestra una información sobre herramientas persistente. La corrección sólo se insinúa por todavía otra entrada en ese hilo, por lo que pensó que sería útil proporcionar la plena, código 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 unas pocas porciones redundantes de código (por ejemplo, el "este "calificador") la diferencia principal es mover la llamada toolTip1.Hide 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 que se muestra permanecerá en pantalla.

2012.07.31 Adición

Sólo quería mencionar que desde entonces he creado un cuadro combinado compuesto que incorpora esta capacidad sobre herramientas así que si usa mi biblioteca no tienes código para escribir en absoluto. Simplemente arrastre un ComboBoxWithTooltip al diseñador de Visual Studio y listo. Desplácese hasta ComboBoxWithTooltip en mi API page o download mi biblioteca de código abierto C# para comenzar. (Tenga en cuenta que el parche para el error que atrapó Andrew estará en la versión 1.1.04, que saldrá pronto.)

+3

Solo una advertencia ... si tiene el 'DropDownStyle' establecido en' DropDownList', esto realmente no funciona. Si usa 'DropDownList', necesitará asegurarse de que' e.Index' sea mayor que -1. – Andrew

+0

¡Gracias por alcanzar ese @Andrew! He modificado el código anterior para evitar el error de tiempo de ejecución resultante. –

+0

Intenté esto (Visual Studio 2013 - .NET 2.0 Project - Windows 8.1) y los límites de texto no parecen ir completamente a la derecha, dejando un espacio vacío al final. Además, con el 'DropDownList'' DropDownStyle', si la lista es más larga que la ventana desplegable, la información sobre herramientas sigue al elemento fantasma. –

0

Si está cargando desde una fuente de datos, obtenga los datos en la tabla de datos y configúrelos en el cuadro combinado. Mi tabla de datos tiene tres columnas ID, NOMBRE, DEFINICIÓN. A continuación se muestra el 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();    
     }  
+0

¡Incorrecto! No hay una propiedad "Información sobre herramientas" en el elemento de cuadro combinado de winform. – woohoo

+0

Sí, woohoo tiene razón. – Balaji

2

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); 
1

Sobre la base de la solución de Michael Sorens (fija algunos errores y características añadidas). Algunas cosas esto hace:

  • se mostrará una vista previa de un archivo asociado con el menú desplegable (en este caso un título de libro de un archivo XML, o se puede añadir más descripciones en el información sobre herramientas, o la pantalla algo completamente diferente).
  • No muestra información sobre herramientas para la posición "0" en el menú desplegable (tenía un marcador de posición, pero simplemente puede eliminar e.index>0 en la segunda declaración if).
  • 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(); 
    } 
    
0

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 
} 
0

A continuación se muestra el código C# para mostrar punta de la herramienta sobre el punto del cuadro combinado, cuya anchura es mayor que la anchura del control de cuadro combinado. punta de la herramienta se mostrará una vez que la libración de usuario en tales 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 más detalles - http://newapputil.blogspot.in/2016/12/display-tooltip-for-combo-box-item-cnet.html

0

Con WPF utilizan 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> 
Cuestiones relacionadas