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

DataGridのクリア後にRowを追加する処理が遅いです。

分類:[.NET]

はじめまして。いつも大変参考にさせていただいております。
今、データ表示専用のためにDataGridを使用しています。

データグリッドのデータクリア後の処理に時間がかかるため、ずっと悩んでいます。

まずはフォームロード時にデータグリッドに初期データを表示しています。
そして、ボタン2クリックでいったんデータを削除します。
ボタン3クリックでデータを再表示する時に1行目のデータ追加のところで4〜5秒ほど時間がかかります。

時間がかかるのは、最初にクリアした後の一回目のみです。
一回クリアしてしまえば、後は何回データ表示とクリアを行ってもこのような問題が発生せずに、スムーズに処理を行うことが出来ます。

このような問題について解決方法をご存知の方がいらっしゃれば、何卒ご教授お願いいたします。

開発環境はWindows2000 VB.NET 2003 .NET Framework1.1です。


Private DataSet1 As DataSet
Private DataTable1 As DataTable

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Call InitGrid()  'データグリッド初期化呼び出し
End Sub


  'データグリッドの初期化処理
Private Sub InitGrid()

' DataGridコントロールを読み取り専用にする
DataGrid1.ReadOnly = True

Dim dataClumn1 As DataColumn
Dim dataClumn2 As DataColumn
Dim dataClumn3 As DataColumn
Dim dgTableStyle As DataGridTableStyle

DataSet1 = New DataSet("商品マスター")

DataTable1 = DataSet1.Tables.Add("商品テーブル")

dataClumn1 = DataTable1.Columns.Add("ID", Type.GetType("System.Int32"))
dataClumn2 = DataTable1.Columns.Add("商品", Type.GetType("System.String"))
dataClumn3 = DataTable1.Columns.Add("個数", Type.GetType("System.String"))


'テーブルのスタイルを作成
dgTableStyle = New DataGridTableStyle
dgTableStyle.MappingName = dataTable1.TableName
DataGrid1.TableStyles.Add(dgTableStyle)


' テーブルの列のスタイルを作成
Dim dgColumnStyle1 As DataGridTextBoxColumn
Dim dgColumnStyle2 As DataGridTextBoxColumn
Dim dgColumnStyle3 As DataGridTextBoxColumn

dgColumnStyle1 = New DataGridTextBoxColumn
dgColumnStyle2 = New DataGridTextBoxColumn
dgColumnStyle3 = New DataGridTextBoxColumn

dgColumnStyle1.MappingName = dataClumn1.ColumnName
dgColumnStyle2.MappingName = dataClumn2.ColumnName
dgColumnStyle3.MappingName = dataClumn3.ColumnName

'ヘッダーにタイトルを設定
dgColumnStyle1.HeaderText = dataClumn1.ColumnName
dgColumnStyle2.HeaderText = dataClumn2.ColumnName
dgColumnStyle3.HeaderText = dataClumn3.ColumnName

' 列のスタイルをテーブル・スタイルに登録
dgTableStyle.GridColumnStyles.Add(dgColumnStyle1)
dgTableStyle.GridColumnStyles.Add(dgColumnStyle2)
dgTableStyle.GridColumnStyles.Add(dgColumnStyle3)

'テーブルに初期データを追加
DataTable1.Rows.Add(New Object() {1, "みかん", 10000})
DataTable1.Rows.Add(New Object() {2, "りんご", 30000})
DataTable1.Rows.Add(New Object() {3, "バナナ", 12000})
DataTable1.Rows.Add(New Object() {4, "すいか", 28000})
DataTable1.Rows.Add(New Object() {5, "いちご", 20000})
DataTable1.Rows.Add(New Object() {6, "メロン", 15000})

DataGrid1.SetDataBinding(DataSet1, DataTable1.TableName)

End Sub


  'データグリッドのクリア処理
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

DataTable1.Clear()

End Sub


