【winform】datagridview获取当前行停留时间


RowStateChanged 的问题#

RowStateChanged事件,也就是行状态发生变化时触发的事件,这个事件无法实现行号变化而触发这个要求,因为当我们从一行选择至另一行时,先触发原行号的状态变事件,然后触发新行号的状态变更事件,也就是换一次行,触发两次事件。

private void dataGridView1_RowStateChanged(object sender, DataGridViewRowStateChangedEventArgs e)
        {
            // if (e.Row.Index == -1)
            // {
            //     return;
            // }
            //
            // if (int.TryParse(dataGridView1.Rows[e.Row.Index].Cells["ID"].Value.ToString(), out int intTryResult))
            // {
            //     int.Parse(dataGridView1.Rows[e.Row.Index].Cells["ID"].Value.ToString());
            // }
            //
            // TableJson json = tableJsons.Find(s => s.ID == intTryResult);
            //
            // if (!e.Row.Selected)
            // {
            //     if (json.StartTime != DateTime.MinValue)
            //     {
            //         if (this.tgtControl1.LabelSrcText != "undefined")
            //         {
            //             try
            //             {
            //                 json.EndTime = DateTime.Now;
            //                 json.TimeSpan = json.EndTime - json.StartTime + json.TimeSpan;
            //                 DataTable table = (DataTable)this.dataGridView1.DataSource;
            //                 table.Rows[json.ID - 1]["time"] =
            //                     json.TimeSpan.ToString(
            //                         @"hh\:mm\:ss"); //table.Rows[json.ID - 1]["timer"] = json.TimeSpan.ToString(@"hh\:mm\:ss");
            //             }
            //             catch (Exception exception)
            //             {
            //                 Console.WriteLine(exception);
            //                 throw;
            //             }
            //         }
            //     }
            // }
            // else
            // {
            //     json.StartTime = DateTime.Now;
            // }
        }

datagridview滚动的时候,也会执行RowStateChanged2次。最上一行与最下一行。

SelectionChanged 与 RowLeave#

选中行时,使用SelectionChanged,离开行时,使用RowLeave

1、使用SelectionChanged事件

MSDN的事件说明:此事件会在选择或取消选择单元格(无论是以编程方式还是通过用户操作的方式)时发生(所以此事件与CurrentCellChanged一样,是针对单元格设计的,DataGridView本身就是针对单元格设计的)。例如,当您希望显示当前选定的单元格之和时,此事件非常有用。当您更改 CurrentCell 属性的值时,SelectionChanged 事件发生在 CurrentCellChanged 事件之前。此时访问 CurrentCell 属性的任何 SelectionChanged 事件处理程序都将获取其以前的值。

说明:我们要求的是行号改变时才触发事件,那么我们可以在事件后判断行号是否发生变化,或者将selectionmode属性设置为FullRowSelection,也就是整行选择模式,这样就可以实现要求了。

问题:在初始化DataGridView时,系统会触发N次SelectionChanged事件,而我们希望用户通过鼠标点击或键盘选择的方式改变行号时才触发事件,所以我们还需要设置一个开关,用来指示什么时候开始处理该事件。

2、使用CurrentCellChanged事件(!!!)

说明:这个就是当前单元格发生变化时触发的事件,用法和问题和SelectionChanged事件几乎一样,但是触发顺序不同。因为SelectionChanged要发生在CurrentCellChanged之前,所以用dataGridView1.Rows[xx].Selected = true;的形式或dataGridView1.CurrentCell = dataGridView1.Rows[xx].Cells[xx]改变单元格时,用SelectionChanged事件获取的CurrentCell值为改变之前的值,而一般情况我们想要获取的是改变后的值,所以SelectionChanged就无法实现我们的要求。

所以:一般情况,我们更多的使用CurrentCellChanged事件。

当然,CurrentCellChanged事件也有一些问题,例如窗体加载完毕后,CurrentCell 从NULL被默认赋值为第一行第一列时,系统会触发CurrentCellChanged事件,而一般情况我们只希望用户点击或代码控制的方式触发事件。类似的情况在SelectionChanged事件则不会发生。

总结:如果不需要使用代码改变CurrentCell 的值,而仅需要响应鼠标和键盘给CurrentCell 带来的变化,那就使用SelectionChanged事件吧,否则,使用CurrentCellChanged可能更能实现任务要求。一般情况下是这样。

这里有个问题。RowLeave 在焦点从datagridview到其他控件上,例如textbox选中时,也会执行RowLeave事件。这里判断dataGridView1.Focused看焦点是否在datagridview上。

private void dataGridView1_SelectionChanged(object sender, EventArgs e)
        {
            var row = dataGridView1.CurrentRow; //当前行
            if (int.TryParse(dataGridView1.Rows[row.Index].Cells["ID"].Value.ToString(), out int intTryResult))
            {
                int.Parse(dataGridView1.Rows[row.Index].Cells["ID"].Value.ToString());
            }

             TableJson json = tableJsons.Find(s => s.ID == intTryResult);

            json.StartTime = DateTime.Now;
        }

        private void dataGridView1_RowLeave(object sender, DataGridViewCellEventArgs e)
        {
            //指示该控件是否有焦点,
            //判断是否其他控件获取焦点,就不执行。
            if (dataGridView1.Focused)
            {
                if (int.TryParse(dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString(), out int intTryResult))
                {
                    int.Parse(dataGridView1.Rows[e.RowIndex].Cells["ID"].Value.ToString());
                }

                TableJson json = tableJsons.Find(s => s.ID == intTryResult);


                if (this.tgtControl1.LabelSrcText != "undefined")
                {
                    try
                    {
                        json.EndTime = DateTime.Now;
                        json.TimeSpan = json.EndTime - json.StartTime + json.TimeSpan;
                        DataTable table = (DataTable)this.dataGridView1.DataSource;
                        table.Rows[json.ID - 1]["time"] =
                            json.TimeSpan.ToString(
                                @"mm\:ss"); //table.Rows[json.ID - 1]["timer"] = json.TimeSpan.ToString(@"hh\:mm\:ss");
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine(exception);
                        throw;
                    }
                }
            }
        }

作者:【唐】三三

出处:https://www.cnblogs.com/tangge/p/10413143.html

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。

posted @   【唐】三三  阅读(471)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
历史上的今天:
2011-02-21 提高编程技能最有效的方法
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
menu
点击右上角即可分享
微信分享提示