【问题标题】:Cancelling Windows Forms Events取消 Windows 窗体事件
【发布时间】:2009-11-19 19:15:46
【问题描述】:

我有一个 Windows 窗体。它有一个ComboBox 和一个DataGrid

我的ComboBox 上有一个Leave 事件,我的DataGrid 行上有一个DoubleClick 事件

这个想法是,在离开ComboBox 时,如果ComboBox 的值发生了变化,那么使用新值重新加载DataGrid

假设ComboBox 显示的值为1,对于该值,DataGrid 中显示了 5 条记录。 现在用户在ComboBox 中输入2 并跳开。在我的 Leave 事件中,我看到该值已更改,我重新加载了 DataGrid 以及该值的所有记录。

但如果用户输入2 并双击现有记录的值1,则 离开事件重新加载DataGrid,然后DoubleClick 事件触发。

如果DataGrid 已重新加载,我如何找到待处理事件列表并取消每个事件?

【问题讨论】:

    标签: winforms events


    【解决方案1】:

    您遇到了事件顺序问题,DataGridView.Enter 事件触发得太快了。这可以通过使用 Control.BeginInvoke() 方法延迟事件操作来彻底解决。一旦您的程序重新进入消息循环,它的委托目标就会触发。换句话说,在所有未决事件都已触发之后。让它看起来像这样:

    private bool selectionDirty;
    
    private void comboBox1_TextChanged(object sender, EventArgs e) {
      selectionDirty = true;
    }
    
    private void dataGridView1_Enter(object sender, EventArgs e) {
      this.BeginInvoke(new Action(() => selectionDirty = false));
    }
    
    private void dataGridView1_CellMouseDoubleClick(object sender, DataGridViewCellMouseEventArgs e) {
      if (selectionDirty) return;
      // etc...
    }
    

    【讨论】:

    • 我会在星期一早上试试这个
    • 我认为这行不通。因为在进入数据网格时,不能保证它被重新加载。
    • 我需要 Jon Skeet 或 Ayende 来帮助我
    【解决方案2】:

    不要使用Leave 事件,而是尝试SelectedIndexChanged Event,它将在DataGrids DoubleClick 事件之前触发。缺点是如果用户使用键盘滚动ComboBox,那么如果用户在ComboBox 中向下滚动5 步,它将触发5 次。

    另一种解决方案是在输入ComboBox 时存储一个局部变量lComboEntered=true,并在触发Leave 事件时将该值设置为false。在DataGridDoubleClick事件中检查lComboEntered=false是否在做任何事情之前。

    【讨论】:

    • 在我的离开事件例程中,如果组合框的值发生了变化,我会重新加载数据网格并将 CancelDoubleClick 标志设置为 TRUE。在我的数据网格双击例程中,我检查了这个标志,如果它是真的就取消事件。如果我更改组合框中的值并双击一行而不做任何其他事情,这会很好。但是,如果我在组合框中输入一个值并简单地使用 tab 键,那么我必须双击数据网格 TWICE。我还能在哪里将该标志重置为 FALSE。
    猜你喜欢
    • 1970-01-01
    • 2017-06-15
    • 2018-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-20
    • 1970-01-01
    相关资源
    最近更新 更多