'データの再表示
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

'テーブルに初期データを追加
DataTable1.Rows.Add(New Object() {1, "みかん", 10000})'←この1行の処理に時間がかかる!!
DataTable1.Rows.Add(New Object() {2, "りんご", 30000})
DataTable1.Rows.Add(New Object() {3, "バナナ", 12000})
DataTable1.Rows.Add(New Object() {4, "すいか", 28000})
DataTable1.Rows.Add(New Object() {5, "いちご", 20000})
DataTable1.Rows.Add(New Object() {6, "メロン", 15000})

End Sub
■No8875に返信(okaさんの記事)

こんにちは 平ちゃんです。

回答ではないです。
表示のみでしたら、データセットは必要ないのでは?
何かメリットがありましたでしょうか?
■No8902に返信(平ちゃんさんの記事)

平ちゃんさん ご指摘ありがとうございます。
実は、開発期間が非常に短く、DataGridのことをほとんど勉強する時間がなく、サンプルの改造でやっています。
それで、どのソースを見てもだいたいDataSetを使っていたのですが、表示の時には必要ないのですか?
基本的すぎる質問で大変申し訳ありません。

実際には、載せてあるソースとは違いますが、やりたいことはああいう感じです。
検索条件を入力し、データベースからその条件に合うレコードを取得してグリッドに表示するというものです。

大変申し訳なく思いますが、もう少しヒントをいただけないでしょうか。
図々しいですが、よろしくお願いいたします。
■No8903に返信(okaさんの記事)

DataGridで表示のみでしたら、データセットなしでテーブルのみで良いと思います。
検索方法について確認したいのですが、

> 実際には、載せてあるソースとは違いますが、やりたいことはああいう感じです。
> 検索条件を入力し、データベースからその条件に合うレコードを取得してグリッドに表示するというものです。

データベースからの検索はデータセット、テーブルに無関係に抽出し結果を単に次のように追加して表示だけならデータセットは不要です。
この辺りはどのようになっていますか?

'テーブルに初期データを追加
DataTable1.Rows.Add(New Object() {1, "みかん", 10000})'←この1行の処理に時間がかかる!!
DataTable1.Rows.Add(New Object() {2, "りんご", 30000})
DataTable1.Rows.Add(New Object() {3, "バナナ", 12000})
■No8904に返信(平ちゃんさんの記事)

平ちゃんさん 早速のご回答本当にありがとうございます。
頂きましたご質問の件ですが、平ちゃんさんのおっしゃられている通り

'sValue()にはセットする値をデータベースから取得してセットしている
DataTable1.Rows.Add(New Object() {sValue(0),sValue(1),sValue(2)})

のような感じでデータを表示しているだけです。
この場合はDataSetの作成をしなくてもよいということでしょうか?
となると、この3行(元の書き込みから抜粋)の扱いがわからなくなってしまいました。

DataSet1 = New DataSet("商品マスター")
DataTable1 = DataSet1.Tables.Add("商品テーブル")

DataGrid1.SetDataBinding(DataSet1, DataTable1.TableName)

これらがいらなくなるのかなと思い削除したところ、当然のようにオブジェクトがNothingのためエラーとなります。

重ね重ね申し訳ありませんが、後少しだけお付き合い願えないでしょうか?
よろしくお願いいたします。
■No8905に返信(okaさんの記事)

念のため断っておきますが、今回の場合データセットがいらない内容と思い、不要なものは使わないと言う考えです。
ですから、参考にしたサンプルが悪いと言う事では決してありません。

お急ぎみたいなので以下に修正したコードを載せます。
比較して訂正して、動作確認してみてください。




'Private DataSet1 As DataSet
Private DataTable1 As DataTable

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Call InitGrid() 'データグリッド初期化呼び出し

End Sub


'データグリッドの初期化処理
Private Sub InitGrid()

