2012-07-12 27 views
15

Tengo una aplicación WinForms y me preguntaba si había una manera más elegante de deshabilitar el elemento Combobox sin cambiar la propiedad SelectedIndex -1 para todos los valores deshabilitados.Desactivar elementos particulares en un cuadro combinado

He estado buscando en Google y muchas de las soluciones involucran a ASP.Net DropDownLists pero este LINK parece prometedor. Creo que tendré que construir mi propio control ComboBox, pero antes de reinventar la rueda me imagino que preguntaría si es posible.

ACTUALIZACIÓN

Aquí está la solución final, gracias a Arif Eqbal:

//Add a Combobox to a form and name it comboBox1 
// 
    using System; 
    using System.Drawing; 
    using System.Windows.Forms; 

    namespace WindowsFormsApplication6 
    { 
     public partial class Form1 : Form 
     { 
      public Form1() 
      { 
       InitializeComponent(); 
       this.comboBox1.DrawMode = DrawMode.OwnerDrawFixed; 
       this.comboBox1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.comboBox1_DrawItem); 
       this.comboBox1.SelectedIndexChanged += new System.EventHandler(this.comboBox1_SelectedIndexChanged); 
      } 

      private void Form1_Load(object sender, EventArgs e) 
      { 
       this.comboBox1.Items.Add("Test1"); 
       this.comboBox1.Items.Add("Test2"); 
       this.comboBox1.Items.Add("Test3"); 
       this.comboBox1.Items.Add("Test4"); 
       this.comboBox1.Items.Add("Test5"); 
       this.comboBox1.Items.Add("Test6"); 
       this.comboBox1.Items.Add("Test7"); 
      } 

      Font myFont = new Font("Aerial", 10, FontStyle.Underline|FontStyle.Regular); 
      Font myFont2 = new Font("Aerial", 10, FontStyle.Italic|FontStyle.Strikeout); 

      private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
      { 
       if (e.Index == 1 || e.Index == 4 || e.Index == 5)//We are disabling item based on Index, you can have your logic here 
       { 
        e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont2, Brushes.LightSlateGray, e.Bounds); 
       } 
       else 
       { 
        e.DrawBackground(); 
        e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); 
        e.DrawFocusRectangle(); 
       } 
      } 

      void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
      { 
       if (comboBox1.SelectedIndex == 1 || comboBox1.SelectedIndex == 4 || comboBox1.SelectedIndex == 5) 
        comboBox1.SelectedIndex = -1; 
      } 
     } 
    } 
+3

ASP.NET = WinForms, no se ven allí. Extender el ComboBox básico no es muy difícil (generalmente se hace para agregar casillas de verificación o íconos o lo que sea), pero no creo que haya tal soporte estándar. –

+1

El enlace que ha mencionado es el camino a seguir si realmente desea dar a los usuarios una idea del elemento que se está deshabilitando. Es posible que desee dibujar el texto en gris, es posible que no desee mostrar un color de fondo de selección, y así sucesivamente y, por supuesto, el usuario aún puede seleccionar ese elemento, por lo que necesitará manejar selectedIndexChanged y establecer el selectedIndex en -1. Pero será visualmente más sugerente hacer el ejercicio. –

Respuesta

23

Prueba esto ... qué le sirve a su propósito:

que se supone que tiene un cuadro combinado llamado ComboBox1 y desea deshabilitar el segundo elemento, es decir, un elemento con índice 1.

Establezca la propiedad DrawMode del ComboBox a continuación OwnerDrawFixed manejar estos dos eventos, como se muestra a continuación:

Font myFont = new Font("Aerial", 10, FontStyle.Regular); 

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
{   
    if (e.Index == 1)//We are disabling item based on Index, you can have your logic here 
    { 
     e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.LightGray, e.Bounds); 
    } 
    else 
    { 
     e.DrawBackground(); 
     e.Graphics.DrawString(comboBox1.Items[e.Index].ToString(), myFont, Brushes.Black, e.Bounds); 
     e.DrawFocusRectangle(); 
    } 
} 

void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     if (comboBox1.SelectedIndex == 1) 
      comboBox1.SelectedIndex = -1; 
    } 
+2

¡Mi amigo es un genio, gracias! –

11

Aquí está mi respuesta basada 100% en Arif Eqbal de. Las mejoras son:

  • reutilizar el Font en el cuadro combinado en lugar de crear otros nuevos (de modo que si lo cambia en el diseñador, que no tendrá que actualizar el código)
  • reutilizar el defecto SystemBrushes (por lo que debe coincidir con su tema; no funcionará si cambia manualmente los colores utilizados en el ComboBox)
  • para los elementos desactivados Tuve que volver a dibujar el fondo, de lo contrario, cada vez que se vuelven a dibujar los elementos, su color acercarse cada vez más al negro
  • crear un dedicado IsItemDisabled m étodo para evitar copiar/pegar

// Don't forget to change DrawMode, else the DrawItem event won't be called. 
// this.comboBox1.DrawMode = System.Windows.Forms.DrawMode.OwnerDrawFixed; 

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
{ 
    ComboBox comboBox = (ComboBox)sender; 

    if (IsItemDisabled(e.Index)) 
    { 
     // NOTE we must draw the background or else each time we hover over the text it will be redrawn and its color will get darker and darker. 
     e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); 
     e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, SystemBrushes.GrayText, e.Bounds); 
    } 
    else 
    { 
     e.DrawBackground(); 
     e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, SystemBrushes.ControlText, e.Bounds); 
     e.DrawFocusRectangle(); 
    } 
} 

void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
{ 
    if (IsItemDisabled(comboBox1.SelectedIndex)) 
     comboBox1.SelectedIndex = -1; 
} 

bool IsItemDisabled(int index) 
{ 
    // We are disabling item based on Index, you can have your logic here 
    return index % 2 == 1; 
} 
4

Aquí está una modificación adicional. El problema con las soluciones anteriores es que un elemento seleccionado no es visible porque el primer plano de fuente y la selección de fondo son ambos oscuros. De ahí que la fuente debe ser ajustado de acuerdo con el valor de e.State:

private void comboBox1_DrawItem(object sender, DrawItemEventArgs e) 
    { 
     ComboBox comboBox = (ComboBox)sender; 
     if (e.Index >= 0) 
     { 
      if (IsItemDisabled(e.Index)) 
      { 
       e.Graphics.FillRectangle(SystemBrushes.Window, e.Bounds); 
       e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, Brushes.LightSlateGray, e.Bounds); 
      } 
      else 
      { 
       e.DrawBackground(); 

       // Set the brush according to whether the item is selected or not 
       Brush br = ((e.State & DrawItemState.Selected) > 0) ? SystemBrushes.HighlightText : SystemBrushes.ControlText; 

       e.Graphics.DrawString(comboBox.Items[e.Index].ToString(), comboBox.Font, br, e.Bounds); 
       e.DrawFocusRectangle(); 
      } 
     } 
    } 
Cuestiones relacionadas