频繁更新DataGridview(1/秒)并保持滚动状态和用户交互性

本文关键字:滚动 状态 交互性 用户 DataGridview 更新 | 更新日期: 2023-09-27 18:08:31

我有一个DataGridview,我正在从一个外部事件更新到我大约每秒一次。当我设法捕捉滚动位置时;DataGridView倾向于在显示第1行到最后一个可见列的显示中重置自己-但我的滚动条保持位置。我也希望我的DataGridView允许更多的用户交互,但它充其量是笨拙的。更新还导致我的应用程序消耗了25%的CPU时间(它所做的就是捕获事件并更新网格(30行10列,主要是整数和浮点数)。

我的两个问题是:

1:如何强制滚动&网格视图位置更新?

2:如何有效地更新DataGridView,以保持用户交互性,同时频繁更新源(@ 1/秒)?(现在我的代码消耗了25%的CPU来完成这个任务。)戴尔精密M4700 24GB内存)

我代码:

void UpdateBayGridview(System.Collections.Generic.List<BAY> bay)
{
    int vscroll = dgBinContent.FirstDisplayedScrollingRowIndex;
    int hscroll = dgBinContent.FirstDisplayedScrollingColumnIndex;
    this.BayTable.BeginLoadData();
    DataTable dtupdates = bay.ToDataTable<BAY>();
    DataColumn[] pkUPdateColumn = { dtupdates.Columns["ID"] };
    dtupdates.PrimaryKey = pkUPdateColumn;
    DataColumn[] pkColumn = { this.BayTable.Columns["ID"] };
    this.BayTable.PrimaryKey = pkColumn;
    this.BayTable.Merge(dtupdates);
    this.BayTable.EndLoadData();
    schemachange = false;
    bsBays.ResetBindings(schemachange);
    // Set the scroll positions
    if (vscroll < 0)
        vscroll = 0;
    if (hscroll < 0)
        hscroll = 0;
    dgBinContent.FirstDisplayedScrollingRowIndex = vscroll;
    dgBinContent.FirstDisplayedScrollingColumnIndex = hscroll;
}

频繁更新DataGridview(1/秒)并保持滚动状态和用户交互性

问题是我是多线程的,没有正确地控制线程以及我试图合并的绑定数据源。所以事情被击中两次或打乱了顺序-所以我修改了代码,使用线程绑定列表,使用字典合并方案,以及一个允许我更新GUI的Invoke扩展方法。

代码工作得很好。我使用一个异步任务方法来调用它——即发即忘。

    private async void WCF_ReceiveProductList(object sender, List<iSortData.PRODUCTS> e)
    {
        VScrollPosition["PRODUCT"] = dgProductContent.FirstDisplayedScrollingRowIndex;   
        HScrollPosition["PRODUCT"] = dgProductContent.FirstDisplayedScrollingColumnIndex;
        if (e.Count > 0)
        {
            await Task.Factory.StartNew(() => TaskBased_UpdateProductList(e)).ConfigureAwait(false);
        }
    }
     private void TaskBased_UpdateProductList(List<iSortData.PRODUCTS> productlist)
    {
        lock (_synclock)
        {
            this.ProductBindingList = MergeListWithBindingProductList(productlist, ProductBindingList);
        }
        dgProductContent.InvokeEx(ProductContent =>
            {
                ProductContent.Refresh();
                ProductContent.ClearSelection();
            });
        SetGridScrollPositions(dgProductContent, "PRODUCT");
    }

   private Utility.Collections.ThreadedProductdingList<PRODUCT> MergeListWithBindingProductList(List<PRODUCT> list1, Utility.Collections.ThreadedProductdingList<PRODUCT> list2)
    {
        lock (_synclock)
        {
            var revdict = list1.ToDictionary(b => b.Name);
            if (list2.Count < 1)
            {
                PRODUCTS[] list3 = revdict.Values.ToArray();
                for (int x = 0, list3Length = list3.Length; x < list3Length; x++)    
                {
                    list2.Add(list3[x]); // index out of range ??(impossible) but happens if not properly threaded i.e. no (_synclock).
                }
            }
            else
            {
                for (int n = 0, list2Count = list2.Count; n < list2Count; n++)
                {
                    if ((!String.IsNullOrEmpty(list2[n].Name)) && revdict.ContainsKey(list2[n].Name))
                    {
                        list2[n] = revdict[list2[n].Name];
                    }
                }
            }
            return list2;
        }
    }