2011-01-30 11 views

Respuesta

51

No puede usarlo directamente.

hacer un truco

Primera iterar a través de todos los elementos de su cuadro combinado, la verificación de la anchura de cada artículo en el texto mediante la asignación de una etiqueta. Luego, compruebe el ancho cada vez, si el ancho del elemento actual es mayor que los elementos anteriores y luego cambie el ancho máximo.

int DropDownWidth(ComboBox myCombo) 
{ 
    int maxWidth = 0; 
    int temp = 0; 
    Label label1 = new Label(); 

    foreach (var obj in myCombo.Items) 
    { 
     label1.Text = obj.ToString(); 
     temp = label1.PreferredWidth; 
     if (temp > maxWidth) 
     { 
      maxWidth = temp; 
     } 
    } 
    label1.Dispose(); 
    return maxWidth;   
} 

private void Form1_Load(object sender, EventArgs e) 
{ 
    comboBox1.DropDownWidth = DropDownWidth(comboBox1); 
} 

O

Como sugiere stakx, puede utilizar la clase TextRenderer

int DropDownWidth(ComboBox myCombo) 
{ 
    int maxWidth = 0, temp = 0; 
    foreach (var obj in myCombo.Items) 
    { 
     temp = TextRenderer.MeasureText(obj.ToString(), myCombo.Font).Width; 
     if (temp > maxWidth) 
     { 
      maxWidth = temp; 
     } 
    } 
    return maxWidth; 
} 
+1

+1, respuesta agradable. Sin haber probado esto, tengo curiosidad: ¿'label1.PreferredWidth' ya se ha calculado correctamente después de configurar' label1.Text'? (Después de todo, la interfaz de usuario no tendrá la oportunidad de actualizarse mientras se ejecuta este código. Me doy cuenta de que 'label1' en realidad no se agrega a ninguna forma, pero sin embargo ... Me sorprende que esto funcione.) – stakx

+0

@stakx, probé con 'label1.Width' pero no funcionaba, ya que no se agregó a la interfaz de usuario. Entonces, utilicé 'label1.PreferredWidth'. :) –

+6

