これは.Netの仕様なのかバグなのか分かりませんが、かなり悩まされました。
下記の条件のときにDataGridViewのスクロールバーが無効にされるという意味不明な現象が発生します。
・DataGridView は TabControl の上に配置する。
・DataGridView が配置されているタブをいったん表示し、その後別タブを表示。
・DataGridView が Enabled = False のとき DataGridView をデータソースにバインドする。
・DataGridView が表示されていないタブで DataGridView の Enabled = True にする。
・DataGridView が配置されているタブを表示する → DataGridView のスクロールバーが無効に。
具体的には下記のようなコードで再現できます。(Visual Studio のデザイナで、タブコントロールとその上(TabPage2)に DataGridView を配置しておく)
DataGridView のデータソースとして、MDBから取ってきた DataTable とします。このMDBは(.Net)DataGridViewでの入力チェックはCellValidatingだけではダメで使ってたやつとします。
Public Class Form1'DataTable
Private mTable1Dtbl As New Database1DataSet.table1DataTable()
'TableAdapter
Private mTable1Adp As New Database1DataSetTableAdapters.table1TableAdapter()
'''
''' フォームロード
'''
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'スクロールバー無効バグ調査 DataGridViewのEnabledを無効にする
Me.DataGridView1.Enabled = False
End Sub
'''
''' スクロールバー無効バグ調査 Button2 の押下イベントハンドラ
'''
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'DataTableにDBの情報を取得し、DataGridViewにバインドさせる
'このとき、DataGridView.Enable は False の状態
mTable1Adp.Fill(mTable1Dtbl)
Me.DataGridView1.DataSource = mTable1Dtbl
'バインド後に Enabled を True に。
Me.DataGridView1.Enabled = True
End Sub
End Class
DataGridView は TabPage2 上に配置しておきます。
まず、TabPage2 を表示。フォームロード時にグリッドは無効かつ何にもバインドしていないので、データは表示されません。
そして、いったん TabPage1 を表示し、Button2 を押下し、グリッドのバインド、有効化します。
で、 TabPage2 を押下すると、スクロールバーが無効に。。ただカーソルキー使うとセルを移動できます。
で、この解決法ですが、DataGridView をデータソースにバインドするとき(グリッドに表示用データがセットされるとき)に、Enabled を True にすることくらいしかないようですね。
ということで、Button2_Click メソッドを下記のように書き換えました。これだと問題なくうまく動きます。
'''
''' スクロールバー無効バグ調査 Button2 の押下イベントハンドラ
'''
Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
'バインド前に Enabled を True にすると問題おきない
Me.DataGridView1.Enabled = True
'DataTableにDBの情報を取得し、DataGridViewにバインドさせる
mTable1Adp.Fill(mTable1Dtbl)
Me.DataGridView1.DataSource = mTable1Dtbl
End Sub
当たり前ですが、DataGridView を GourpBox 等のコンテナ上に配置している場合、そのコンテナの Enabled を True にしないといけないので要注意です。
この場合は再帰処理すればいいかもしれません。一応下記に親のコントロールから Enabled を True にするメソッドを上げておきます。
'''
''' 指定されたコントロールの親がEnableをFalseにしていたら解除する
'''
''' 検査するコントロール
'''
EnabledがFalseの最も親のコントロール。Falseのコントロールがない場合はNothigを返す '''
Private Function ParentControlEnableTrue(ByVal ctl As Control) As Control
If ctl.Enabled Then
Return Nothing
End If
If ctl.Parent IsNot Nothing AndAlso Not ctl.Parent.Enabled Then
Return ParentControlEnableTrue(ctl.Parent)
Else
ctl.Enabled = True
Return ctl
End If
End Function
これがバグならさっさと直してほしいですね。
参考: