トップ回答者
DataGridViewの選択セルが画面上に表示されない

質問
-
みなさん。こんにちは。いつも参考にしています。DataGridViewの、表示行について質問があります。画面上に、テキストボックスと、DataGridViewを配置し、テキストボックスに値を入れ、DataGridViewのデータを検索するメソッドで、値に合致するデータが有れば、CurrentCellをそのデータのセルに設定します。その時、DataGridView の AutoSizeRowsMode を DisplayedCells にすると、選択したセルが、画面上に表示されません。(正しくスクロールされない)検索値に合致するセルを一度画面に表示した後、同様の操作を行うと、正しく画面上に表示されます。おそらく、DisplayedCells にすると、行の高さの計算が正しく行われていないのではないかと思っています。FirstDisplayedScrollingRowIndex で設定してみたのですが、やはり画面上に表示されません。AutoSizeRowsMode を AllCells にすると、正しく表示されるのですが、AllCellsは、表示スピードが遅いので、使用したくありません。DisplayedCells にして、選択したセルを画面上に表示する方法は無いでしょうか。宜しくお願いします。
回答
-
思いっきり対処療法ですが、例えばですが・・・
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
すべての返信
-
みなさん。こんにちは。現象について、原因が判ったので、再度質問させて下さい。DataGridViewに表示しているテーブルのクエリ実行時、表示スピードを上げるため、クエリ実行前に、AutoSizeRowsMode を None に設定し、クエリ完了後に DisplayedCells に設定しているのが原因でした。<例>DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.NoneTableAdapterXXX.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.ClickDim col1 As New DataGridViewTextBoxColumncol1.Name = "col1"col1.HeaderText = "項目1"DataGridView1.Columns.Add(col1)Dim col2 As New DataGridViewTextBoxColumncol2.Name = "col2"col2.HeaderText = "項目2"col2.DefaultCellStyle.WrapMode = DataGridViewTriState.TrueDataGridView1.Columns.Add(col2)DataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.NoneDim line() As String = {"aaaaa", "bbbbb", "ccccc", "ddddd", "eeeee"}For i As Integer = 0 To 999DataGridView1.Rows.Add()DataGridView1.Rows(i).Cells(0).Value = i + 1For j As Integer = 0 To i Mod 5If DataGridView1.Rows(i).Cells(1).Value <> "" ThenDataGridView1.Rows(i).Cells(1).Value += vbLfEnd IfDataGridView1.Rows(i).Cells(1).Value += line(j)NextNextDataGridView1.AutoSizeRowsMode = DataGridViewAutoSizeRowsMode.DisplayedCellsEnd SubPrivate Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.ClickDim row As IntegerIf Integer.TryParse(TextBox1.Text, row) AndAlso row > 0 ThenDataGridView1.CurrentCell = DataGridView1(0, row - 1)End IfEnd Sub宜しくお願いします。
-
こんにちは。
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
に、「セルが現在のセルとして設定されていて、現在表示されていない場合は、スクロールして表示します。 」
とあるのに表示されないのは、バグと言えばバグのような気もしますが・・・。
以上、よろしくお願いします。 -
思いっきり対処療法ですが、例えばですが・・・
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
-
trapemiyaさん。いつもご回答有難うございます。ご教授の方法を参考を元に無事解決しました。ご教授のメソッドを試したところ、e.NewValueだけ設定すれば希望の動作となったので、下記のイベントを実装し、検索ヒット時に割り当てて対処しました。'DataGridView.Scroll イベントハンドラPrivate Sub DataGridView_Scroll(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ScrollEventArgs)e.NewValue = m_DataGridViewNewRowEnd Sub'検索メソッド'row、colは検索にヒットした行列番号'm_DataGridViewNewRowは広域変数m_DataGridViewNewRow = rowAddHandler DataGridView.Scroll, AddressOf DataGridView_ScrollDataGridView.CurrentCell = DataGridView(col, row)RemoveHandler DataGridView.Scroll, AddressOf DataGridView_Scrollいつも助かります。有難うございました。