【问题标题】:C# combobox selected index changed fires old valueC# 组合框选择的索引更改触发旧值
【发布时间】:2009-12-18 11:25:45
【问题描述】:

我有一种情况,我想通过使用 Ctrl-Left 或 Ctrl-Right 来更改 Windows 窗体应用程序中组合框的选定值。但是,如果组合框是窗体上的选定控件,则此方法不起作用。选定的值在设置为新值后设置为旧值。如果组合框不是选定的控件,那么一切正常。在我的应用程序中,组合可以接收焦点,因为这些值也可以用鼠标更改。虽然我想要的可以通过在实际更改值之前在表单上选择一些其他控件来完成,但我不太喜欢这个解决方案。

所以,有两个问题:如果组合框是窗体上的选定控件,为什么 selectedIndexChanged 事件会使用旧值触发? 如何避免这种情况,或者如果我不能,什么是好的解决方法?还有一些代码来说明我的问题。如果您在表单上放置一个组合框和一个富文本框并在 Form1.cs 中复制以下代码,您可以看到我的问题。您需要制作组合 DropDownList 样式并添加一些数字作为项目(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));
    }
}

【问题讨论】:

  • 如何使用适当的方法获取组合框索引:SelectedIndex。这样能解决吗?

标签: c# combobox


【解决方案1】:

这是由于默认情况下,如果组合框有焦点,那么按左右(无控制)会改变值。

您正在捕获 ctrl-left,增加值...然后将按键传递给基础对象,该基础对象解释左按键并减少所选项目。

如下更改你的代码,吞下按键,事情似乎按预期工作:

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

【讨论】:

  • 你太糟糕了 :-) 我太专注于 Ctrl-Left 以为我忘记了我正在按向左和向右键,这些也会像下拉列表上的光标一样.但是现在我有一个问题:如果我在 ProcessCmdKey 中返回该真实值,此组合键是否会进一步传播到“侦听”这些键的其他程序?我的计算机上安装了一个小应用程序,当我按下 Ctrl-M 时,它正在做某事,但不知何故,它停止传播此组合键(因此,VS 中的 Ctrl-M 在这种特殊情况下什么都不做)
  • 我不确定当其他应用程序正在侦听时会发生什么行为,但 msdn 说:“在派生类中重写 ProcessCmdKey 方法时,控件应返回 true 以指示它具有处理了key,对于没有被控件处理的key,应该返回调用基类的ProcessCmdKey方法的结果。 (msdn.microsoft.com/en-us/library/…) ...所以我想这是正确的行动??
  • 我处理了 Shift 键按下,返回 true 似乎不是问题。按 5 次后会出现 Windows StickyKeys 消息,因此我认为该消息会进一步发送。非常感谢您的回复。
【解决方案2】:

为什么不直接从 DoUpdate 方法运行 SetComboValue 方法?如果这不起作用,您始终可以设置一个标志,说明它是从 DoUpdate 方法设置的,并且仅在直接访问时运行选定的索引更改事件。只是一个想法。

当我们在加载表单期间有一堆与组合框和列表相关的事件时,我们会做类似的事情。我们正在设置值并且不希望事件在加载期间触发,因此我们有一个标志来防止事件在表单加载完成之前触发。

我的想法是您正在设置该值,但其他一些事情正在强制发生第二个选定项更改事件。但是,由于您在 DoUpdate 方法和 SetComboValue 方法中设置了 selectedindex,因此看起来您可能会陷入无限循环。

只需在一处更改所选索引。

【讨论】:

  • 感谢您的评论约书亚。这不会改变问题,因为在 SetComboValue 中是这一行:comboBox1.SelectedItem = value.ToString(); (实际上是 comboBox1.SelectedItem = Convert.ToInt32(value); 但我改变了因为不正确)这将再次触发 selectedIndexChanged 事件。因此,即使我设置了值,即使我调用了一个方法来设置值,我也会遇到同样的问题。由于设计原因,我没有调用 SetComboValue。我认为最好让该函数由其他方法调用。
  • 我尽量避免添加另一个全局变量来充当标志,因为我已经有一些标志需要关心,我不认为这是一个好的设计。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-23
  • 2013-06-29
  • 2018-02-15
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多