none
DataGridViewで値検索 RRS feed

  • 質問

  • お世話になっております。

     

    Accessから抽出したデータを、構造体を経由してDataGridViewにて表示させています。

    要件の一つに、DBにアクセスせずフリ仮名検索をするというものがあるので

    DataGridViewのRowsを全件検索かけ、該当しないものをVisible=Falseとしています。

     

    そこで行き詰ったのですが、2回目からの検索は1秒もかからないのですが

    最初の検索だけ20秒程かかってしまいます。

     

    何か、検索に問題があるのでしょうか??

    どうか、ご教示ください。

    2010年11月25日 1:58

回答

  • 各 DataGridViewRow 等のプロパティを設定すると、「共有行」状態で無くなる際に若干負荷がありますので、行数が多い場合は(1回目に)遅くなる可能性はあります。

    Windows フォーム DataGridView コントロールを拡張するための推奨される手順
    共有行の使用
    http://msdn.microsoft.com/ja-jp/library/ha5xt0d9.aspx

    DataGridView はバインドを利用されていますでしょうか?
    もし DataGridView を DataTable 等にバインドされている場合は、DataView の RowFilter プロパティに条件を設定するだけで済むかもしれず、それによって問題がなくなるかもしれません。

    差支えなければ現状のコードの抜粋を書かれた方がいいかもしれませんね。
    もしかすると別の問題が見つかったりするかもしれないので。

    追記:
    参考までにグリッドの行数も教えてください。

    • 編集済み TH01 2010年11月25日 2:59 追記
    • 回答としてマーク segment 2010年11月25日 9:54
    2010年11月25日 2:22

