DataGridView で DB から取得した DataTable をデータソースとしてバインドし、DataGridViewCheckBoxColumn 列を追加しました。
その状態で、何かチェックを付けてソートすると、チェックが全て消えるという現象が発生。
調べてみると、uedakoの日記:DataGridViewとチェックボックスとソートの話で同じ現象で悩んでる人発見。
どうやら、バインド列と非バインド列が混在してる場合、こうなるのがMSの仕様だそうです。
確かに、MSDN:Windows フォーム DataGridView コントロール内の列の並べ替えモードをみると、そう書かれています。
で、ソート時に非バインド列で値を保持するためには、DataGridView.VirtualMode = True にして、仮想モードでやればいいようです。
しかし、これをすると様々な動作を自分で書いて実装しないと行けないらしく非常に面倒です。(仮想モードは大量のデータをグリッドに表示するときにパフォーマンスを落とさないようするときに使う場合が多いみたい)
一応仮想モード時のサンプルがMSDN:方法 : Windows フォーム DataGridView コントロールで仮想モードを実装するにあるんですが、ちらっと見たところやっぱり面倒くさそうです。
それで、DBから取得した後の DataTable に対して Boolean 型の DataColumn を追加して、それを DataGridView にバインドさせる方法をとることにしました。
なお、チェックボックス列は先頭に表示することとします。(DataGridViewColumnの DisplayIndex プロパティで指定)
コードはこんな感じです。
Public Class Form1
'TableAdapter VisualStudioのDataSetデザイナが作ってくれたやつ使用
Private m_adp As New Database1DataSetTableAdapters.table1TableAdapter()
'DBから取得したデータを保存してる DataTalbe
Private m_tbl As DataTable
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
'DBからデータ取得
m_tbl = m_adp.GetData()
'DataTable にチェックボックス用の Boolean 列用意
Dim clmCheck As New DataColumn("check", Type.GetType("System.Boolean"))
m_tbl.Columns.Add(clmCheck)
'グリッドにバインド
Me.DataGridView1.DataSource = m_tbl
'チェックボックス用列を最初に表示
Me.DataGridView1.Columns("check").DisplayIndex = 0
Me.DataGridView1.Columns("check").SortMode = DataGridViewColumnSortMode.Automatic
End Sub
End Class
これでちゃんとソートしても値が保持されるようになりました。