' DataGridコントロールを読み取り専用にする
DataGrid1.ReadOnly = True

Dim dataClumn1 As DataColumn
Dim dataClumn2 As DataColumn
Dim dataClumn3 As DataColumn
Dim dgTableStyle As DataGridTableStyle

' DataSet1 = New DataSet("商品マスター")

'DataTable1 = DataSet1.Tables.Add("商品テーブル")
DataTable1 = New DataTable()

dataClumn1 = DataTable1.Columns.Add("ID", Type.GetType("System.Int32"))
dataClumn2 = DataTable1.Columns.Add("商品", Type.GetType("System.String"))
dataClumn3 = DataTable1.Columns.Add("個数", Type.GetType("System.String"))


'テーブルのスタイルを作成
dgTableStyle = New DataGridTableStyle()
dgTableStyle.MappingName = dataTable1.TableName
DataGrid1.TableStyles.Add(dgTableStyle)


' テーブルの列のスタイルを作成
Dim dgColumnStyle1 As DataGridTextBoxColumn
Dim dgColumnStyle2 As DataGridTextBoxColumn
Dim dgColumnStyle3 As DataGridTextBoxColumn

dgColumnStyle1 = New DataGridTextBoxColumn()
dgColumnStyle2 = New DataGridTextBoxColumn()
dgColumnStyle3 = New DataGridTextBoxColumn()

dgColumnStyle1.MappingName = dataClumn1.ColumnName
dgColumnStyle2.MappingName = dataClumn2.ColumnName
dgColumnStyle3.MappingName = dataClumn3.ColumnName

'ヘッダーにタイトルを設定
dgColumnStyle1.HeaderText = dataClumn1.ColumnName
dgColumnStyle2.HeaderText = dataClumn2.ColumnName
dgColumnStyle3.HeaderText = dataClumn3.ColumnName

' 列のスタイルをテーブル・スタイルに登録
dgTableStyle.GridColumnStyles.Add(dgColumnStyle1)
dgTableStyle.GridColumnStyles.Add(dgColumnStyle2)
dgTableStyle.GridColumnStyles.Add(dgColumnStyle3)

'テーブルに初期データを追加
DataTable1.Rows.Add(New Object() {1, "みかん", 10000})
DataTable1.Rows.Add(New Object() {2, "りんご", 30000})
DataTable1.Rows.Add(New Object() {3, "バナナ", 12000})
DataTable1.Rows.Add(New Object() {4, "すいか", 28000})
DataTable1.Rows.Add(New Object() {5, "いちご", 20000})
DataTable1.Rows.Add(New Object() {6, "メロン", 15000})

DataGrid1.SetDataBinding(DataTable1, DataTable1.TableName)

End Sub


'データグリッドのクリア処理
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

DataTable1.Clear()

End Sub


'データの再表示
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

'テーブルに初期データを追加
DataTable1.Rows.Add(New Object() {1, "みかん", 10000}) '←この1行の処理に時間がかかる!!
DataTable1.Rows.Add(New Object() {2, "りんご", 30000})
DataTable1.Rows.Add(New Object() {3, "バナナ", 12000})
DataTable1.Rows.Add(New Object() {4, "すいか", 28000})
DataTable1.Rows.Add(New Object() {5, "いちご", 20000})
DataTable1.Rows.Add(New Object() {6, "メロン", 15000})

End Sub
■No8907に返信(平ちゃんさんの記事)

平ちゃんさん お忙しいところ本当にありがとうございます。

> 念のため断っておきますが、今回の場合データセットがいらない内容と思い、不要なものは使わないと言う考えです。
> ですから、参考にしたサンプルが悪いと言う事では決してありません。

はい。そのあたりは理解できている(はず?)と思います。
ご指摘ありがとうございます。

早速教えていただいたとおり、プログラムを修正して動作確認してみました。

