简体   繁体   English

C#组合框选择的索引更改会触发旧值

[英]C# combobox selected index changed fires old value

I have a situation when I want to change the selected value of a combo box in a windows forms application by using Ctrl-Left ori Ctrl-Right. 当我想通过使用Ctrl-Left ori Ctrl-Right来更改Windows窗体应用程序中组合框的选定值时,出现一种情况。 However if the combobox is the selected control on the form this does not work. 但是,如果组合框是窗体上的选定控件,则此方法不起作用。 The selected value is set to the old value after it is set to the new value. 在将所选值设置为新值之后,将其设置为旧值。 If the combobox is not the selected control then everything works fine. 如果组合框不是选定的控件,则一切正常。 In my application the combo can receive focus because the values can also be changed with the mouse. 在我的应用程序中,该组合可以获得焦点,因为还可以使用鼠标更改这些值。 While what I want can be accomplished by selecting some other control on the form before actually changing the value I don't like this solution to much. 虽然我想要的可以通过在实际更改值之前在表单上选择其他控件来实现,但我不太喜欢这种解决方案。

So, there are two questions: Why is the selectedIndexChanged event fired with the old value if the combo box is the selected control on the form and How can avoid this or if I can't what is a good workaround ? 因此,有两个问题:如果组合框是窗体上的选定控件,为什么为什么用旧值触发了selectedIndexChanged事件,以及如何避免这种情况或者如果我不能找到一个好的解决方法? Further is some code to illustrate my issue. 进一步是一些代码来说明我的问题。 If you drop a combo box and a richtext box on a form and copy the below code in Form1.cs you can see my problem. 如果在窗体上放置一个组合框和一个RTF框,然后将以下代码复制到Form1.cs中,则可以看到我的问题。 You need to make the combo DropDownList Style and add some numbers as items (1, 2, 3 is fine) 您需要组合使用DropDownList Style并添加一些数字作为项目(1、2、3可以)

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));
    }
}

This is caused by the fact that by default, if the combobox has focus, then pressing left and right(without control) will change the value. 这是由于以下事实造成的:默认情况下,如果组合框具有焦点,则按向左和向右(无控制)将更改该值。

You are catching ctrl-left, incrementing the value ... and then passing on the keypress to the base object, which interprets the left keypress and decrements the selected item. 您正在捕捉ctrl-left,将值...递增,然后将按键传递到基础对象,该对象将解释左按键并递减所选项目。

Change your code as follows, to swallow the keypress, and things seem to work as expected: 如下更改代码,以吞下按键,一切似乎按预期进行:

    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);
        }
    }

Why don't you just run the SetComboValue method from your DoUpdate method? 为什么不从DoUpdate方法中运行SetComboValue方法呢? If that doesn't work you could always set a flag that states it's set from the DoUpdate method and only run the selected index changed event when directly accessed. 如果那不起作用,则可以始终设置一个标志,指出它是通过DoUpdate方法设置的,并且仅在直接访问时运行选定的索引更改事件。 Just a thought. 只是一个想法。

We do something similar when we have a bunch of events tied to comboboxes and lists during our load of the form. 加载表单时,如果有大量与组合框和列表相关的事件发生,则我们会执行类似的操作。 We are setting values and don't want the events to fire during load so we have a flag that keeps the events from firing until the form load is complete. 我们正在设置值,并且不希望事件在加载过程中触发,因此我们有一个标志来阻止事件在表单加载完成之前触发。

My thought is that you are setting the value but something else is forcing a second selecteditem change event to occur. 我的想法是您正在设置值,但其他原因则迫使第二次selectitem更改事件发生。 However it also looks like you could get into a endless loop since you set the selectedindex in the DoUpdate method and the SetComboValue method. 但是,由于您在DoUpdate方法和SetComboValue方法中设置了selectedindex,因此您似乎也陷入了一个无限循环。

Just change the selected index in one place. 只需在一处更改所选索引。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM