none
DataGridViewの選択セルが画面上に表示されない RRS feed

  • 質問

  • みなさん。こんにちは。いつも参考にしています。
    DataGridViewの、表示行について質問があります。
    画面上に、テキストボックスと、DataGridViewを配置し、テキストボックスに値を入れ、
    DataGridViewのデータを検索するメソッドで、値に合致するデータが有れば、
    CurrentCellをそのデータのセルに設定します。
    その時、DataGridView の AutoSizeRowsMode を DisplayedCells にすると、選択したセルが、
    画面上に表示されません。(正しくスクロールされない)
    検索値に合致するセルを一度画面に表示した後、同様の操作を行うと、正しく画面上に表示されます。
    おそらく、DisplayedCells にすると、行の高さの計算が正しく行われていないのではないか
    と思っています。
    FirstDisplayedScrollingRowIndex で設定してみたのですが、やはり画面上に表示されません。
    AutoSizeRowsMode を AllCells にすると、正しく表示されるのですが、AllCellsは、表示スピードが
    遅いので、使用したくありません。
    DisplayedCells にして、選択したセルを画面上に表示する方法は無いでしょうか。
    宜しくお願いします。
    2011年5月13日 3:07

回答

  • 思いっきり対処療法ですが、例えばですが・・・

      Private Sub DataGridView1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles DataGridView1.Scroll
    
        Dim row As Integer
        Integer.TryParse(TextBox1.Text, row)
    
        If e.NewValue = row - 1 Then Return
    
        For i = e.NewValue + 1 To row - 1
          DataGridView1.AutoResizeRow(i, DataGridViewAutoSizeRowMode.AllCells)
        Next
    
        DataGridView1.FirstDisplayedScrollingRowIndex = row - 1
    
      End Sub
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク しんなべ 2011年5月23日 6:19
    2011年5月18日 6:09
    モデレータ