すべての返信

  • 各 DataGridViewRow 等のプロパティを設定すると、「共有行」状態で無くなる際に若干負荷がありますので、行数が多い場合は(1回目に)遅くなる可能性はあります。

    Windows フォーム DataGridView コントロールを拡張するための推奨される手順
    共有行の使用
    http://msdn.microsoft.com/ja-jp/library/ha5xt0d9.aspx

    DataGridView はバインドを利用されていますでしょうか?
    もし DataGridView を DataTable 等にバインドされている場合は、DataView の RowFilter プロパティに条件を設定するだけで済むかもしれず、それによって問題がなくなるかもしれません。

    差支えなければ現状のコードの抜粋を書かれた方がいいかもしれませんね。
    もしかすると別の問題が見つかったりするかもしれないので。

    追記:
    参考までにグリッドの行数も教えてください。

    • 編集済み TH01 2010年11月25日 2:59 追記
    • 回答としてマーク segment 2010年11月25日 9:54
    2010年11月25日 2:22
  • さっそくの、ご回答ありがとうございます!

    教えて頂いた、共有行の件、調べてみます。

     

    また、取り急ぎソースを載せておきます。

     

     ' データ取り込み
    
     ' フィールド名・患者マスターデータ
     Dim fieldName As Array
     Dim clientDt As ArrayList
    
     ' フィールドの追加
     For Each fName As String In fieldName
      Me.DataGridView1.Columns.Add(fName, fName)
     Next
     ' 値の追加
     For Each dt As Object In clientDt
      With dt
       Me.DataGridView1.Rows.Add(.karteCode, .clientName, .hurigana, .sexCode, .eraName, _
             .birthYear, .birthMonth, .birthDay, .address1, .address2, _
             .TELNumber, .ZIPCode, .job)
      End With
     Next
    
    '******************************************************
    
     ' 仮名ボタンクリック
     Private Sub bt_KANA_Click(ByVal sender As Object, ByVal e As EventArgs)
      For i As Integer = 0 To Me.DataGridView1.Rows.Count - 1
       ' 該当フリ仮名検索
       If (Mid(Me.DataGridView1.Rows(i).Cells(modDefine.COL_HURIGANA).Value, 1, 1) <> StrConv(sender.Text, VbStrConv.Narrow)) Then
        ' 該当しないRowをHide
        Me.DataGridView1.Rows(i).Visible = False
       Else
        Me.DataGridView1.Rows(i).Visible = True
       End If
      Next
     End Sub
    

     

    追記:

    行数(件数)は、全部で400件弱です。

     

    2010年11月25日 2:59
  • 以下の続きと思われます。

    http://social.msdn.microsoft.com/Forums/ja-JP/vsgeneralja/threads

    ので、データは構造体のArrayList、ということだと思います。

    GridViewに、ArrayListをループして表示しているのかなと想像してます。


    今回のように条件によって行の表示・非表示を行ないたいのであればTH01さんの

    仰る通り、Filterを使うと簡単に実装できます。

    ワイルドカードを使って、以下のように書くだけで行をフィルタできます。

    「dataView.RowFilter = "フリ仮名のカラム LIKE '*検索する文字列*'"」

    そうするとGridViewはデータバインドであることが望ましく、前回のスレッドで

    元々のインターフェイスはDataTableをバインドしていた事などがあり、

    もう一度ここら辺から検討してもいいのでは、と思いました。

    2010年11月25日 3:07
  • honefaiさん、引き続きありがとうございます!

     

    やはり、データバインドが望ましいのですね。

    知識足らずで、先輩を納得させられるか解りませんが、確認してみます。

     

    しかし、データバインドせず、値をループ検索した際に、最初だけ時間が

    かかるというのは、納得しておきたいので、もう少し調査してみます。

    2010年11月25日 3:43
  • そういえば前のスレッド見たとき、私は DataTable のままの方が好きなのに、とか思ってました。
    ただし、どちらが良いかは場合によると思います。

    試してみましたところ、1回目が遅いというよりは、Visible の変化行数が多いかどうかがレスポンスに影響しているように思われました。

    私の環境では、2000 行でも数秒でしたので、400 行で 20 秒というと相当遅いですね。
    ただし、私の検証では StrConv は使いませんでした。
    これがそんなに遅いとは思えませんが、ループの外で1度だけ実行するようにされてはいかがでしょうか?

    バインドされていないので、共有行の話は関係ないようです。

    2010年11月25日 4:04
  • >Visible の変化行数が多いかどうかがレスポンスに影響しているように思われました。

     

    同意です。しかしながら、今回400行で20秒ですのでこれはちょっと掛かりすぎていると思いますが、

    その原因がいま出てきている情報だけでは想像出来ないようなきがします。

    これを実行した際のメモリの使用状況・CPUの使用状況は、問題なく空きがある状態でしたか?

     

    あと要件としては、恐らく全角カナの「ア」「イ」「ウ」・・・といったボタンが画面に配置してあり、

    それを押すことで、「hiragana」カラムの先頭一文字と一致する場合に行を表示し、一致しない場合に

    行を非表示にするという感じで受け止めました。

    これであれば、RowFilterを使った行の表示・非表示の実装が簡単に出来ます。

    その為には、今までの話で出てきていた通り、DataSourceにバインドされている必要があります。

    方法としては以下のような感じになるかと思います。

     

    Private Sub Button1_Click(......) Handles Button2.Click
     Dim dv As DataView = Me.DataGridView1.DataSource
     dv.RowFilter = "hurigana LIKE '" + StrConv(sender.Text, VbStrConv.Narrow) + "*'"
    End Sub
    
    

     

    2010年11月25日 7:59
  • 回答、ありがとうございます!

    動作確認してみましたが、大差ないです。

     

    先輩に相談したところ、今回はバインドせずあくまで構造体でやりとりするようです。

    今回のこの時間のロスも、毎回クエリを投げるという事で解決させるようです。

     

    テストまでしていただいて、ありがとうございました。

    今回はこれで閉じさせていただきます。

    2010年11月25日 9:51
  • 先にも書きましたが、今回は毎回クエリを投げるという形で、解決することになりました。

     

    できれば、私もDataTableを使って、サクッとコーディングしたいのですが、

    やはり会社と先輩の意思を優先し、これで解決させます。

     

    コードまで書いていただき、ありがとうございました!

    またの際は、どうぞよろしくおねがいします。

    2010年11月25日 9:53