2008-12-24 24 views
45

No deseo que el usuario pueda cambiar el valor que se muestra en el cuadro combinado. He estado usando Enabled = false pero se pone gris el texto, por lo que no es muy legible. Quiero que se comporte como un cuadro de texto con ReadOnly = true, donde el texto se muestra normalmente, pero el usuario no puede editarlo.Cómo crear Combobox en winforms readonly

¿Hay alguna forma de lograr esto?

Respuesta

18

El artículo ComboBox-with-read-only-behavior sugiere una solución interesante:

crear tanto un cuadro de texto de sólo lectura y un cuadro combinado en el mismo lugar. Cuando desee el modo de solo lectura, visualice el cuadro de texto, cuando desee que se pueda editar, muestre el cuadro combinado.

+0

Votación acentuado porque: La respuesta no es realmente útil. El control de combobox estándar ya proporciona la funcionalidad deseada como señaló @amar vashi. – Andreas

8

Lo mejor que puedo sugerir es reemplazar el cuadro combinado con una caja de texto de sólo lectura (o simplemente tal vez una etiqueta) - de esa manera el usuario puede todavía seleccionar/copiar el valor, etc.

De por supuesto, otra táctica descarada sería establecer la DropDownStyle a DropDownList, y basta con retirar todas las demás opciones - a continuación, el usuario no tiene nada más para recoger ;-P

8

No estoy seguro si esto es lo que estás buscando, pero ..

Establecer DropDownStyle = DropDownList

Luego, en el caso SelectedIndexChanged

If (ComboBox1.SelectedIndex <> 0) 
{ 
    ComboBox1.SelectedIndex = 0 
} 

Esta parte fea es que se "sientan" como pueden cambiarlo. Podrían pensar que es un error a menos que les dé una alerta para decirles por qué no pueden cambiar el valor.

1

Puede cambiar el color anterior y el posterior a los colores del sistema para un cuadro combinado habilitado, aunque esto puede confundir a los usuarios (por qué lo tienen si no pueden cambiarlo), se verá mejor.

127

hacen DropDownStyle propiedad a DropDownList en lugar de DropDown entonces controlar el evento TextChanged para evitar el cambio de texto de usuario.

+11

¿Por qué no es esta la respuesta correcta? Rápido, simple y no reinventa la rueda. – DoubleDunk

+8

Esto no evitará que el usuario seleccione diferentes opciones, solo desde la edición del texto. – billpg

+4

Puede que no sea la respuesta correcta, pero para 56 de nosotros (al momento de escribir esto) era la respuesta que estábamos buscando (cómo deshabilitar la edición del texto). – Bretticus

0

¿Por qué no solo utiliza un cuadro de texto? El cuadro de texto tiene una propiedad de "Solo lectura", y como quiere que su cuadro combinado solo muestre datos, no veo por qué necesitaría un cuadro combinado.

Una alternativa es cancelar la entrada para el evento "on value changed". De esa manera se le mostrando su información sin importar que el usuario hace ...

0

En realidad, su bastante simple:

Private Sub combobox1_KeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles combobox1.KeyDown 
    ' the following makes this the combobox read only  
    e.SuppressKeyPress = True  
End Sub 
+1

Simple, pero no funciona. Eso no impide que uno seleccione otro elemento del cuadro combinado. –

1

Aquí es la mejor solución para el ReadOnly Combo.

private void combo1_KeyPress(object sender, KeyPressEventArgs e) 
{ 
    e.KeyChar = (char)Keys.None; 
} 

Se descartará la pulsación de la tecla del Combo.

+0

No, no funciona; eso no impide que uno seleccione otro elemento del cuadro combinado. –

+0

Gracias por este código. Impide que los usuarios escriban texto personalizado en su cuadro combinado, lo que les permite seleccionar lo que hay allí pero no causar excepciones ingresando sus datos iniciales. –

-1

Aquí está la mejor solución para el Combo de ReadOnly.

private void combo1_KeyPress(object sender, KeyPressEventArgs e) { 
    e.KeyChar = (char)Keys.None; 
} 

Descartará la pulsación de la tecla del Combo. No tiene "e.! KeyChar "

+0

¿Por qué esto se ve casi exactamente como la respuesta de Manish? ¿Qué significa "no tiene e.KeyChar"? – LarsTech

+0