すべての返信

  • こちらで簡単に試したところ、再現されませんでした。
    仮想モードを使用しているなど、DataGridViewに何か設定をされていますか?

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年5月13日 3:44
    モデレータ
  • trapemiyaさん。

    いつもご回答有難うございます。

     

    自分でも別アプリを作成したところ、再現しないので、原因を調べているところです。

    仮想モードは使用していません。また、特に変わった設定もしていません。

    しかし、現象が出るアプリでは、必ず再現するので、何らかの設定により起こる現象だと思います。

    何かお気づきでしたらご教授お願いします。

     

    宜しくお願いします。

     

     

    2011年5月13日 6:41
  • みなさん。こんにちは。
    現象について、原因が判ったので、再度質問させて下さい。
    DataGridViewに表示しているテーブルのクエリ実行時、
    表示スピードを上げるため、クエリ実行前に、AutoSizeRowsMode を None に設定し、
    クエリ完了後に DisplayedCells に設定しているのが原因でした。
    <例>
    DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
    TableAdapterXXX.Fill(XXXDataSet.XXXTable)
    その他リンクテーブルのデータを取得してセルに設定
    DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells
    とすると、選択セルが画面に表示されない現象が再現します。これを、
    TableAdapterXXX.Fill(XXXDataSet.XXXTable)
    その他リンクテーブルのデータを取得してセルに設定
    だけにすると、再現しません。
    クエリの前に
    DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
    を実行すると、クエリの開始から表示完了までの時間が、11秒が2秒に短縮されるので、
    その設定はそのままで、選択セルが画面に表示されない現象を解決したいのですが、
    何か良いお考えが有りましたら、ご教授お願いします。
    下記はテストソースです。画面にDataGridView 1個, Buttonを2個, TextBox 1個
    を貼り付け、TextBoxに「500」等と数値をいれ実行すると再現します。
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim col1 As New DataGridViewTextBoxColumn
            col1.Name = "col1"
            col1.HeaderText = "項目1"
            DataGridView1.Columns.Add(col1)
            Dim col2 As New DataGridViewTextBoxColumn
            col2.Name = "col2"
            col2.HeaderText = "項目2"
            col2.DefaultCellStyle.WrapMode = DataGridViewTriState.True
            DataGridView1.Columns.Add(col2)
            DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.None
            Dim line() As String = {"aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee"}
            For i As Integer = 0 To 999
                DataGridView1.Rows.Add()
                DataGridView1.Rows(i).Cells(0).Value = i + 1
                For j As Integer = 0 To i Mod 5
                    If DataGridView1.Rows(i).Cells(1).Value <> "" Then
                        DataGridView1.Rows(i).Cells(1).Value += vbLf
                    End If
                    DataGridView1.Rows(i).Cells(1).Value += line(j)
                Next
            Next
            DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells
        End Sub
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            Dim row As Integer
            If Integer.TryParse(TextBox1.Text, row) AndAlso row > 0 Then
                DataGridView1.CurrentCell = DataGridView1(0, row - 1)
            End If
        End Sub
    宜しくお願いします。
    2011年5月16日 12:01
  • こんにちは。

    DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCells

    の部分を、

    DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.AllCells

    とすれば大丈夫そうですが、ダメですかね。
    また、パフォーマンス的には許容範囲でしょうか?

    もともとDataGridViewAutoSizeRowsMode.DisplayedCells指定は
    パフォーマンスを優先させるために表示されている行のみの高さを再計算させるようなので、
    スクロールバーがうまく計算できていないようですね。

    MSDNの
    ■DataGridView.CurrentCell プロパティ (System.Windows.Forms)
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.currentcell(v=VS.100).aspx

    に、「セルが現在のセルとして設定されていて、現在表示されていない場合は、スクロールして表示します。 」
    とあるのに表示されないのは、バグと言えばバグのような気もしますが・・・。

    以上、よろしくお願いします。

    2011年5月16日 13:17
  • Tetsuaki Uchidaさん。

    ご返事有難うございます。

    仰る通り、AllCellsにすれば大丈夫なのですが、パフォーマンス的に許容範囲ではないので、

    DisplayedCellsで正しく表示出来ないかと思案中です。

    何か解決方法をご存じであれば、ご教授お願いします。

     

    宜しくお願いします。


    2011年5月18日 4:35
  • 思いっきり対処療法ですが、例えばですが・・・

      Private Sub DataGridView1_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs) Handles DataGridView1.Scroll
    
        Dim row As Integer
        Integer.TryParse(TextBox1.Text, row)
    
        If e.NewValue = row - 1 Then Return
    
        For i = e.NewValue + 1 To row - 1
          DataGridView1.AutoResizeRow(i, DataGridViewAutoSizeRowMode.AllCells)
        Next
    
        DataGridView1.FirstDisplayedScrollingRowIndex = row - 1
    
      End Sub
    

    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク しんなべ 2011年5月23日 6:19
    2011年5月18日 6:09
    モデレータ
  • trapemiyaさん。
    いつもご回答有難うございます。
    ご教授の方法を参考を元に無事解決しました。
    ご教授のメソッドを試したところ、
    e.NewValue
    だけ設定すれば希望の動作となったので、下記のイベントを実装し、検索ヒット時に割り当てて対処しました。
    'DataGridView.Scroll イベントハンドラ
    Private Sub DataGridView_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs)
        e.NewValue = m_DataGridViewNewRow
    End Sub
    '検索メソッド
    'row、colは検索にヒットした行列番号
    'm_DataGridViewNewRowは広域変数
    m_DataGridViewNewRow = row
    AddHandler DataGridView.Scroll, AddressOf DataGridView_Scroll
    DataGridView.CurrentCell = DataGridView(col, row)
    RemoveHandler DataGridView.Scroll, AddressOf DataGridView_Scroll
    いつも助かります。有難うございました。
    2011年5月23日 6:19