2012-03-06 111 views
1

好吧,新的谜题!非常简单的概念验证设置:DataGridView,通过DataTable绑定到SQL视图。数据是动态的(虽然行#是恒定的),所以我添加了一个​​刷新它:设置DataGridView.FirstDisplayedScrollingRowIndex停止发射定时器?

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行的执行如预期的那样:message-box表示'真',标题不断增加新的'|'。取消注释第2行,并且没有消息框!?,没有标题更新,但没有任何例外!?这是直接从VS2010以调试模式运行,可以调试器吞下任何异常(我从来没有见过这种情况)?估计,因为没有消息框显示这表示问题是启动计时器,=>它不会触发。但就像我说的,唯一的变化就是取消注释第2行..它如何/为什么会影响计时器!?

好的,接下来的尝试将通过动态切换(例如通过复选框)来避免重新编译是否保留滚动位置,其余的可视化处理,也许这会暴露无聊。

+0

滴答之间的时间间隔是多少?您可以尝试在调用LoadData()之前禁用定时器,并在加载完成后重新启用定时器。 – ebutusov 2012-03-06 22:55:53

+0

通常1秒,但它并不重要:我尝试了5,10和20 - 并且仍然没有快乐。数据检索在0.02秒内完成。还尝试在dvGrid_Scroll事件期间禁用Timer - 无效。最奇怪的是,即使是断点也不会被打 - 所以它实际上从来没有开火!但是,一个Timer如何知道并且关心我设置这个ScrollingRowIdx - 我到目前为止还不知道.. – Astrogator 2012-03-06 23:16:33

+0

为什么它值得我试过你的例子,并且不能复制这个问题。一个区别是我使用的是对象的BindingList作为数据源并向它添加行,但这不应该有所作为。你是否尝试过加载数据以确保在那里没有什么奇怪的事情发生?你有没有检查,看看你的IDE没有隐藏任何异常? – 2012-03-06 23:26:58

回答

1

这大概应该是一个评论,但我没有足够的信誉分置评所以...

你已经把一个断点oTimer.Start()?第一次调用frmMain_Load()中的LoadData()是否完成?你的连接是否打开?也许有这以某种方式被吞噬,正如大卫音乐厅提到的例外?

1

EDIT2:嗯,我终于找到了根本原因:与2号线启用oTimer.Start()不会被调用。原因是在第一次调用LoadData()[来自frmMain_Load(..)]时,第2行产生一个异常(,因为该索引的初始值为-1,这是一个无效值,将被分配回 )!正确的方式来保持滚动位置将改变2号线这样的:

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

但是讨厌的事情是,不添加一个明确的try-catch块LoadData()我不会找到它!在表单初始化/加载期间看起来像任何异常正在悄悄吞噬!!经验教训;但恕我直言,这不是一个好的方法,因为我甚至不能依靠VS调试器来宣布在WinForm的UI线程中可能发生的合理的高级异常。

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