結果はもちろん動いたのですが、残念なことに偶数行に設定している色が奇数行と同じ色になっていたり、カラムごとに設定しているカラム幅の設定が適用されなくなったりしています。

私が載せていたソースは今書いているプログラムを載せると、非常に大きくなるためわかりずらいかと思い、簡素化したものであったため、実際のプログラムでやっていることの情報が伝わらなかったことと、私が単にデータ表示するだけと言い切っていたせいですね。
大変申し訳ありませんでした。

改めての質問となりますが、上記で発生するような原因・対応としては元のままDataSetを使用することとなるのでしょうか?

また、教えていただいたサンプルではDataTableのTableNameには何も入れていないのですが、それは特に必要ないということになりますか?
ちなみに自分でいれようとしましたが、入れ子に出来ないというエラーになってしまいました。

時間がないという理由だけで、答えを聞くような質問ばかりで本当にすみません。
よろしくお願いいたします。
■No8910に返信(okaさんの記事)
> 結果はもちろん動いたのですが、残念なことに偶数行に設定している色が奇数行と同じ色になっていたり、カラムごとに設定しているカラム幅の設定が適用されなくなったりしています。

okaさんの場合なぜそうなるか解りませんが

DataGrid1.TableStyles.Add(dgTableStyle) のように追加していますので
これに対して設定を適用する必要があります。
TableStyleを1つだけ追加しているならば
DataGrid1.TableStyles.Item(0) になりますので

DataGrid1.TableStyles.Item(0).AlternatingBackColor = Color.Aqua
DataGrid1.TableStyles.Item(0).BackColor = Color.Chocolate
DataGrid1.TableStyles.Item(0).GridColumnStyles.Item(0).Width = 100

のように設定します。


> また、教えていただいたサンプルではDataTableのTableNameには何も入れていないのですが、それは特に必要ないということになりますか?

これに関しては私も良く解らないのですが
DataTable1 = New DataTable() として
DataTable1.TableName で確認すると "DataTable1" という名前がついてます。
また別名をつけると 例えば
DataTable1 = New DataTable("商品テーブル")とした場合は次のようにします。
DataGrid1.SetDataBinding(DataTable1, "")

私の場合特に必要が無いので名前を指定していません。
■No8911に返信(平ちゃんさんの記事)

平ちゃんさん 毎回毎回早いレスに大変感謝しております。

教えていただいたことと調べたことを織り交ぜながらやっていったのですが、どうしても列幅や色の設定が適用されません。
元のDataSetを使っている時は大丈夫なのですが・・・。
恐らく根本的に何かがおかしいんでしょうね。

そこで恥をしのんで今(DataSetを使用しているまま)のソースを載せてみることにしました。(←勝手に)
こんなことを頼んでもよいのかどうか迷いましたが、問題点があるようでしたらご指摘いただけないでしょうか?

申し訳ありませんがよろしくお願いいたします。


'データグリッドの列番号を列挙体にて管理する
Private Enum ENUM_COLUMN_INDEX_LIST
INDEX_MIN = 0 'インデックス番号最小値
SHOW_MIN = 0 '表示インデックス最小値
WAREHOUSE_CODE = 0 '倉庫コード
WAREHOUSE_NAME = 1 '倉庫名称
SHOW_MAX = 1 '表示インデックス最大値
UPD_DATE = 2 '更新日付
INDEX_MAX = 2 'インデックス番号最大値
End Enum

Private m_dgWarehouseListDataSet As DataSet '倉庫一覧DataGridのDataSetオブジェクト
Private m_dgWarehouseListTable As DataTable '倉庫一覧DataGridのDataTableオブジェクト

Private Sub InitDataGrid()

Dim i As Integer
Dim sColumnName(ENUM_COLUMN_INDEX_LIST.INDEX_MAX) As String
Dim iColumnWidth(ENUM_COLUMN_INDEX_LIST.INDEX_MAX) As Integer
Dim dgColumn(ENUM_COLUMN_INDEX_LIST.INDEX_MAX) As DataColumn
Dim dgTableStyle As DataGridTableStyle
Dim dgColumnStyle(ENUM_COLUMN_INDEX_LIST.INDEX_MAX) As DataGridTextAlignColumn 'DataGridTextBoxColumnの継承クラス(再描画によるテキストのAlign設定)


'セル内のタブ移動を防ぐために、Tabボタンが押下された時に移動するコントロールを指定
Me.dgWarehouseList.NextControl = Me.txtWarehouseCode

'セル内のタブ移動を防ぐために、Shift + Tabボタンが押下された時に移動するコントロールを指定
Me.dgWarehouseList.PrevControl = Me.txtCheckID

'データセット作成
Me.m_dgWarehouseListDataSet = New DataSet("Warehouse")

'データテーブル作成
Me.m_dgWarehouseListTable = m_dgWarehouseListDataSet.Tables.Add("List")
'Me.m_dgWarehouseListTable = New DataTable


'テーブルスタイルを作成してデータグリッドに追加
dgTableStyle = New DataGridTableStyle
dgTableStyle.MappingName = "List"
dgTableStyle.AllowSorting = False 'ヘッダークリックによる並べ替えを禁止する
dgTableStyle.AlternatingBackColor = Color.FromArgb(235, 235, 235) '偶数行の色設定
dgWarehouseList.TableStyles.Add(dgTableStyle)

'カラム名セット
sColumnName(ENUM_COLUMN_INDEX_LIST.WAREHOUSE_CODE) = "コード"
sColumnName(ENUM_COLUMN_INDEX_LIST.WAREHOUSE_NAME) = "倉庫名称"
sColumnName(ENUM_COLUMN_INDEX_LIST.UPD_DATE) = "最終更新日付"

'カラム幅セット
iColumnWidth(ENUM_COLUMN_INDEX_LIST.WAREHOUSE_CODE) = 52
iColumnWidth(ENUM_COLUMN_INDEX_LIST.WAREHOUSE_NAME) = 170
iColumnWidth(ENUM_COLUMN_INDEX_LIST.UPD_DATE) = 0


'カラム作成(表示最大インデックス番号より大きい値のカラムを非表示にする)
For i = 0 To ENUM_COLUMN_INDEX_LIST.INDEX_MAX
dgColumn(i) = New DataColumn(sColumnName(i), GetType(String))

If i > ENUM_COLUMN_INDEX_LIST.SHOW_MAX Then
dgColumn(i).ColumnMapping = MappingType.Hidden
End If

Me.m_dgWarehouseListTable.Columns.Add(dgColumn(i))
Next


'列スタイルを作成してテーブルスタイルに追加
For i = 0 To ENUM_COLUMN_INDEX_LIST.INDEX_MAX
dgColumnStyle(i) = New DataGridTextAlignColumn
dgColumnStyle(i).MappingName = sColumnName(i)

'隠しカラム以外のカラム名をセット
If i <= ENUM_COLUMN_INDEX_LIST.SHOW_MAX Then
dgColumnStyle(i).HeaderText = sColumnName(i)
End If

dgColumnStyle(i).Width = iColumnWidth(i)
dgColumnStyle(i).TextAlignment = HorizontalAlignment.Left
dgColumnStyle(i).Alignment = HorizontalAlignment.Center
dgTableStyle.GridColumnStyles.Add(dgColumnStyle(i))
Next

'データグリッドにテーブルを表示する
dgWarehouseList.SetDataBinding(m_dgWarehouseListDataSet, "List")
'dgWarehouseList.SetDataBinding(m_dgWarehouseListTable, m_dgWarehouseListTable.TableName)

End Sub
■No8912に返信(okaさんの記事)

次のようにしてみて下さい。

データセットはとる

データテーブルに名前をつけたいので
Me.m_dgWarehouseListTable = New DataTable("List") とする

