none
DataGridViewのComboBoxのデータ表示の高速化 RRS feed

  • 質問

  • おはようございます。

    VB2005+SQLServerExpressにて作業をしております。

    注文伝票のようなフォームを作成しており、商品名を選択するComboBoxがDataGridView内にあります。
    商品のデータが約2万件あり、データを表示する際に時間がかかってしまいます。

    絞り込みを行いたいと思い、DataSourceとなっているTableAdapterに商品名のふりがなの一部をWHERE条件としてクエリを作成しました。

    動作の流れとしては、

    ComboBoxにフォーカスが移動する。

    入力モードとなる

    商品名のカナの一部を入力する

    入力した仮名をもとに絞り込まれたデータがComboBoxに表示される

    という動作を実現したいと思います。

    そこで、カナを入力後、新しく作成したクエリを使い、該当するデータのDataTableをComboBoxのDataSourceに指定をすれば
    よいと思い、CellEndEditというものがあったので、これが使えるかと思ったのですが、こちらはDataDridViewからフォーカスが
    外れなければだめだったので使えませんでした。

    そこで、DataGridViewColumnにValidatingイベントがないか探してみたのですが、見つかりませんでした。

    まず、そもそも必要なComboBoxに入力されたカナの一部をどのように取得できるのでしょうか。
    そして、現在編集中の行のComboBoxのみ選択するデータを絞り込むにはどのようにDataSourceをセットすればよいでしょうか。
    (はじめ、ComboBoxのDataSourceをセットせずに、あとからDataSourceをセットすればよいと思って、試したところ、
    すでに入力済みのデータがあるため、当然ですが表示の時点でエラーとなってしまいました。)

    どうか、よろしくお願いします。

    2010年4月4日 20:03

回答

  • そこで、DataGridViewColumnにValidatingイベントがないか探してみたのですが、見つかりませんでした。

    DataGridViewのEditingControlShowingイベントで表示されるコンボボックス、つまりDataGridViewComboBoxEditingControlを取得し、そのValidatingイベントが使用できます。

    (参考)
    DataGridView with dynamically filled ComboBox
    http://www.windowsdevelop.com/windows-forms-data-controls-databinding/datagridview-with-dynamically-filled-combobox-47412.shtml

    そして、現在編集中の行のComboBoxのみ選択するデータを絞り込むにはどのようにDataSourceをセットすればよいでしょうか。

    コンボボックスにバインドしているDataView、もしくはBindingSourceを利用されているのであればそれに対してフィルターを設定するのが素直だと思います。商品件数によってはSQLをその都度発行した方が良いかもしれません。

    (参考)
    DataGridView: Filter Combobox Column Items
    http://www.vb-tips.com/DGVFilterCombo.aspx


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク 菊地俊介 2010年4月23日 4:23
    2010年4月5日 1:32
    モデレータ
  • カナの取得については、こちらのページが参考になると思います。

    http://dobon.net/vb/bbs/log3-32/19814.html

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク 菊地俊介 2010年4月23日 4:23
    2010年4月5日 0:13

