Je ne veux pas que l'utilisateur puisse modifier la valeur affichée dans la liste déroulante. J'utilisais Enabled = false
mais le texte est grisé, donc ce n'est pas très lisible. Je veux qu'il se comporte comme une zone de texte avec ReadOnly = true
, où le texte est affiché normalement, mais l'utilisateur ne peut pas le modifier.
Y a-t-il un moyen d'accomplir cela?
L'article ComboBox-with-read-only-behavior suggère une solution intéressante:
Créez à la fois une zone de texte en lecture seule et une liste déroulante au même endroit. Lorsque vous voulez le mode lecture seule, affichez la zone de texte, lorsque vous souhaitez le modifier, affichez la liste déroulante.
transformez la propriété DropDownStyle
en DropDownList
au lieu de DropDown
puis gérez l'événement TextChanged
pour empêcher l'utilisateur de modifier le texte.
Je ne sais pas si c'est ce que vous cherchez, mais ...
Définir le DropDownStyle = DropDownList
Puis sur l'événement SelectedIndexChanged
If (ComboBox1.SelectedIndex <> 0)
{
ComboBox1.SelectedIndex = 0
}
Cette partie laide, c'est qu'ils vont "se sentir" comme s'ils pouvaient le changer. Ils pourraient penser que c'est une erreur, sauf si vous leur donnez une alerte leur indiquant pourquoi ils ne peuvent pas changer la valeur.
La meilleure chose que je puisse suggérer est de remplacer la liste déroulante par une zone de texte en lecture seule (ou peut-être simplement une étiquette) - de cette façon, l'utilisateur peut toujours sélectionner/copier la valeur, etc.
Bien sûr, une autre tactique effrontée consisterait à définir DropDownStyle
sur DropDownList
et à supprimer toutes les autres options - l'utilisateur n'aura plus rien à choisir ;-p
entrez la description du lien ici
Il suffit de changer la
DropDownStyle
enDropDownList
. Ou si vous voulez qu'il soit entièrement en lecture seule, vous pouvez définirEnabled = false
, ou si vous n'aimez pas son apparence, j'ai parfois deux commandes, une zone de texte en lecture seule et une liste déroulante, puis masquez la liste déroulante et affichez-la si elle doit être complètement en lecture seule et vice versa.
Je l'ai traitée en sous-classant ComboBox pour ajouter une propriété ReadOnly qui se cache lorsqu'elle est définie et affiche une zone de lecture en lecture seule contenant le même texte:
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;
}
}
}
}
Le code de Michael R fonctionne, mais ...
Le DropDownHeight = 1;
doit revenir à la valeur par défaut lorsque la propriété ReadOnly est définie sur false. Donc, insérez avant 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);
}
}
}
Pour compléter cette réponse:
Fichier -> Nouveau -> Projet ... Visual C # -> Windows -> Classic Desktop -> Bibliothèque de contrôles Windows Forms
tapez le nom de votre contrôle - OK et collez ce code.
Vous pouvez choisir le nom de votre fichier dll:
Project - les propriétés de votre projet ...
Voici la meilleure solution pour le Combo ReadOnly.
private void combo1_KeyPress(object sender, KeyPressEventArgs e)
{
e.KeyChar = (char)Keys.None;
}
Il supprimera la pression de touche pour le Combo.
Vous pouvez modifier la couleur de couleur de fond et la couleur de fond en couleurs système pour une zone de liste déroulante activée, bien que cela puisse dérouter les utilisateurs (pourquoi l'avoir s'il ne peut pas le changer), cela aura l'air mieux.
Voici comment vous répondriez qu'une ComboBox
avec Enabled = False
est difficile à lire:
Définissez la propriété DropdownStyle
sur Simple
Ajoutez le code ci-dessous à l'événement KeyPress
de ComboBox
private void comboBoxName_KeyPress(object sender, KeyPressEventArgs e)
{
e.Handled = true;
return;
}
Ajoutez le code ci-dessous à l'événement KeyDown
de ComboBox
private void comboBoxName_KeyDown(object sender, KeyEventArgs e)
{
e.Handled = true;
return;
}
Si vous l'avez déjà rempli, avez sélectionné l'élément approprié et l'avez défini comme suit DropDownList
, vous pouvez utiliser une méthode d'extension de ce type pour réduire rapidement la liste de sélection à l'élément sélectionné:
public static void MakeReadOnly(this ComboBox pComboBox) {
if (pComboBox.SelectedItem == null)
return;
pComboBox.DataSource = new List<object> {
pComboBox.SelectedItem
};
}
Je sais que je suis un peu en retard pour la fête, mais je cherchais cette question précise et je savais qu'il devait y avoir un moyen de rendre le combobox en lecture seule comme s'il s'agissait d'une zone de texte et de désactiver la liste qui apparaît. Ce n'est pas parfait, mais c'est certainement meilleur que toutes les réponses que j'ai trouvées sur Internet et qui ne fonctionnent pas pour moi. Une fois que le bouton est enfoncé et que OnDropDown est appelé, un nouveau thread est créé pour définir la propriété DroppedDown sur false, créant ainsi l'effet de «rien ne se passe». La molette de la souris est utilisée et les événements clés sont également utilisés.
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);
}
}
}
En fait, c'est plutôt 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
Pourquoi n'utilisez-vous pas simplement une zone de texte? Zone de texte a une propriété «Lecture seule», et puisque vous voulez que votre liste déroulante affiche uniquement des données, je ne vois pas pourquoi vous auriez besoin d'une boîte à options.
Une autre solution consiste à annuler l'entrée pour l'événement "à la valeur modifiée". De cette façon, vous ne pourrez plus afficher vos informations quel que soit l'utilisateur ...