¡Uy! ¡Tienes razón! Estaba equivocado, utilicé el evento KeyDown en lugar del evento KeyPress. ¡Lo siento! – Behzad

4

He manejado por la subclasificación el cuadro combinado para agregar una propiedad de sólo lectura que se esconde cuando se establece y muestra un cuadro de texto de sólo lectura en la parte superior que contiene el mismo texto:

class ComboBoxReadOnly : ComboBox 
{ 
    public ComboBoxReadOnly() 
    { 
     textBox = new TextBox(); 
     textBox.ReadOnly = true; 
     textBox.Visible = false; 
    } 

    private TextBox textBox; 

    private bool readOnly = false; 

    public bool ReadOnly 
    { 
     get { return readOnly; } 
     set 
     { 
      readOnly = value; 

      if (readOnly) 
      { 
       this.Visible = false; 
       textBox.Text = this.Text; 
       textBox.Location = this.Location; 
       textBox.Size = this.Size; 
       textBox.Visible = true; 

       if (textBox.Parent == null) 
        this.Parent.Controls.Add(textBox); 
      } 
      else 
      { 
       this.Visible = true; 
       this.textBox.Visible = false; 
      } 
     } 
    } 
} 
0

conjunto DropdownStyle Propiedad a Simple

Añadir a continuación el código para que KeyPress caso de ComboBox

private void comboBoxName_KeyPress(object sender, KeyPressEventArgs e) 
{ 
    e.Handled = true; 
    return; 
} 

Añadir a continuación el código para que KeyDown caso de ComboBox

private void comboBoxName_KeyDown(object sender, KeyEventArgs e) 
{ 
    e.Handled = true; 
    return; 
} 
0

Si ya pobladas, y seleccionada el elemento apropiado, y lo convirtió en DropDownList, luego puede usar un método de extensión como este para reducir rápidamente la lista de selección al solo elemento seleccionado:

public static void MakeReadOnly(this ComboBox pComboBox) { 
    if (pComboBox.SelectedItem == null) 
     return; 

    pComboBox.DataSource = new List<object> { 
     pComboBox.SelectedItem 
    }; 
} 
0

Sé que estoy un poco tarde a la fiesta, pero yo estaba investigando esta pregunta exacta y sabía que tenía que haber alguna manera de hacer que el cuadro combinado de sólo lectura, como si se tratara de un cuadro de texto y desactivado el lista apareciendo. No es perfecto, pero definitivamente es mejor que todas las respuestas que he encontrado en Internet que no me funcionan. Después de que se presiona el botón y se llama a OnDropDown, se crea un nuevo subproceso que establecerá la propiedad DroppedDown en falso, creando así el efecto de "no pasar nada". La rueda del mouse se consume y los eventos clave se consumen también.

using System; 
using System.Threading; 
using System.Windows.Forms; 

namespace Test_Application 
{ 
    class ReadOnlyComboBox : ComboBox 
    { 
     private bool _readOnly; 
     private bool isLoading; 
     private bool indexChangedFlag; 
     private int lastIndex = -1; 
     private string lastText = ""; 

     public ReadOnlyComboBox() 
     { 
     } 

     public bool ReadOnly 
     { 
      get { return _readOnly; } 
      set { _readOnly = value; } 
     } 

     protected override void OnDropDown(EventArgs e) 
     { 
      if (_readOnly) 
      { 
       DropDownHeight = 1; 
       var t = new Thread(CloseDropDown); 
       t.Start(); 
       return; 
      } 
      base.OnDropDown(e); 
     } 

     private delegate void CloseDropDownDelegate(); 
     private void WaitForDropDown() 
     { 
      if (InvokeRequired) 
      { 
       var d = new CloseDropDownDelegate(WaitForDropDown); 
       Invoke(d); 
      } 
      else 
      { 
       DroppedDown = false; 
      } 
     } 
     private void CloseDropDown() 
     { 
      WaitForDropDown(); 
     } 

     protected override void OnMouseWheel(MouseEventArgs e) 
     { 
      if (!_readOnly) 
       base.OnMouseWheel(e); 
     } 

     protected override void OnKeyDown(KeyEventArgs e) 
     { 
      if (_readOnly) 
      { 
       switch (e.KeyCode) 
       { 
        case Keys.Back: 
        case Keys.Delete: 
        case Keys.Up: 
        case Keys.Down: 
         e.SuppressKeyPress = true; 
         return; 
       } 
      } 
      base.OnKeyDown(e); 
     } 

