繁体   English   中英

C#datagridview行切换

[英]C# datagridview row toggle

我正在寻找有关datagridview的帮助。

我想做的是,当我单击receiveview(datagridview)列表中的一个项目(一行)时,它应该切换该行的选择(即,如果它已被选择,它将取消选择,反之亦然)。

到目前为止,我已经找到了以下代码,但是,这并非一直有效:

    private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
    {
        if (!_selectionChanged)
        {
            //do other stuff here
            receiptView.ClearSelection();
            _selectionChanged = true;
        }
        else
        {
            //do other stuff here
            _selectionChanged = false;
        }
    }

    private void receiptView_SelectionChanged(object sender, EventArgs e)
    {
        _selectionChanged = true;
    }

FYI

  • 当单击某行并且没有选择任何行或者已经选择了某行并且现在选择了新行时,它将按以下顺序触发事件:

    1. receiptView_SelectionChanged
    2. receiptView_CellClick
  • 单击某行并已将其选中时,它仅会触发receiveView_CellClick事件

问题

发生的事情是,当我非常快地选择/取消选择一行时(类似于双击),最终将“取消同步”实际的选择状态和_selectionChanged 我的意思是:

  1. 选中某行后,它将高亮显示/选择该行(正常)
  2. 现在再次选择同一行(快速单击后)时,它不会取消选择该行,但似乎被选中,而错误的“在这里做其他事情”被执行了(不正常,应该取消选择)
  3. 在第三次单击时,它取消选择(如果是步骤2,则为正常,应该只有两个步骤)

并非每次我快速点击都会发生这种情况,但它会定期发生(大约每第二/第三次点击对)。 如果我缓慢而故意地单击,就永远不会发生。

理论

我真的不知道为什么会这样,但是我怀疑由于点击1和点击2发生得非常接近,当第二个点击事件仍在运行时会触发第二个点击事件,导致第一次点击将_selectionChanged更改为false,并且第二个将其更改回true,同时保持选定的行。 但是,由于我没有创建任何新线程,并且所有线程都在主UI线程上运行,因此它不应该是序列化的执行吗? 即单击1的事件触发器,一旦完成,单击2的事件触发器?

如果你们中的任何一个知道一种更简单的方法(在datagridview中切换),或者可以看到错误和/或找到解决方案,将不胜感激。

谢谢。

TL; DR

您的第二次点击被CellDoubleClick事件劫持。 使用您的CellClick事件处理程序中的相同代码来订阅它。
-请参阅答案末尾的解决方案

调试说明

为了演示正在发生的事情,我们将以下输出添加到您的方法中,然后运行您在OP中描述的场景。

private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    if (!_selectionChanged)
    {
        Console.WriteLine("Cleared.......");
        receiptView.ClearSelection(); // NOTE: Triggers SelectionChanged event.
        _selectionChanged = true;
    }
    else
    {
        Console.WriteLine("Highlighted...");
        _selectionChanged = false;
    }
}

private void receiptView_SelectionChanged(object sender, EventArgs e)
{
    Console.WriteLine("Changed!");
    _selectionChanged = true;
}

当前未选择任何行,以下测试,预期结果和实际结果:

+======================+=================+================+=================+
|       ACTION         | EXPECTED OUTPUT | ACTUAL OUTPUT  |   GUI RESULTS   |
+======================+=================+================+=================+
| Single-click 1st row | Changed!*       | Changed!*      | Row Highlighted |
|                      | Highlighted...  | Highlighted... |                 |
+----------------------+-----------------+----------------+-----------------+
| Double-click 1st row | Cleared.......  | Cleared....... | Row Highlighted |
|                      | Changed!^       | Changed!^      |                 |
|                      | Changed!*       | Changed!*      |                 |
|                      | Highlighted...  |                |                 |
+----------------------+-----------------+----------------+-----------------+
| Single-click 1st row | Cleared.......  | Highlighted... | Row Highlighted |
|                      | Changed!^       |                | (Still...?)     |
+----------------------+-----------------+----------------+-----------------+

* SelectionChanged在后面的代码中触发; 现在选择了未选中的行。
^通过调用ClearSelection()触发SelectionChanged。

分析 :第一次单击将触发SelectionChanged并按预期突出显示该行。 接下来, 双击该行,认为第一次单击将清除该行(您将手动导致该行触发SelectionChanged ),第二次单击(再次在背景中触发SelectionChanged )再次突出显示该行。 这是我们出问题的地方。

通过双击 ,第一次单击将按预期触发clear和SelectionChanged事件。 我们甚至从SelectionChanged看到了第二个预期的打印输出,但是没有从CellClick事件中看到突出显示的打印输出。 为什么?

单击一次行/单元格时,将触发CellClick 当您快速连续单击两次时, CellClick触发第一次单击,而CellDoubleClick触发第二次单击。 因此,您的第一次点击将按预期方式命中您的代码。 第二次单击永远不会命中您的代码,除了在后台仍然选择了未选择的行,因此SelectionChanged仍会再次触发。 从这一点开始,您的_selectionChanged标志已关闭-导致更多不准确的结果。

解决方案 :订阅CellDoubleClick事件并执行它相同的代码在CellClick ,你会没事的。

private void receiptView_CellClick(object sender, DataGridViewCellEventArgs e)
{
    this.DoStuff();
}

private void receiptView_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
    this.DoStuff();
}

private void DoStuff()
{
    if (!_selectionChanged)
    {
        //do other stuff here
        receiptView.ClearSelection();
        _selectionChanged = true;
    }
    else
    {
        //do other stuff here
        _selectionChanged = false;
    }
}

暂无
暂无

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

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