3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

(.Net)DataGirdViewとTabControl の組み合わせで、DataGridViewのスクロールバーが無効化される現象

これは.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

これがバグならさっさと直してほしいですね。

参考:

@IT BBS :DataGridのスクロール表示について

@IT BBS :C# Tabコントロール上のDataGridViewが崩れる