DOBON.NET DOBON.NETプログラミング掲示板過去ログ

DataGridView の Column数を増やした時の処理時間増大

環境/言語:[Windows XP、VB2008pro]
分類:[.NET]

最下記のコードをこちらの環境で実行したところ

Column数 起動直後実行秒数(Button1 による 2回目以降秒数)
300 7秒(4)
400 13秒(6)
500 21秒(10)
600 30秒(15)
700 41秒(20)
800 54秒(27)
900 68秒(34)

といった結果となりました。
処理時間を速く(5秒以内に)する方法は無いでしょうか?
データ数が多いので多少の処理時間は許容するつもりですが、
あまりに時間が掛かる為、改善できる方法は無いかと思い
質問いたしました。

データベースのテーブルであれば、フィールド数が数百というのは
設計に問題ないか考えるべきですが、Grid 系の無料で付属している
コントロールが DataGridView であり、Graphics クラスを使った
表現が容易なので、表として利用しようとしています。
しかし、この程度のデータ数でこれほどの時間が掛かっては
使い物になりません。
DataGridView 内部の幅調整などの機能は制限が掛かっても構いません。
とにかくデータを表示するだけの目的で速くしたいです。
何か情報をお持ちの方が居られましたらご協力頂ければと思います。

    ' 「FillWeight 値 を合計した最大値が65535を超えている」といった例外が発生に対応
    Private Sub dgv_ColumnAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewColumnEventArgs) Handles DataGridView1.ColumnAdded
        If e.Column.FillWeight <> 10 Then
            e.Column.FillWeight = 10
        End If
    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim dt As New DataTable
        Dim count As Integer

        Int32.TryParse(Me.TextBox1.Text, count)
        With dt.Columns
            For index As Integer = 0 To count
                .Add("サンプル" & index.ToString, System.Type.GetType("System.Int32"))
            Next
        End With
        ''row は増やしても0.5秒以内(Columnsは1の時)で表示される
        'For index As Integer = 0 To 900
        '    dt.Rows.Add(dt.NewRow())
        'Next

        Dim sTime0 As DateTime = Now
        Me.DataGridView1.DataSource = dt’←ボトルネック

        '処理時間を計測
        Dim eTime0 As DateTime = Now
        Me.Label1.Text = eTime0.Subtract(sTime0).TotalSeconds & " 秒かかりました。"

    End Sub
http://raluck.exblog.jp/14873007/ を参考に、ダブルバッファにしてみました。
900列が0.9秒で描画されます。

Public Class Form1
Friend Class DoubleBufferedDataGridView
Inherits DataGridView
Public Sub New()
Me.DoubleBuffered = True
End Sub
End Class
Friend WithEvents dbdgv As DoubleBufferedDataGridView
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim dt As New DataTable
Dim count As Integer

Int32.TryParse(Me.TextBox1.Text, count)
With dt.Columns
For index As Integer = 0 To count
.Add("サンプル" & index.ToString, System.Type.GetType("System.Int32"))
Next
End With

Dim sTime0 As DateTime = Now
dbdgv.DataSource = dt

'処理時間を計測
Dim eTime0 As DateTime = Now
Me.Label1.Text = eTime0.Subtract(sTime0).TotalSeconds & " 秒かかりました。"
End Sub

Private Sub dbdgv_ColumnAdded(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewColumnEventArgs)
If e.Column.FillWeight <> 10 Then
e.Column.FillWeight = 10
End If
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
dbdgv = New DoubleBufferedDataGridView
dbdgv.Location = New Point(13, 37)
dbdgv.Size = New Size(637, 491)
dbdgv.Anchor = AnchorStyles.Left Or AnchorStyles.Right Or AnchorStyles.Bottom
AddHandler dbdgv.ColumnAdded, AddressOf dbdgv_ColumnAdded
Me.Controls.Add(dbdgv)
End Sub
End Class
■No31340に返信(doyabohさんの記事)
> http://raluck.exblog.jp/14873007/ を参考に、ダブルバッファにしてみました。
> 900列が0.9秒で描画されます。

ありがとうございます。
こちらの環境でも1秒前後で処理できるようになりました。
ダブルバッファリングを使うだけでここまで改善するものなのですね。
ListView で作り直そうとか思っていたところだったので助かりました。
継承コントロールへの置き換えだけで修正できそうです。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板