テーブルスタイルの MappingName を合わす
dgTableStyle.MappingName = "List"

'データグリッドにテーブルを接続する
dgWarehouseList.SetDataBinding(m_dgWarehouseListTable, "")


わたしは今から外出しますのでまた夕方みます。
宜しくお願いします。
■No8913に返信(平ちゃんさんの記事)
> ■No8912に返信(okaさんの記事)

平ちゃんさん 本当にありがとうございます。
お叱りのお言葉をもらっても仕方がないかなって思ってたんですが、ご丁寧に見ていただいたみたいで、本当に助かってます。

さて、平ちゃんさんに教えていただいたことにならって、プログラムに修正を加えてみた所、DataSetなしでも色や幅の適用ができるようになりました。
ありがとうございます。

それで、本題のクリア処理の問題ですが、先程わかったことなんですが、開発環境から起動した場合はやはり遅いのですが、いったんビルドしたexeファイルから起動すると、なぜか速く(2回目以降と同様の速度)クリア処理ができています。

原因がわからないのですごく気持ちが悪いのと、今までの少ない経験ではこういうときは必ずどこかに問題が残っていたりするパターンが多いので、時間の許す限り見ていきたいと思います。

もし、上記現象から何か気づかれたことがありましたら、またご教授いただければ大変ありがたいです。←ほんと図々しいですね。

よろしくお願いいたします。
■No8915に返信(okaさんの記事)
>
DataSetなしでも動くようになって「めでたし、めでたし」ですが
本題は改善されてないと言うことですね。

しかし 「いったんビルドしたexeファイルから起動すると問題ない」とのことですのでOKでしょう。

普通 アプリケーションを作るとリリースビルドして配布しますのでビルドしない場合の動作は気にしなくて良いでしょう。
■No8917に返信(平ちゃんさんの記事)

平ちゃんさん レスありがとうございます。

> DataSetなしでも動くようになって「めでたし、めでたし」ですが
> 本題は改善されてないと言うことですね。

はい。すべて平ちゃんさんに教えていただいたおかげです。
たぶんちょっと勉強すればいいことなんでしょうけど、今回は思いっきり甘えてしまいました。


> しかし 「いったんビルドしたexeファイルから起動すると問題ない」とのことですのでOKでしょう。
>
> 普通 アプリケーションを作るとリリースビルドして配布しますのでビルドしない場合の動作は気にしなくて良いでしょう。

そう言っていただけると少し心強いです。
なんというか、原因がわからないけど解決したときは神経質になってしまう癖があるみたいで、いつも調べてる時間が長くなりがちなんです。

でも、今回は本当に助かりました。そして、勉強になりました。
今後、また馬鹿な質問をするかもしれませんが、よろしくお願いいたします。
ありがとうございました。
解決済み!
2005/02/09(Wed) 22:54:25 編集(投稿者)

■No8920に返信(okaさんの記事)

今日は 平ちゃんです。

>原因がわからないのですごく気持ちが悪いのと、今までの少ない経験ではこういうときは必ずどこかに問題が残っていたりするパターンが>多いので、時間の許す限り見ていきたいと思います。


忘れていた事を思い出させて恐縮ですが、非常に初心者的な確認をさせて頂きます。

プログラム全体の事になりますが名前空間とクラス名がダブっている事は無いですか。

例えば Test というプロジェクトでプログラムを組む場合 Test と言う名前のクラスは使えないという事です。

これはプロジェクト名がデフォルトの名前空間である事からの制限です。

厄介な事にダブっていても問題なく動作する場合が多いので、デフォルトの名前空間を気にしない人は要注意です。

以上 ご参考まで。
解決済み!
■No9037に返信(平ちゃんさんの記事)

平ちゃんさん、わざわざ教えていただき、ありがとうございます。
一瞬ひやっととして慌てて見ましたが、大丈夫でした。

ありがとうございました。

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