En una nota relacionada, supongo que si bien este truco con 'label1.PreferredWidth' podría funcionar bien, una forma un poco más directa y" expresiva "de medir el ancho del texto sería usar [' TextRenderer.MeasureText'] (http://msdn.microsoft.com/en-us/library/system.windows.forms.textrenderer.measuretext.aspx) ...? – stakx

11

Aquí es una solución muy elegante. Solo necesita suscribir el cuadro combinado a este controlador de eventos:

private void AdjustWidthComboBox_DropDown(object sender, EventArgs e) 
     { 
      var senderComboBox = (ComboBox)sender; 
      int width = senderComboBox.DropDownWidth; 
      Graphics g = senderComboBox.CreateGraphics(); 
      Font font = senderComboBox.Font; 

      int vertScrollBarWidth = (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems) 
        ? SystemInformation.VerticalScrollBarWidth : 0; 

      var itemsList = senderComboBox.Items.Cast<object>().Select(item => item.ToString()); 

      foreach (string s in itemsList) 
      { 
       int newWidth = (int)g.MeasureString(s, font).Width + vertScrollBarWidth; 

       if (width < newWidth) 
       { 
        width = newWidth; 
       } 
      } 

      senderComboBox.DropDownWidth = width; 
     } 

Este código fue tomado de la CodeProject: Adjust combo box drop down list width to longest string width. Pero lo he modificado para que funcione con cuadros combinados llenos de cualquier dato (no solo cadenas).

+0

+1 para tener en cuenta el ancho de la barra de desplazamiento vertical y permitir cualquier contenido, no solo cadenas. Sin embargo, es una pena no utilizar la clase TextRenderer como en las otras respuestas. – MarkJ

+4

Debe recordar disponer de la instancia de 'Graphics' inmediatamente después del uso, mejor envolviéndola dentro de un bloque' using'. – Groo

1

Parcialmente se añade el mismo código que en la segunda sugerencia de Javed Akram, pero la anchura de la barra de desplazamiento vertical:

int setWidth_comboBox(ComboBox cb) 
{ 
    int maxWidth = 0, temp = 0; 
    foreach (string s in cb.Items) 
    { 
    temp = TextRenderer.MeasureText(s, cb.Font).Width; 
    if (temp > maxWidth) 
    { 
     maxWidth = temp; 
    } 
    } 
    return maxWidth + SystemInformation.VerticalScrollBarWidth; 
} 

Utilice el código como el siguiente (en un formulario con un cuadro combinado con el nombre myComboBox) :

myComboBox.Width = setWidth_comboBox(myComboBox); 
7

obj.ToString() no funciona para mí, Es mejor utilizar myCombo.GetItemText (obj). Esto funciona para mí:

private int DropDownWidth(ComboBox myCombo) 
{ 
    int maxWidth = 0, temp = 0; 
    foreach (var obj in myCombo.Items) 
    { 
     temp = TextRenderer.MeasureText(myCombo.GetItemText(obj), myCombo.Font).Width; 
     if (temp > maxWidth) 
     { 
      maxWidth = temp; 
     } 
    } 
    return maxWidth + SystemInformation.VerticalScrollBarWidth; 
} 
+0

Buena captura. 'myCombo.GetItemText (obj)' es definitivamente más correcto que las otras respuestas. 'obj.ToString()' puede ser diferente de la propiedad 'DisplayMember' del combobox. –

0

Esta es una vieja pregunta, pero me acaba de ejecutar en él y combina un par de las respuestas para mi solución. Me gustó la simplicidad de la respuesta aceptada, pero quería algo que funcionara con cualquier tipo de objeto en el cuadro combinado. También quería hacer uso del método a través de un método de extensión.

public static int AutoDropDownWidth(this ComboBox myCombo) 
    { 
     return AutoDropDownWidth<object>(myCombo, o => o.ToString()); 
    } 
    public static int AutoDropDownWidth<T>(this ComboBox myCombo, Func<T, string> description) 
    { 
     int maxWidth = 1; 
     int temp = 1; 
     int vertScrollBarWidth = (myCombo.Items.Count > myCombo.MaxDropDownItems) 
       ? SystemInformation.VerticalScrollBarWidth : 0; 

     foreach (T obj in myCombo.Items) 
     { 
      if (obj is T) 
      { 
       T t = (T)obj; 
       temp = TextRenderer.MeasureText(description(t), myCombo.Font).Width; 
       if (temp > maxWidth) 
       { 
        maxWidth = temp; 
       } 
      } 

     } 
     return maxWidth + vertScrollBarWidth; 
    } 

De esta manera si mi clase es:

public class Person 
{ 
    public string FullName {get;set;} 
} 

pude ajuste automáticamente el cuadro combinado desplegable ancho de la siguiente manera:

cbPeople.DropDownWidth = cbPeople.AutoDropDownWidth<Person>(p => p.FullName); 
0

Vote por la respuesta de algreat a continuación.

Simplemente modifiqué la respuesta de algreat con el código de cambiar el tamaño de todo el control .

Lo habría agregado como comentario pero no pude agregar el código formateado en el comentario.

private void combo_DropDown(object sender, EventArgs e) 
{ 
    //http://www.codeproject.com/Articles/5801/Adjust-combo-box-drop-down-list-width-to-longest-s 
    ComboBox senderComboBox = (ComboBox)sender; 
    int width = senderComboBox.DropDownWidth; 
    Graphics g = senderComboBox.CreateGraphics(); 
    Font font = senderComboBox.Font; 
    int vertScrollBarWidth = 
     (senderComboBox.Items.Count > senderComboBox.MaxDropDownItems) 
     ? SystemInformation.VerticalScrollBarWidth : 0; 

    int newWidth; 
    foreach (string s in ((ComboBox)sender).Items) 
    { 
     newWidth = (int)g.MeasureString(s, font).Width 
      + vertScrollBarWidth; 
     if (width < newWidth) 
     { 
      width = newWidth; 
     } 
  if (senderComboBox.Width < newWidth) 
      { 
       senderComboBox.Width = newWidth+ SystemInformation.VerticalScrollBarWidth; 
      } 
} 
    senderComboBox.DropDownWidth = width; 
} 
+0

terminaste con un formato realmente agradable aunque –

0

antiguo pero clásico, espero trabajar lo suficientemente rápido

private int GetDropDownWidth(ComboBox combo) 
{ 
    object[] items = new object[combo.Items.Count]; 
    combo.Items.CopyTo(items, 0); 
    return items.Select(obj => TextRenderer.MeasureText(combo.GetItemText(obj), combo.Font).Width).Max(); 
}