すべての返信

  • カナの取得については、こちらのページが参考になると思います。

    http://dobon.net/vb/bbs/log3-32/19814.html

     


    なかむら(http://d.hatena.ne.jp/griefworker)
    • 回答としてマーク 菊地俊介 2010年4月23日 4:23
    2010年4月5日 0:13
  • そこで、DataGridViewColumnにValidatingイベントがないか探してみたのですが、見つかりませんでした。

    DataGridViewのEditingControlShowingイベントで表示されるコンボボックス、つまりDataGridViewComboBoxEditingControlを取得し、そのValidatingイベントが使用できます。

    (参考)
    DataGridView with dynamically filled ComboBox
    http://www.windowsdevelop.com/windows-forms-data-controls-databinding/datagridview-with-dynamically-filled-combobox-47412.shtml

    そして、現在編集中の行のComboBoxのみ選択するデータを絞り込むにはどのようにDataSourceをセットすればよいでしょうか。

    コンボボックスにバインドしているDataView、もしくはBindingSourceを利用されているのであればそれに対してフィルターを設定するのが素直だと思います。商品件数によってはSQLをその都度発行した方が良いかもしれません。

    (参考)
    DataGridView: Filter Combobox Column Items
    http://www.vb-tips.com/DGVFilterCombo.aspx


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/
    • 回答としてマーク 菊地俊介 2010年4月23日 4:23
    2010年4月5日 1:32
    モデレータ
  • お返事が遅くなりました。

    CellBeginEditやCellEndEditを利用することで、DataGridViewなどの列の値を利用して、特定の列のDataSourceの変更などができることは
    わかりました。

    本当に相変わらず、説明が下手で申し訳ないのですが、改めて現状を説明します。

    現状
    DataGridViewにはComboBoxがひとつ
    DataSourceとなるテーブルにはデータが約2万ある
    注文伝票のようなものを想定している

    行いたい動作
    ComboBoxがフォーカスを取得する
    DataSourceが空になる
    ComboBoxに文字を入力し、Enterキーを押し、(変換を確定した時点)入力した文字を含むデータの候補を
    ComboBoxに表示する。

    何も考えずに、2万のデータをすべてComboBoxにセットしてしまえば、上記の動作を実現することは可能なのですが、
    データ量が多いため、編集状態に入るまでに少し時間がかかるので、それが回避できれば良いな、と考えています。

    現在、
    DataSourceを空にする(DataSource=Nothingでできました。)
    ComboBoxの編集終了後にDataSourceを元に戻す(CellEndEditにて、DataSourceを再セットすることで実現)

    今はComboBoxのValidatedイベントにて実現ができないかを検討中です。

    Private Sub dgv_CellBeginEdit(ByVal sender As Object, _
                ByVal e As System.Windows.Forms.DataGridViewCellCancelEventArgs) _
                Handles dgv.CellBeginEdit
            If e.ColumnIndex = 2 Then
                Dim dgvCbo As DataGridViewComboBoxCell = TryCast(dgv(e.ColumnIndex, e.RowIndex),             DataGridViewComboBoxCell)

                If dgvCbo IsNot Nothing Then
                    Dim str As String = dgv.Item(0, dgv.CurrentRow.Index).Value.ToString

                    If str Is Nothing Then
                        dgvCbo.DataSource = Nothing
                    End If
                End If
            End If
        End Sub

    また、上記のような記述で、ComboBoxCellの編集が開始した時点のComboBoxの文字列を取得し、何もデータがない場合は
    DataSourceを空にするということをしようと思ったのですが、上記の記述ですと、「str」に編集中の行の1行前の行のデータが
    入ってしまいます。

    ColumnIndex RowIndexともに編集中のComboBoxを示しているのですが、いまいち理由がわかりません。

    CurrentRowは新しい行を追加して編集を開始しても、確定している最終の行をさすのでしょうか。

    2010年4月12日 3:02
  • おはようございます。

    時間が取れるようになってきたので、再度こちらを考えてみたいと思いテストをしてみました。

    ご提示いただいたページを参考にプログラムを書いてみましたが、ComboboxのValidatingイベントはフォーカスが外れる前に
    動作をするように見えました。

    なので、2つのComboboxがあり、1つ目のデータをもとに2つめのComboboxのDataSourceを編集する場合はこの内容で
    対応できそうですが、Comboboxがひとつしかない場合は、自分ではどのようにすればよいかわかりませんでした。

    今、考えていることは以下のとおりです。(ComboboxはDataGridViewの中のことです。)

    Comboboxに文字を入力

    Enterキーで文字を確定

    確定した文字列を元にComboboxのDataSourceをセットし、DropDownする

    といったことを実現できればと考えています。

    そこで、Enterキーで文字入力を確定した時点のComboboxのTextが取得できれば、と考えておりその方法を調べているところです。

    どうしても、方法がわからない場合は、再度こちらにて質問をさせていただきます。
    よろしくお願いします。

    2010年5月23日 19:05
  • 自己レスです。

    KeyPressイベントを用意して、DataGridViewのeditingcontrolShowingにて、DataGridViewのKeyPressイベントにセットしました。

    そして、KeyPressイベントにて、

    e.KeyChar.ToStringで入力確定した文字列を取得できるかと思ったのですが、数文字の文字列の場合、1文字ずつしか取得されません。

    また、Enterキーをクリックすると、KeyPressイベントが2回呼び出されてしまいます。
    (デバッグで1行ずつ実行すると2回通過します。)

    Combboxに入力し、Enterキーで確定をした文字列を取得するにはどのようにすればよいでしょうか。

    また、KeyPressイベントが2回起こるのはなぜでしょうか。
    (はじめは、e.KeyChar.ToStringをMessageboxで表示しており、OKボタンをEnterキーでクリックした状態にしていたので、それが原因かと
    思ったので、OKボタンをマウスでクリックするようにしてみたのですが、結果は同じでした。)

    よく、理解できていないので、わかりにくい文章になっていることは承知しておりますが、どうかアドバイスよろしくお願いします。

    2010年5月25日 4:58