     protected override void OnKeyPress(KeyPressEventArgs e) 
     { 
      if (_readOnly) 
      { 
       e.Handled = true; 
       return; 
      } 
      base.OnKeyPress(e); 
     } 
    } 
} 
5

enter link description here

sólo cambia el DropDownStyle-DropDownList. O si quiere que se lea completamente solo, puede configurar Enabled = false, o si no le gusta el aspecto de eso, a veces tengo dos controles, un cuadro de texto de solo lectura y un cuadro combinado y luego ocultar el combo y mostrar el cuadro de texto si debería estar completamente Readonly y viceversa.

0

forma más sencilla con código de:

en lugar de los métodos de la adición de KeyPress o KeyDown, añadir este código en 'Form1_Load' método:

comboBox1.KeyPress += (sndr, eva) => eva.Handled = true;

o

comboBox1.KeyDown += (sndr, eva) => eva.SuppressKeyPress = true;

(sndr, eva) es de código funciona (object sender, EventArgs e)

1

de Michael R, pero ... El "DropDownHeight = 1;" debe volver al valor predeterminado cuando la propiedad ReadOnly se establece en false. Por lo tanto, inserte antes de "base.OnDropDown (e)": DropDownHeight = 106;

using System; 
using System.Threading; 
using System.Windows.Forms; 

namespace Test_Application 
{ 
    class ReadOnlyComboBox : ComboBox 
    { 
     private bool _readOnly; 
     private bool isLoading; 
     private bool indexChangedFlag; 
     private int lastIndex = -1; 
     private string lastText = ""; 

     public ReadOnlyComboBox() 
     { 
     } 

     public bool ReadOnly 
     { 
      get { return _readOnly; } 
      set { _readOnly = value; } 
     } 

     protected override void OnDropDown (EventArgs e) 
     { 
      if (_readOnly) 
      { 
       DropDownHeight = 1; 
       var t = new Thread(CloseDropDown); 
       t.Start(); 
       return; 
      } 
      DropDownHeight = 106; //Insert this line. 
      base.OnDropDown(e); 
     } 

     private delegate void CloseDropDownDelegate(); 
     private void WaitForDropDown() 
     { 
      if (InvokeRequired) 
      { 
       var d = new CloseDropDownDelegate (WaitForDropDown); 
       Invoke(d); 
      } 
      else 
      { 
       DroppedDown = false; 
      } 
     } 
     private void CloseDropDown() 
     { 
      WaitForDropDown(); 
     } 

     protected override void OnMouseWheel (MouseEventArgs e) 
     { 
      if (!_readOnly) 
       base.OnMouseWheel(e); 
     } 

     protected override void OnKeyDown (KeyEventArgs e) 
     { 
      if (_readOnly) 
      { 
       switch (e.KeyCode) 
       { 
        case Keys.Back: 
        case Keys.Delete: 
        case Keys.Up: 
        case Keys.Down: 
         e.SuppressKeyPress = true; 
         return; 
       } 
      } 
      base.OnKeyDown(e); 
     } 

     protected override void OnKeyPress (KeyPressEventArgs e) 
     { 
      if (_readOnly) 
      { 
       e.Handled = true; 
       return; 
      } 
      base.OnKeyPress(e); 
     } 
    } 
} 

Para completar esta respuesta: Archivo - Nuevo - Proyecto ... - Visual C# - Windows - Escritorio clásico - Windows Forms Control Library - escriba el nombre de su control - Aceptar y pega este código . Puede elegir el nombre de su archivo dll: Proyecto - sus Propiedades de proyecto ... - Nombre de ensamblado - escriba el nombre. Simplemente crea la solución y tienes tu archivo dll. Entonces, abra el proyecto donde desea usar su combo de Solo lectura, haga clic derecho en Referencias - Agregar referencia ... y explore su archivo dll. Para insertar su componente personalizado en la Caja de herramientas, abra su Caja de herramientas, haga clic derecho en la pestaña General - Elija los elementos ... - Examine su archivo dll - Abrir. Ahora puede usar su ReadOnlyComboBox en sus proyectos. PD: estoy usando VS2015.

Cuestiones relacionadas