频繁更新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;
}
问题是我是多线程的,没有正确地控制线程以及我试图合并的绑定数据源。所以事情被击中两次或打乱了顺序-所以我修改了代码,使用线程绑定列表,使用字典合并方案,以及一个允许我更新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;
}
}