views:

1346

answers:

3

Hi,

I have a combobox with a given width. It may occur that one row of the data is partially hidden (the combobox might be too narrow). I'd like to show the whole line by using a tooltip or right-click context menu.

Currently I can't find how to 'catch' the row that I'm currently holding on or passing over by mouse. Please tell me.

Thanks in advance!

+2  A: 

Have you tried to increase the DropDownWidth property so that everything is visible?

Edit: To find the ideal width based on the items in the list:

var maxLength = 0;
// using the ComboBox to get a Graphics object:
using (var g = Graphics.FromHwnd(comboBox2.Handle)) {
  foreach (var item in comboBox2.Items.Cast<string>()) {
    var itemLength = g.MeasureString(item, comboBox2.Font);
    maxLength = Math.Max((int) itemLength.Width, maxLength);
  }
}
if (comboBox2.Items.Count > comboBox2.MaxDropDownItems) {
  // correction when ScrollBar is displayed
  maxLength += 15;
}
comboBox2.DropDownWidth = maxLength;

I put this code in the DropDown event of the ComboBox for testing. Maybe you can find a better place for it, like after populating the ComboBox...

Julien Poulin
Thank, I didn't know this property. The question now is how to know the width of the longest data....
Tamir Gefen
To measure text, look at the System.Drawing.Graphics.MeasureString method.
hometoast
Note: this example only works if the items in the ComboBox are strings. If the items in the combobox are anything other than strings due to databinding then make sure that .Cast<string>() is updated to match the item's datatype and then in the .MeasureString() you'd have to measure the property on item that is the combobox's DisplayMember.
ckittel
A: 

Your're right, there really isn't a "Item.OnMouseOver", but I suppose you could (off the top of my head, so I've likely forgotten something)...

  • inherit from ComboBox,
  • override OnDrawItem (you may need to turn change .DrawMode to "Owner Drawn").
    • you will know which item is hovered in the OnDrawItem event/override from the EventArgs.
  • Set the tooltip on the control at that point.
  • optionally set a timer to manually show the tooltip if the above doesn't work automatically.
hometoast
A: 

Going in the same direction that Julien went, here is a generic extension method that will resize the drop down area regardless of how the combobox is filled (manually with strings or via data binding).

<Extension()> _
Public Sub AutosizeDropDownWidth(ByVal combobox As ComboBox)
    Dim longestItem As Integer = 0
    Using g = Graphics.FromHwnd(combobox.Handle)
        Dim itemsAsText = (From item In combobox.Items _
                           Select combobox.GetItemText(item))
        longestItem = CInt(itemsAsText.Max(Function(text) g.MeasureString(text, combobox.Font).Width))
    End Using

    ' Account for scrollbar
    If (combobox.Items.Count > combobox.MaxDropDownItems) Then longestItem += 15

    ' Resize as needed (but never smaller than the default width)
    combobox.DropDownWidth = Math.Max(longestItem, combobox.Width)
End Sub

To use it then you can simply do the following...

Private Sub MyCombobox_DropDown(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyCombobox.DropDown
    MyCombobox.AutosizeDropDownWidth()
End Sub

Note, I didn't test corner cases like an empty combobox in this code example.

ckittel