天天看點

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 變量。