「ほっ」と。キャンペーン
(.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()
 
''' <summary>
''' フォームロード
''' </summary>
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
 
''' <summary>
''' スクロールバー無効バグ調査 Button2 の押下イベントハンドラ
''' <summary>
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 を表示。フォームロード時にグリッドは無効かつ何にもバインドしていないので、データは表示されません。
e0091163_1122986.jpg


そして、いったん TabPage1 を表示し、Button2 を押下し、グリッドのバインド、有効化します。
e0091163_1125826.jpg


で、 TabPage2 を押下すると、スクロールバーが無効に。。ただカーソルキー使うとセルを移動できます。
e0091163_1131971.jpg



で、この解決法ですが、DataGridView をデータソースにバインドするとき(グリッドに表示用データがセットされるとき)に、Enabled を True にすることくらいしかないようですね。

ということで、Button2_Click メソッドを下記のように書き換えました。これだと問題なくうまく動きます。

''' <summary>
''' スクロールバー無効バグ調査 Button2 の押下イベントハンドラ
''' <summary>
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 にするメソッドを上げておきます。

''' <summary>
''' 指定されたコントロールの親がEnableをFalseにしていたら解除する
''' </summary>
''' <param name="ctl">検査するコントロール</param>
''' <returns>EnabledがFalseの最も親のコントロール。Falseのコントロールがない場合はNothigを返す</returns>
''' <remarks></remarks>
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が崩れる
[PR]
by jehoshaphat | 2009-02-18 01:14 | .Net開発 | Trackback | Comments(1)
トラックバックURL : http://jehupc.exblog.jp/tb/9636479
トラックバックする(会員専用) [ヘルプ]
※このブログはトラックバック承認制を適用しています。 ブログの持ち主が承認するまでトラックバックは表示されません。
Commented by もも at 2013-05-10 12:14 x
Visual Studio 2012を使っていますが、同じ現象で困っていました。この記事でとても助かりました。ありがとうございます。


<< YouTube:飛行機乗り遅れ... (VC++).Net Fram... >>