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.InvalidOperationExceptions。这导致性能非常差,这是我必须纠正的。

我明白发生了什么。在表单上,​​我们使用控件的 Text 属性将 TextBox 控件绑定到网格的 BindingSource。每次将行合并到 BindingSource 时都会触发此绑定。最后一部分没有被观察到,这有点猜测,但绝对数量的异常表明这是正确的假设。那,以及当我注释掉所有绑定时,性能显着提高的事实。

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

我也已经尝试过了:

g.SuspendBinding();

它没有任何区别。事实上,我已经尝试在等式的两端暂停绑定,在表单和线程刷新中,但总是所有尝试都没有结果。

你能帮我吗?

4

2 回答 2

3

这可能是您的问题(取自MSDN)。

使用 SuspendBinding 并防止在调用 ResumeBinding 之前将更改推送到数据源,但实际上不会阻止任何事件的发生。使用复杂数据绑定的控件(例如 DataGridView 控件)根据更改事件(例如 ListChanged 事件)更新其值,因此调用 SuspendBinding 不会阻止它们接收对数据源的更改。因此,此 SuspendBinding 和 ResumeBinding 设计用于与简单绑定控件(如 TextBox 控件)一起使用。或者,如果通过将 RaiseListChangedEvents 属性设置为 false 来抑制 ListChanged 事件,则可以在复杂的绑定方案中使用这些方法。

于 2012-12-20T14:56:44.277 回答
1

就其价值而言,hack 方法似乎确实很成功。我不是很喜欢它,但我也看不到任何不涉及手动绑定全谱控制的替代方法。

我有幸拥有基于我们从 Form 派生的类的所有 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 是我们表单类的成员,它是递归循环的结果,该循环返回控件名称和控件对象的哈希表。

于 2012-12-20T18:04:38.897 回答