2009-12-18 5 views
1

J'ai une situation où je veux changer la valeur sélectionnée d'une zone de liste déroulante dans une application Windows Forms en utilisant Ctrl-Left ou Ctrl-Right. Toutefois, si la zone de liste déroulante est le contrôle sélectionné sur le formulaire, cela ne fonctionne pas. La valeur sélectionnée est définie sur l'ancienne valeur après qu'elle a été définie sur la nouvelle valeur. Si la zone de liste déroulante n'est pas le contrôle sélectionné, tout fonctionne correctement. Dans mon application, le combo peut recevoir le focus car les valeurs peuvent également être modifiées avec la souris. Alors que ce que je veux peut être accompli en sélectionnant un autre contrôle sur le formulaire avant de changer la valeur, je n'aime pas beaucoup cette solution. Donc, il y a deux questions: Pourquoi l'événement selectedIndexChanged est-il déclenché avec l'ancienne valeur si la zone de liste déroulante est le contrôle sélectionné sur le formulaire et Comment peut-on éviter cela ou si je ne peux pas savoir quelle est une bonne solution de contournement? De plus, il y a du code pour illustrer mon problème. Si vous déposez une zone de liste modifiable et une zone richtext sur un formulaire et copiez le code ci-dessous dans Form1.cs, vous pouvez voir mon problème. Vous devez faire le combo DropDownList style et ajouter quelques chiffres que les éléments (1, 2, 3 est très bien)C# combobox l'index sélectionné a changé d'ancienne valeur

public partial class Form1 : Form 
{ 
    public Form1() 
    { 
     InitializeComponent(); 
     comboBox1.SelectedIndex = 0; 
    } 

    protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == (Keys.Control | Keys.Left)) 
     { 
      DoUpdate(); 
     } 
     return base.ProcessCmdKey(ref msg, keyData); 
    } 

    private void DoUpdate() 
    { 
     int index = Convert.ToInt32(comboBox1.SelectedItem); 
     index++; 
     if (comboBox1.Focused) 
      richTextBox1.Select(); 
     comboBox1.SelectedItem = index.ToString(); 
    } 

    private void SetComboValue(int value) 
    { 
     comboBox1.SelectedItem = value.ToString(); 
     richTextBox1.AppendText(string.Format("Set value {0} \r\n", value.ToString()));   
    } 

    private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) 
    { 
     richTextBox1.AppendText(string.Format("Selected index changed before {0}\r\n", comboBox1.SelectedItem)); 
     SetComboValue(Convert.ToInt32(comboBox1.SelectedItem)); 
     richTextBox1.AppendText(string.Format("Selected index changed after {0}\r\n", comboBox1.SelectedItem)); 
    } 
} 
+0

Qu'en est-il en utilisant la méthode pour obtenir l'index correspond le combobox: SelectedIndex. Est-ce que ça arrange ça? – RvdK

Répondre

1

Cela est dû au fait que, si la zone de liste déroulante est active par défaut, si vous appuyez sur les touches gauche et droite (sans contrôle), la valeur est modifiée.

Vous attrapez ctrl-left, en incrémentant la valeur ... puis en transmettant la touche à l'objet de base, qui interprète la touche de gauche et décrémente l'élément sélectionné.

Changer votre code comme suit, Soloeil keypress, et les choses semblent fonctionner comme prévu:

protected override bool ProcessCmdKey(ref Message msg, Keys keyData) 
    { 
     if (keyData == (Keys.Control | Keys.Left)) 
     { 
      DoUpdate(); 
      return true; 
     } 
     else 
     { 
      return base.ProcessCmdKey(ref msg, keyData); 
     } 
    } 
+0

Vous avez raison :-) terribles je donc se concentrer sur les touches Ctrl-gauche penser que je ne connais plus que je pressais les touches gauche et droite et ils seront également agir comme un curseur sur la liste déroulante. Cependant maintenant j'ai une question: si je retourne cette vraie valeur dans ProcessCmdKey cette combinaison de touches se propagera-t-elle plus loin à d'autres programmes qui "écoutent" pour ces clés ou pas? J'ai une petite application installée sur mon ordinateur et je fais quelque chose quand j'appuie sur Ctrl-M mais aussi, d'une manière ou d'une autre, arrête de propager cette combinaison de touches (Ctrl-M dans VS ne fera rien dans ce cas) – mosu

+0

Je ne suis pas sûr de ce que sera le comportement lorsque d'autres applications écoutent, mais msdn dit ceci: "En surchargeant la méthode ProcessCmdKey dans une classe dérivée, un contrôle devrait renvoyer true pour indiquer qu'il a traité la clé. ne sont pas traitées par le contrôle, le résultat de l'appel de la méthode ProcessCmdKey de la classe de base doit être renvoyé. " (http://msdn.microsoft.com/en-us/library/system.windows.forms.control.processcmdkey.aspx) ... Donc je suppose que c'est l'action correcte à prendre? – rcknight

+0

J'ai manipulé la touche Maj enfoncée et il semble ne pas être un problème de retour vrai. Après avoir appuyé 5 fois sur le message Windows StickyKeys apparaît, je pense que le message est envoyé plus loin. Merci beaucoup pour votre réponse. – mosu

0

Pourquoi ne pas vous lancez simplement la méthode SetComboValue de votre méthode DoUpdate? Si cela ne fonctionne pas, vous pouvez toujours définir un indicateur qui indique qu'il est défini à partir de la méthode DoUpdate et exécute uniquement l'événement modifié d'index sélectionné lorsque vous y accédez directement. Juste une pensée.

Nous faisons quelque chose de similaire lorsque nous avons un tas d'événements liés à des listes déroulantes et des listes pendant notre chargement du formulaire. Nous définissons des valeurs et ne souhaitons pas que les événements se déclenchent pendant la charge. Par conséquent, nous avons un indicateur qui empêche les événements de se déclencher tant que le chargement du formulaire n'est pas terminé. Je pense que vous définissez la valeur, mais quelque chose d'autre oblige à un second événement de changement d'élément sélectionné. Cependant, il semble également que vous pourriez entrer dans une boucle sans fin depuis que vous avez défini l'index selected dans la méthode DoUpdate et la méthode SetComboValue.

Modifiez simplement l'index sélectionné en un seul endroit.

+0

Merci pour votre commentaire Joshua. Cela ne changera pas le problème car SetComboValue est cette ligne: comboBox1.SelectedItem = value.ToString(); (en fait, il était comboBox1.SelectedItem = Convert.ToInt32 (valeur); mais j'ai changé cela parce que c'est incorrect) qui va déclencher l'événement selectedIndexChanged une fois de plus. Donc, même si je définis la valeur même si j'appelle une méthode pour définir la valeur, j'ai le même problème. Je n'appelle pas SetComboValue pour des raisons de conception. Je pense qu'il est préférable d'avoir cette fonction appelée par d'autres méthodes. – mosu

+0

J'essaye d'éviter d'ajouter une autre variable globale pour agir comme un drapeau car j'ai déjà des drapeaux à prendre en compte et je ne considère pas cela, dans mon cas, un bon design. – mosu

Questions connexes