BindingList <> ListChanged事件

And*_*ndy 19 .net c# data-binding datagridview winforms

我有一个类的BindingList <>设置为BindingSource的DataSource属性,该属性又设置为DataGridView的DataSource属性.

1.我的理解是,对列表的任何添加都将触发ListChanged事件,该事件将通过BindingSource传播,然后传播到DataGridView,DataGridView将更新自身以显示更改.这将发生,因为事件已自动连接.(是?)

当所有工作都在UI线程上完成时,这一切都很好,但是当从非UI线程创建和更改列表时,最终在更新网格时会发生跨线程异常.我能理解为什么会这样,但是没有办法解决这个问题......

2.我很难理解,我应该在哪里最好拦截ListChanged事件来尝试将内容整理到UI线程中?我猜我需要一个UI线程的引用以某种方式帮助做到这一点?

我已经阅读了很多这方面的帖子/文章,但我很难挣扎,因为我不完全理解这里的工作机制.

我们永远不会在列表中更改任何项目,只添加它们,并最初清除列表.

(我使用的是.NET 2.0)

MaL*_*Lio 28

您可以扩展BindingList以使用ISynchronizeInvoke(由System.Windows.Forms.Control实现)将事件调用封送到UI线程.

然后,您需要做的就是使用新的列表类型,并对所有列表进行排序.

public partial class Form1 : System.Windows.Forms.Form {

    SyncList<object> _List; 
    public Form1() {
        InitializeComponent();
        _List = new SyncList<object>(this);
    }
}

public class SyncList<T> : System.ComponentModel.BindingList<T> {

    private System.ComponentModel.ISynchronizeInvoke _SyncObject;
    private System.Action<System.ComponentModel.ListChangedEventArgs> _FireEventAction;

    public SyncList() : this(null) {
    }

    public SyncList(System.ComponentModel.ISynchronizeInvoke syncObject) {

        _SyncObject = syncObject;
        _FireEventAction = FireEvent;
    }

    protected override void OnListChanged(System.ComponentModel.ListChangedEventArgs args) {
        if(_SyncObject == null) {
            FireEvent(args);
        }
        else {
            _SyncObject.Invoke(_FireEventAction, new object[] {args});
        }
    }

    private void FireEvent(System.ComponentModel.ListChangedEventArgs args) {
        base.OnListChanged(args);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 真棒.如果我可以百万次投票,我愿意. (3认同)