设置DataGridView.FirstDisplayedScrollingRowIndex可阻止计时器启动

本文关键字:计时器 启动 DataGridView FirstDisplayedScrollingRowIndex 设置 | 更新日期: 2023-09-27 18:27:02

好的,新的谜题!非常简单的概念验证设置:DataGridView,通过DataTable绑定到SQL视图。数据是动态的(尽管行数是恒定的),所以我添加了一个Forms.Timer来刷新它:

private DataTable   tbData= new DataTable( );
private void    frmMain_Load( object sender, EventArgs e )
{
    LoadData( );
    oTimer.Start( );
    MessageBox.Show( oTimer.Enabled.ToString( ) );
}
private void    frmMain_DoubleClick( object sender, EventArgs e )
{
    LoadData( );    // to reload on-demand - works perfectly
}
private void    LoadData( )
{
    SqlDataAdapter  da=
        new SqlDataAdapter( "select * from vwOne", Program.oSqlConn );
    tbData.Clear( );
    da.Fill( tbData );
    dgView.DataSource=  tbData;
}
private void    oTimer_Tick( object sender, EventArgs e )
{
    LoadData( );
    this.Text+= "|";
}

为了在刷新期间保持滚动位置,我添加了以下行(1和2):

private void    LoadData( )
{
    SqlDataAdapter  da=
        new SqlDataAdapter( "select * from vwOne", Program.oSqlConn );
    int iRow=   dgView.FirstDisplayedScrollingRowIndex; // 1-remember row
    tbData.Clear( );
    da.Fill( tbData );
    dgView.DataSource=  tbData;
    dgView.FirstDisplayedScrollingRowIndex=     iRow;   // 2-restore back
}

到目前为止还不错。现在关键是:在没有第2行重载的情况下可以完美地工作(不保留滚动),但只要我取消注释第2行,计时器就会停止(oTimer_Tick中的断点永远不会命中)

什么给了!?

编辑:frmMain_DoubleClick(..)添加到上面的代码中(已经有了,并且一直在使用),它工作正常绝对没有抛出异常,SQL连接也没有问题。从字面上看,取消对那一行(#2)的注释会产生完全的不同,在oTimer_Tick中根本没有被调用!

根据建议(谢谢大家!)我添加了几条新的线路:

  • frmMain_Load(..)显示oTimer.Enabled并确认其结束
  • 并在每次oTimer_Tick(..)触发时在窗体的标题后附加一个"|"

在没有第2行的情况下,执行按预期进行:消息框显示"True",标题随着新的"|"而不断增长。取消注释行2和。。没有消息框!?,没有标题更新,但没有任何例外!?这是在调试模式下直接从VS2010运行的,调试器会吞下任何异常吗(我从未见过)?据推测,由于没有显示消息框,这表明问题在于启动计时器,=>它不会启动。但正如我所说,唯一的变化是取消第2行的注释。它是如何/为什么影响计时器的!?

好的,接下来要尝试的是通过动态切换(例如通过复选框)是否保留滚动位置来避免重新编译,在剩下的可视化过程中,这可能会暴露smth。。

设置DataGridView.FirstDisplayedScrollingRowIndex可阻止计时器启动

这可能是一条评论,但我没有足够的信誉点来评论,所以…

你在oTimer.Start()上设置了断点吗?frmMain_Load()中对LoadData()的第一次调用是否完成?您的连接打开了吗?正如大卫·霍尔所提到的,也许有一个例外正在被吞噬。。。

Edit2:好吧,我终于找到了根本原因:启用了第2行,oTimer.Start( )没有被调用。原因是在第一次调用LoadData()[来自frmMain_Load(..)]期间,第2行产生了一个异常(,因为该索引的初始值是-1,这是一个要赋值回的无效值)!保持滚动位置的正确方法是这样更改第2行:

if(  iRow >= 0  )   dgView.FirstDisplayedScrollingRowIndex=     iRow;

然而,令人讨厌的是,如果不向LoadData()添加显式的try-catch块,我就找不到它!在表单初始化/加载过程中,似乎所有异常都被静默地吞噬了经验教训;但IMHO这不是微软采取的一个好方法,因为我现在甚至不能依靠VS调试器来宣布WinForm中UI线程上可能发生的合理高级异常。

答案代表是@appclay,我会把它交给@David Hall,因为他是第一个暗示这种可能性的人
谢谢大家!