簡體   English   中英

c#填充datagridview的速度很慢

[英]c# very slow populating the datagridview

我正在從數據表填充 datagridview。

在填充列和行的同時,我也同時對其進行格式化,這導致 datagridview 加載非常緩慢,是否有解決此問題的方法?

除了處理AutoSizeColumnsMode ,還要確保各個列的AutoSizeMode屬性也設置為除所有單元格之外的其他值。

我也發現有必要使用

SendMessage(dg.Handle, WM_SETREDRAW, false, 0); // before

// updates to datagridview here...

SendMessage(dg.Handle, WM_SETREDRAW, true, 0); // after

有了這個,datagridview 將像 java jtable 一樣快 :)

public static class ExtensionMethods
{
    public static void DoubleBuffered(this DataGridView dgv, bool setting)
    {
        Type dgvType = dgv.GetType();
        PropertyInfo pi = dgvType.GetProperty("DoubleBuffered",
            BindingFlags.Instance | BindingFlags.NonPublic);
        pi.SetValue(dgv, setting, null);
    }
}

ExtensionMethods.DoubleBuffered(dataGridView1, true);

我花了大約 2-4 分鍾來加載 1-2k 行。 我更改了 auto-resize 屬性,現在它縮短到幾秒鍾,可能是 10-20。 我在行創建循環之前運行它以確保它獲得所有列。

foreach (DataGridViewColumn c in thisGrid.Columns)
{
    c.AutoSizeMode = DataGridViewAutoSizeColumnMode.None;
}

您可以檢查 DataGridView 的屬性 - AutoSizeColumnsMode 我發現,如果我將模式從 AllCells 更改為 DisplayedCells,則性能會有所不同。 我希望這能幫到您。

當您使用 datagrid 視圖顯示來自 dataabse 的數據時,您應該始終考慮使用某種策略來限制結果集並僅在用戶真正看到它們時才顯示記錄。 這有時稱為虛擬模式或數據分頁。 我得到了wpf 的這種策略的一個例子,但也有一些適用於 winforms 的東西。 也看看這個問題: 與 MS Access Grid 相比,Winform DataGridview 非常慢,我認為這也與您的問題有關。

一個愚蠢的老家伙的規則: - 避免使用 DataTable,眾所周知效率低下 - 避免使用行的預分配 ["Grid".Rowcount + "Grid".AddRange() +..](比“Grid”慢約 5 倍“ADD()) - 考慮到 DataGridView 綁定到“你的屏幕”:即。 用幾屏數據加載它。 - 我應用了這些簡單的事實,我可以在 15 秒內“加載”一個 420 000 行、159 列的“愚蠢文件”。 (~200 MB)。

我有一個相當不錯的DataGridView性能。 添加數百行大約需要 200 毫秒。 這是我所做的:

virtual = true -- 使用虛擬化數據網格視圖似乎可以使整個過程更快。 請記住正確實現logViewGrid_CellValueNeeded

另一件要做的事情是在將數據添加到綁定列表時暫時禁用布局事件。 試着做:

logViewGrid.SuspendLayout();
// add data, perform some operations on grid view
logViewGrid.ResumeLayout(false);

我也遇到了緩慢行着色的問題; 我這樣做的方法是分別設置每個單元格的樣式,如下所示:

gridViewInstance.Rows[currentRow].Cells[cellIndex].Style.BackColor = val;

相反,我去了:

gridViewInstance.Rows[currentRow].DefaultCellStyle.BackColor = val;

對於 30 列,這讓我在這部分代碼中顯着提高了速度。

我在一個程序中做了一些測試,我加載了 6 列的 5000 行,每個單元格都加載了行號,只是為了獲得一些數據。 然后我使用秒表來測試每種方法。 我加載了dataviewgrid,禁用它並加載它然后啟用它,隱藏它,加載它並顯示它,以及suspendlayout和resumelayout。 我發現通過隱藏它並加載它然后在我的測試中顯示它要快得多。 只需要 0.91 秒就可以加載 0.91 秒來暫停布局、加載、恢復布局 0.25 秒來禁用、加載和重新啟用網格 0.19 秒來隱藏、加載和顯示網格。

我同意您應該避免加載不需要的內容,但認為此測試會有所幫助。

我有同樣的問題,在我的情況下,我還必須設置DataGridView.RowHeadersWidthSizeMode = DisableResizing

這就是我發現的工作。 我正在構建一個帶有自定義單元格着色的 52x15 網格,它需要 10-20 秒的時間來生成和顯示上述所有建議並沒有太大提高性能。

現在,此更改使其與上面的雙緩沖一起顯示在大約 1 秒內。

dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None;

然后在完成生成數據之后

dataGridView1.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.AllCells;
dataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells;

對我來說,問題出在 ColumnHeadersHeightSizeMode 屬性上,所以我建議使用這個代碼片段,其中包含了其他受訪者的一些建議。 如果您的網格沒有以某種方式自動調整大小,這具有不會盲目地恢復到自動調整大小的優點:

private static void FastLoadDataGrid<T>(DataGridView dgv, IEnumerable<T> objList)
{
    // Cache old values
    DataGridViewAutoSizeColumnsMode oldAutoSizeCols = dgv.AutoSizeColumnsMode;
    DataGridViewAutoSizeRowsMode oldAutoSizeRows = dgv.AutoSizeRowsMode;
    DataGridViewRowHeadersWidthSizeMode oldRowHeader = dgv.RowHeadersWidthSizeMode;
    DataGridViewColumnHeadersHeightSizeMode oldCol = dgv.ColumnHeadersHeightSizeMode;

    dgv.SuspendLayout(); // off for performance 

    // switch off stuff for performance
    dgv.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.None; 
    dgv.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None; 
    dgv.RowHeadersWidthSizeMode = DataGridViewRowHeadersWidthSizeMode.DisableResizing;
    dgv.ColumnHeadersHeightSizeMode = DataGridViewColumnHeadersHeightSizeMode.DisableResizing;

    // flush and load data source 
    dgv.DataSource = null;
    dgv.DataSource = new List<T>(objList); //wrap in sortable bindinglist to allow user to sort via column header click

    // revert back to old values
    dgv.AutoSizeColumnsMode = oldAutoSizeCols;  
    dgv.AutoSizeRowsMode = oldAutoSizeRows; 
    dgv.RowHeadersWidthSizeMode = oldRowHeader;
    dgv.ColumnHeadersHeightSizeMode = oldCol;

    dgv.ResumeLayout(false); // turn back on
}

對該過程的典型調用是:

FastLoadDataGrid(MyDataGridView, MyListOfCustomers);

通過使用我的 FastLoadDataGrid,導入 10000 行 3 列並且每次成功顯示在數據網格視圖中的測試從 8 秒縮短到 3 秒。

Microsoft 的其他建議是: DataGridView 優化

一種完全不同的方法也可以這樣做或代替使用虛擬化。 打開 VirtualMode = true。 但這可能需要重構數據綁定事件。 請參閱: DataGridView 虛擬化

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM