天天看点

C# Winform Datagridview 排序 多线程操作数据 遇到的坑

先上代码:

public class BindingCollection<T> : BindingList<T>
    {
        protected bool isSorted;
        protected PropertyDescriptor sortProperty;
        protected ListSortDirection sortDirection;
        public ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
        /// <summary>
        /// 构造函数
        /// </summary>
        public BindingCollection()
            : base()
        {
        }


        public delegate void ApplySortCoreDel(PropertyDescriptor property, ListSortDirection direction);
        /// <summary>
        /// 自定义排序操作
        /// </summary>
        /// <param name="property"></param>
        /// <param name="direction"></param>
        protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
        {
          
            List<T> items = this.Items as List<T>;
            try
            {
                if (Items != null)
                {
                   
                    ObjectPropertyCompare<T> pc = new ObjectPropertyCompare<T>(property, direction);
                    items.Sort(pc);
                    isSorted = true;
                }
                else
                {

                    isSorted = false;
                }

                sortProperty = property;
                sortDirection = direction;
            }
            catch (Exception ex)
            {
                log.Error("ApplySortCore");
                log.Error(ex);

            }
           
        }
        public  void ApplySort(PropertyDescriptor property, ListSortDirection direction)
        {
            ApplySortCore(property, direction);
        }
        /// <summary>
        /// 获取一个值,指示列表是否已排序
        /// </summary>
        protected override bool IsSortedCore
        {
            get
            {
                return isSorted;
            }
        }

        /// <summary>
        /// 获取一个值,指示列表是否支持排序
        /// </summary>
        protected override bool SupportsSortingCore
        {
            get
            {
                return true;
            }
        }

        /// <summary>
        /// 获取一个只,指定类别排序方向
        /// </summary>
        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return sortDirection;
            }
        }

        /// <summary>
        /// 获取排序属性说明符
        /// </summary>
        protected override PropertyDescriptor SortPropertyCore
        {
            get
            {
                return sortProperty;
            }
        }

        /// <summary>
        /// 获取一个只,指定类别排序方向
        /// </summary>
        public  ListSortDirection SortDirection
        {
            get
            {
                return sortDirection;
            }
        }

        /// <summary>
        /// 获取排序属性说明符
        /// </summary>
        public  PropertyDescriptor SortProperty
        {
            get
            {
                return sortProperty;
            }
        }
        /// <summary>
        /// 移除默认实现的排序
        /// </summary>
        protected override void RemoveSortCore()
        {
            isSorted = false;
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

    }
    public class BindingListInvoked<T> : BindingCollection<T>
    {
        public BindingListInvoked() { }

        private static ISynchronizeInvoke _invoke;
        public BindingListInvoked(ISynchronizeInvoke invoke) { _invoke = invoke; }
        public BindingListInvoked(IList<T> items) { this.DataSource = items; }
        public void SetInvoke(ISynchronizeInvoke invoke) { _invoke = invoke; }
        delegate void ListChangedDelegate(ListChangedEventArgs e);

        protected override void OnListChanged(ListChangedEventArgs e)
        {

            if ((_invoke != null) && (_invoke.InvokeRequired))
            {
                IAsyncResult ar = _invoke.BeginInvoke(new ListChangedDelegate(base.OnListChanged), new object[] { e });
            }
            else
            {
                base.OnListChanged(e);
            }
        }
        public IList<T> DataSource
        {
            get
            {
                return this;
            }
            set
            {
                if (value != null)
                {

                    this.ClearItems();
                    RaiseListChangedEvents = false;

                    foreach (T item in value)
                    {
                        this.Add(item);
                    }
                    isSorted = false;
                    sortProperty = null;
                    //sortDirection = ListSortDirection.;
                    RaiseListChangedEvents = true;
                    OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
                }
            }
        }
       
       
        }
    }
           

以前公司 没有用原生 C# winform 控件,但考虑到 打开页面速度,决定用 原生的Winform 控件。最长用的控件 就是Datagridview。

用List<T> 绑定数据后不能排序,百度后,我写了BindingCollection<T> 

他们说 用了BindingCollection 就可以绑定一次 ,修改Add数据是不用重新绑定。

我还以为,回头是岸了。没有想到是苦海的开始:

因为Datagridview 一旦修改数据就会报 错BiJie.DealForm.FrmDealBuy - System.IndexOutOfRangeException: 索引 4 没有值

一大堆呀

后来才知道 BindingCollection 在Add 时会触发一些 UI ,更新UI 要在主线程 操作。

而 我用了多线程。。哈哈。。

我又一次 高兴了。可是我设置了 一个 主窗体 做为SetInvoke 的参数 赋给 一个静态变量。

可是 错误 还是存在。。。。愤怒。。。

没有办法 调试吧 。。。

功夫不负有心人

原来 在C# 中 BindingCollection<int> 和BindingCollection<string> 是 两个类 在其中定义的 static 变量 当然也不能通用,是不同的两个变量。

哈哈 到此为止 这个问题 总算 解决了

BindingCollection<Entity1>.setInvoke(Form1);

 BindingCollection<Entity2>.setInvoke(Form1);

BindingCollection<T>中 不同的T 都要 设置 他的static 变量。