c# - usar - ¿Cómo mostrar el texto en el cuadro combinado cuando no hay ningún elemento seleccionado?
como usar combobox c# (16)
C # y .Net 2.0 pregunta (WinForms)
Tengo un conjunto de elementos en ComboBox
y ComboBox
de ellos seleccionado. Me gustaría mostrar una cadena en el combo " Seleccionar elemento " en esa situación.
La implementación actual se acaba de agregar un elemento vacío con dicho texto en el índice 0 y eliminarlo cuando el usuario selecciona uno de los siguientes elementos. Desafortunadamente, el elemento vacío se muestra en la lista desplegable también. Cómo evitar esta situación o de otra manera: ¿hay alguna forma de mostrar texto personalizado en ComboBox
cuando no se selecciona ningún elemento?
Las respuestas a continuación funcionan cuando ComboBoxStyle
se establece en DropDown
( ComboBox
es editable). ¿Existe la posibilidad de hacer esto cuando ComboBoxStyle
se establece en DropDownList
?
¿Por qué no hacerlo XAML?
<ComboBox x:Name="myComboBoxMenu" PlaceholderText="Hello"/>
Aquí puede encontrar una solución creada por pavlo_ua: si tiene .Net> 2.0 y social.msdn.microsoft.com/Forums/en/winformsdesigner/thread/…
Saludos, JBK
Edición: Así que para tener una respuesta clara no solo enlace.
Puede establecer Text of combobox cuando su estilo se establece como DropDown (y es editable). Cuando tiene la versión .Net <3.0, no hay ninguna propiedad IsReadonly, por lo que necesitamos usar win api para configurar el cuadro de texto de combobox como readonly:
private bool m_readOnly = false;
private const int EM_SETREADONLY = 0x00CF;
internal delegate bool EnumChildWindowsCallBack( IntPtr hwnd, IntPtr lParam );
[DllImport("user32.dll", CharSet = CharSet.Auto)]
internal static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
[ DllImport( "user32.dll" ) ]
internal static extern int EnumChildWindows( IntPtr hWndParent, EnumChildWindowsCallBack lpEnumFunc, IntPtr lParam );
private bool EnumChildWindowsCallBackFunction(IntPtr hWnd, IntPtr lparam)
{
if( hWnd != IntPtr.Zero )
{
IntPtr readonlyValue = ( m_readOnly ) ? new IntPtr( 1 ) : IntPtr.Zero;
SendMessage( hWnd, EM_SETREADONLY, readonlyValue, IntPtr.Zero );
comboBox1.Invalidate();
return true;
}
return false;
}
private void MakeComboBoxReadOnly( bool readOnly )
{
m_readOnly = readOnly;
EnumChildWindowsCallBack callBack = new EnumChildWindowsCallBack(this.EnumChildWindowsCallBackFunction );
EnumChildWindows( comboBox1.Handle, callBack, IntPtr.Zero );
}
Así es como lo hago. Puede que no sea el mejor método y ofrezca el menor control; sin embargo, es simple y rápido y pensé que podría ser una buena idea compartirlo para que haya más opciones disponibles para otros.
<ComboBox SelectedIndex="0">
<ComboBoxItem Visibility="Collapsed">Please select one...</ComboBoxItem>
<ComboBoxItem>1</ComboBoxItem>
<ComboBoxItem>2</ComboBoxItem>
<ComboBoxItem>3</ComboBoxItem>
<ComboBoxItem>4</ComboBoxItem>
</ComboBox>
La idea detrás de esto es que la selección inicial es el índice 0, que está contraído, por lo que no está disponible bajo selección para el usuario una vez que seleccione otra cosa. El inconveniente es que debe recordar que si está buscando un índice seleccionado, recuerde que el índice 0 significa que no se realizó ninguna selección.
Esperaba encontrar una solución a esto también. Veo que esta es una publicación anterior, pero espero que mi enfoque pueda simplificar este problema para otra persona.
Estaba usando un cuadro combinado con un estilo desplegable de DropDownList, pero esto debería funcionar con otros estilos. En mi caso, quería que el texto dijera "Seleccionar origen" y que las otras opciones fueran "Archivo" y "Carpeta".
comboBox1.Items.AddRange(new string[] {"Select Source", "File", "Folder" });
comboBox1.Text = "Select Source";
Puede seleccionar el índice 0 en su lugar si lo desea. Luego eliminé el elemento "Seleccionar origen" cuando se cambia el índice, ya que ya no importa si ese texto es visible.
comboBox1.SelectedIndexChanged += new EventHandler(comboBox1_IndexChanged);
private void comboBox1_IndexChanged(object sender, EventArgs e)
{
comboBox1.Items.Remove("Select Source");
if (comboBox1.SelectedIndex != -1)
{
if (comboBox1.SelectedIndex == 0) // File
{
// Do things
}
else if (comboBox1.SelectedIndex == 1) // Folder
{
// Do things
}
}
}
Gracias
Esto funciona con el estilo DropDownList; cree una clase derivada de ComboBox
(aparecerá en la caja de herramientas después de la reconstrucción), que dibuja la sugerencia utilizando System.Drawing,
coloque este control desde Toolbox en su formulario y establezca la Sugerencia "Seleccione un elemento" en sus propiedades.
public class HintComboBox : ComboBox
{
string hint;
public string Hint
{
get { return hint; }
set { hint = value; Invalidate(); }
}
protected override void WndProc(ref Message m)
{
base.WndProc(ref m);
if (m.Msg == 0xf && !Focused && string.IsNullOrEmpty(Text) && !string.IsNullOrEmpty(Hint))
using (var g = CreateGraphics())
{
TextRenderer.DrawText(g, Hint, Font, ClientRectangle, SystemColors.GrayText, BackColor,
TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter);
}
}
}
Haga que la propiedad Dropdownstyle del cuadro combinado a Dropdown y establezca el texto del cuadro combinado a "Seleccionar" como se muestra a continuación
combobox.DataSource = dsIn.Tables[0];
combobox.DisplayMember = "Name";
combobox.ValueMember = "Value";
combobox.Text = "--Select--";
Lamentablemente, nada de lo anterior funcionó para mí, así que en vez de eso, agregué una etiqueta en la parte superior del comboxbox que dice "Por favor, seleccione". Usé el siguiente código para mostrarlo y ocultarlo:
Cuando inicializo mi combobox, si no hay un valor seleccionado, lo traigo al frente y configuro el texto:
PleaseSelectValueLabel.BringToFront(); PleaseSelectValueLabel.Text = Constants.AssessmentValuePrompt;
Si hay un valor seleccionado lo envío a la parte posterior:
PleaseSelectValueLabel.SendToBack();
Luego utilizo los siguientes eventos para mover la etiqueta al frente o atrás dependiendo de si el usuario ha seleccionado un valor:
private void PleaseSelectValueLabel_Click(object sender, EventArgs e) { PleaseSelectValueLabel.SendToBack(); AssessmentValue.Focus(); } private void AssessmentValue_Click(object sender, EventArgs e) { PleaseSelectValueLabel.SendToBack(); } //if the user hasnt selected an item, make the please select label visible again private void AssessmentValue_Leave(object sender, EventArgs e) { if (AssessmentValue.SelectedIndex < 0) { PleaseSelectValueLabel.BringToFront(); } }
Me doy cuenta de que este es un tema antiguo, pero solo quería que otras personas que podrían buscar una respuesta a esta pregunta sepan que, en la versión actual de Visual Studio (2015), hay una propiedad llamada "Placeholder Text" que hace lo que originalmente se hizo. preguntó sobre. Use el cuadro de propiedades, bajo "Propiedades comunes".
No pude hacer funcionar el enfoque de @Andrei Karcheuski, pero él me inspiró a este enfoque: (Agregué la propiedad Localizable para que la Sugerencia pueda ser traducida a través de archivos .resx para cada cuadro de diálogo en el que la use)
public partial class HintComboBox : ComboBox
{
string hint;
Font greyFont;
[Localizable(true)]
public string Hint
{
get { return hint; }
set { hint = value; Invalidate(); }
}
public HintComboBox()
{
InitializeComponent();
}
protected override void OnCreateControl()
{
base.OnCreateControl();
if (string.IsNullOrEmpty(Text))
{
this.ForeColor = SystemColors.GrayText;
Text = Hint;
}
else
{
this.ForeColor = Color.Black;
}
}
private void HintComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if( string.IsNullOrEmpty(Text) )
{
this.ForeColor = SystemColors.GrayText;
Text = Hint;
}
else
{
this.ForeColor = Color.Black;
}
}
No puedo ver ninguna forma nativa de .NET para hacerlo, pero si quieres ensuciarte las manos con los controles Win32 subyacentes ...
Debería poder enviar el mensaje CB_GETCOMBOBOXINFO
con una estructura COMBOBOXINFO
que contendrá el identificador del control de edición interno. A continuación, puede enviar al control de edición el mensaje EM_SETCUEBANNER
con un puntero a la cadena. (Tenga en cuenta que esto requiere al menos XP y estilos visuales para habilitarse.
Si ComboBoxStyle
se establece en DropDownList
, la forma más sencilla de asegurarse de que el usuario selecciona un elemento es establecer SelectedIndex = -1
, que estará vacío.
Si ninguna de las soluciones anteriores funciona para usted, ¿por qué no agregar algo de validación en combobox?
var orginalindex = 0;
private void comboBox1_SelectedItemChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex == 0)
{
comboBox1.Text = "Select one of the answers";
comboBox1.SelectedIndex = comboBox1.SelectedIndex;
}
else
{
orginalindex = comboBox1.SelectedIndex;
}
}
Una línea después del formulario InitializeComponent();
cbo_MyDropBox.Text = "Select a server...";
Solo lo necesitas una vez ¿verdad? Todo lo que debe hacer si una selección es obligatoria es verificar si el índice de la casilla es != -1
. ¿Alguien podría explicar por qué las otras respuestas saltan a través de aros para que esto funcione?
Lo único que me falta es que este texto inicial aparezca en gris. Si realmente desea, solo use una etiqueta en el frente y desactívela una vez que se cambie el índice.
Use el método de inserción del cuadro combinado para insertar el "Por favor, seleccione el elemento" en el índice 0,
comboBox1.Items.Insert(0, "Please select any value");
y agregue todos los elementos al cuadro combinado después del primer índice. En el conjunto de carga de formulario.
comboBox1.SelectedIndex = 0;
EDITAR:
En forma de carga escriba el texto en el comboBox1.Text
por codificación
comboBox1.Text = "Please, select any value";
y en el evento TextChanged del comboBox1 escriba el siguiente código
private void comboBox1_TextChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedIndex < 0)
{
comboBox1.Text = "Please, select any value";
}
else
{
comboBox1.Text = comboBox1.SelectedText;
}
}
Utilicé una solución rápida para poder mantener el estilo DropDownList.
class DummyComboBoxItem
{
public string DisplayName
{
get
{
return "Make a selection ...";
}
}
}
public partial class mainForm : Form
{
private DummyComboBoxItem placeholder = new DummyComboBoxItem();
public mainForm()
{
InitializeComponent();
myComboBox.DisplayMember = "DisplayName";
myComboBox.Items.Add(placeholder);
foreach(object o in Objects)
{
myComboBox.Items.Add(o);
}
myComboBox.SelectedItem = placeholder;
}
private void myComboBox_SelectedIndexChanged(object sender, EventArgs e)
{
if (myComboBox.SelectedItem == null) return;
if (myComboBox.SelectedItem == placeholder) return;
/*
do your stuff
*/
myComboBox.Items.Add(placeholder);
myComboBox.SelectedItem = placeholder;
}
private void myComboBox_DropDown(object sender, EventArgs e)
{
myComboBox.Items.Remove(placeholder);
}
private void myComboBox_Leave(object sender, EventArgs e)
{
//this covers user aborting the selection (by clicking away or choosing the system null drop down option)
//The control may not immedietly change, but if the user clicks anywhere else it will reset
if(myComboBox.SelectedItem != placeholder)
{
if(!myComboBox.Items.Contains(placeholder)) myComboBox.Items.Add(placeholder);
myComboBox.SelectedItem = placeholder;
}
}
}
Si utiliza el enlace de datos, tendrá que crear una versión ficticia del tipo al que está obligado: solo asegúrese de eliminarlo antes de cualquier lógica de persistencia.
private void comboBox1_TextChanged(object sender, EventArgs e)
{
if (comboBox1.Text == "")
comboBox1.Text = "Select one of the answers";
}
debe hacer el truco al inicio, esta línea está presente, cuando se selecciona un elemento en el cuadro combinado, aparecerá el texto de este elemento. Al borrar el texto este texto aparecerá de nuevo.