2012-12-20 67 views
0

首先,有问题的代码:为什么我不能在绑定源上挂起绑定?

public virtual void grid_RefreshFetchData(Object sender, RefreshEventArgs e) 
{ 
    C1DBGrid g = (C1DBGrid)sender; 
    if (g.RefreshUseResult) 
    { 
     DataTable dtNew = FetchRawData(e.Argument); 
     dt_Patch(dtNew, e.Argument); 
     g.BindingSource.SuspendBinding(); 
     ((DataTable)g.BindingSource.DataSource).Clear(); 
     ((DataTable)g.BindingSource.DataSource).Merge(dtNew); 
     g.BindingSource.ResumeBinding(); 
    } 
} 

你看到的是一个正在从最终推出,因为Windows窗体想要的数据后台线程调用的事件处理程序。网格对象(它是一个ComponentOne TrueDBGrid)由该表单拥有,并且我们设置了一些事件来允许表单告诉网格请求新数据。这个调用导致这个处理器,其目的是请求一个底层数据类来获取带有记录的DataTable,然后将该表与网格的BindingSource(它是同一模式的DataTable)进行合并。

我的问题:当调用Merge()方法将新数据合并到网格(新清空的)BindingSource(同样,DataTable本身)时,会引发大量的异常。每个异常实例都是三重异常:一个System.Reflection.TargetInvocationException后跟一对System.InvalidOperationException。这会导致难以置信的糟糕表现,而这正是我必须解决的问题。

我明白发生了什么事。在表单上,​​我们使用控件的Text属性将TextBox控件绑定到网格的BindingSource。每次将行合并到BindingSource时,都会触发此绑定。最后一部分没有被观察到,这是一个猜测,但绝对数量的例外表明这是一个正确的假设。这一点,以及当我评论出所有约束力时,表现都大幅度提高。

所以我要求的是帮助理解我如何暂停这个绑定触发器。正如你所看到的,我在事件处理程序中有行尝试在BindingSource上挂起它。

我已经尝试过这个问题,以及:

g.SuspendBinding(); 

它没有什么区别。事实上,我试图在表达式和线程刷新中暂停等式两端的绑定,但所有尝试都是徒劳的。

你能帮忙吗?

回答

3

这可能是你的问题(摘自MSDN)。

使用SuspendBinding并防止推入 数据源直到ResumeBinding被称为变化,但实际上并不 防止发生任何事件。使用复杂数据绑定的控件(如DataGridView控件)在更改事件(如ListChanged事件)时基于 更新其值,因此调用 SuspendBinding不会阻止它们接收对 数据源所做的更改。因此,此SuspendBinding和ResumeBinding 设计用于简单绑定的控件,如TextBox 控件。或者,如果您通过将 RaiseListChangedEvents属性设置为false来禁止ListChanged事件,则可以在复杂绑定方案 中使用这些方法。

+0

我也遇到过,我也很奇怪。也许是。希望有人知道比我更能根据我所描述的来确认这一点。尽管“简单控制”部分确实符合我所做的。我的绑定看起来像这样:txtEquipment.DataBindings.Add(“Text”,gridMain.BindingSource,“fldEquipNo”); – DonBoitnott

+0

@DonBoitnott,我感到你的痛苦。我以前经历过这样的事情,经常诉诸摆脱束缚,因为我的事件在各地都有发生。 (想想充满捕鼠器的房间里的卡通人物,踏上一个,它会触发可怕的连锁反应!) – Stainy

+0

D,那会很粗糙。我们有50份表格的订单,所有表格都至少与一个拥有的网格绑定。那太糟糕了。也许是不可逾越的......我们不是一个大装备。我考虑设立一个委托人,当我需要“暂停”时可以被解雇,而且这个委托人可以为控制做些事情。也许存储绑定,删除它们,并在刷新完成后替换它们?看起来像这样的黑客......但我还能做什么? – DonBoitnott

0

对于什么是值得的,黑客方法似乎取得了很好的成功。我不太喜欢它,但我也没有看到任何不涉及手动全面控制绑定的替代方法。

我有我所有的Windows窗体基于我们从窗体派生的类的豪华。所以在那里,我制作了两个方法:SuspendBinding()和ResumeBinding()。

这里是什么,我做了一个样本:

private List<KeyValuePair<String, Binding>> _savedBindings = new List<KeyValuePair<String, Binding>>(); 

private delegate void InvokeSuspendBinding(); 
public void SuspendBinding() 
{ 
    if (InvokeRequired) 
    { 
     Invoke(new InvokeSuspendBinding(SuspendBinding)); 
     return; 
    } 

    foreach (DictionaryEntry entry in ChildControls) 
    { 
     if (entry.Value is Control && ((Control)entry.Value).DataBindings.Count > 0) 
     { 
      for (Int32 i = 0; i < ((Control)entry.Value).DataBindings.Count; i++) 
      { 
       _savedBindings.Add(new KeyValuePair<String, Binding>(entry.Key as String, ((Control)entry.Value).DataBindings[i])); 
       ((Control)entry.Value).DataBindings.RemoveAt(i); 
      } 
     } 
    } 
} 

private delegate void InvokeResumeBinding(); 
public void ResumeBinding() 
{ 
    if (InvokeRequired) 
    { 
     Invoke(new InvokeResumeBinding(ResumeBinding)); 
     return; 
    } 

    foreach (DictionaryEntry entry in ChildControls) 
    { 
     foreach (KeyValuePair<String, Binding> kvp2 in _savedBindings) 
     { 
      if (kvp2.Key.Equals(entry.Key)) 
       ((Control)entry.Value).DataBindings.Add(kvp2.Value); 
     } 
    } 

    _savedBindings.Clear(); 
} 

注意,在循环中引用的成员ChildControls是我们的窗体类的成员,这是一个递归循环返回控制的一个Hashtable的结果名称和控制对象。

相关问题