views:

305

answers:

2

I have a WinForms combo box, I wish to set the width of the column box so that any selected item can be shown in full. (I do not know what items will be in the combo box at the time of writing the software)

However when I call Combobox.PreferredSize, it does not seem to take into account the items that are in the drop down list.

+1  A: 

You can use the System.Drawing.Graphics.MeasureString method. Take a look at this answer for more details on how to find the widest item in the list.

private void ResizeComboBox(ComboBox comboBox) {
  var maxItemLength = 0;
  // using the ComboBox to get a Graphics object:
  using (var g = Graphics.FromHwnd(comboBox.Handle)) {
    foreach (var item in comboBox.Items.Cast<string>()) {
      var itemLength = g.MeasureString(item, comboBox.Font);
      maxItemLength = Math.Max((int) itemLength.Width, maxItemLength);
    }
  }
  // correction for the drop down arrow
  maxItemLength += 15;
  comboBox.Width = maxItemLength;
}
Julien Poulin
Thanks, but how match to I add on to cope with the broader and drop down arrow etc? (Remember the way that the combro box is drawn depends on the OS Winforms is running on)
Ian Ringrose
does the += 15 take into account high DPI displays etc?
Ian Ringrose
No, it's a value that fits well on Vista, but I haven't tested it on other OS. What do you mean 'high DPI display'? Points are a constant regardless of the screen size in windows-forms, so there should be no problem. Just find out the maximum correction under all the OS you want to support and use that value. HTH.
Julien Poulin
+2  A: 

Using System.Drawing.Graphis.MeasureString or the other (faster) alternative TextRenderer.MeasureText will do the trick in measuring the width of a string in a given font. Simply get the maximum width of all the items in the list of items and set the width of the control to that maximum.

The algorithm for doing so is:

using (Graphics g = comboBox.CreateGraphics())
{
    float maxWidth = comboBox.Width;

    foreach(string s in comboBox.Items)
    {
        SizeF size = g.MeasureString(s, comboBox.Font);
        if (size.Width > maxWidth)
            maxWidth = size.Width;
    }
}

comboBox.Width = maxWidth;
Mike J
Thanks, but how match to I add on to cope with the broader and drop down arrow etc? (Remember the way that the combro box is drawn depends on the OS Winforms is running on)
Ian Ringrose
Have a look at the System.Windows.Forms.SystemInformation class that describes a lot of the UI metrics like widths and heights or you could try the GetSystemMetrics Win32 API method call using the SM_CXVSCROLL property.
Mike J
Also, consider that you cannot really add a "this feels right" value for the width of the drop down arrow, since the user can customize the width of it! That's where the SystemInformation and GetSystemMetrics will definitely help.
Mike J