トップ回答者
DatagridView のソートのタイミングを変える方法を教えてください。(VB.NET 2005)

質問
-
下記データーサンプル(マイクロソフト NorthWindow DB)から TEST.MDB(Access 2003) に「売り上げ」とういうテーブルを作成しました
販売コード 支店 販売日 商品 個数 売上
1 池袋 2009/10/05 13:54:30 オレンジジュース 5 \1,250
2 上野 2009/10/05 0:20:11 コーヒー 10 \1,800
3 上野 2009/10/05 1:05:18 グレープジュース 10 \2,500
4 上野 2009/10/05 8:57:54 紅茶 10 \1,800
5 新宿 2009/10/05 22:47:22 オレンジジュース 7 \1,750
6 上野 2009/10/05 1:17:03 グレープジュース 6 \1,500
7 渋谷 2009/10/05 14:56:41 コーヒー 4 \720
8 渋谷 2009/10/05 19:54:55 紅茶 7 \1,260
9 品川 2009/10/05 21:51:47 オレンジジュース 8 \2,000
10 品川 2009/10/05 5:51:16 グレープジュース 3 \750
11 上野 2009/10/06 0:22:37 グレープジュース 3 \750
12 新宿 2009/10/06 19:10:24 オレンジジュース 2 \500
==================================================
VB.NET 2005 にて 新しいプロジェクトを作成
Windows フォーム Form1 上に メニューからデータ/新しいデータ接続 を実行し
先に作成した MDB に接続してください。
データーソースのウインドウより テーブル「売り上げ」をForm1 上に
ドラッグ&ドロップすると 自動的にデータグリッドの配置がされます。
この状態からForm1 を実行してデータを編集します。
初期状態は 販売コード で昇順でソートされています。
「支店」のヘッダーをクリックして 「支店」で昇順になるようにします。
販売コード 8番 のデータ 支店:渋谷 → 池袋 にします。 セルを移動しても ソートされません
編集直後では 支店 でのソートは起こりません。 行を変更、つまり
他の行をクリックしたときに ソートが起こります。
この他の行をクリックしたときに ソートが起こるのではなく ヘッダーの支店をクリックした場合のみソート
をさせるということは 可能でしょうか?
=======================================<実装したコード>============================
Public Class Form1Private Sub 売上テーブルBindingNavigatorSaveItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles 売上テーブルBindingNavigatorSaveItem.Click
Me.Validate()
Me.売上テーブルBindingSource.EndEdit()
Me.売上テーブルTableAdapter.Update(Me.TESTDataSet.売上テーブル)End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
'TODO: このコード行はデータを 'TESTDataSet.売上テーブル' テーブルに読み込みます。必要に応じて移動、または削除をしてください。
Me.売上テーブルTableAdapter.Fill(Me.TESTDataSet.売上テーブル)End Sub
End Class
==============================================================================
以上、よろしくお願いします。- 編集済み MYNOBU 2010年1月3日 18:15
回答
-
可能か不可能かでいえば、かなり面倒な手段を使えば実現は可能です。
以下の内容でわからないのでしたら、特殊な並べ替えはあきらめたほうがいいですよ。
DataGridViewは並べ替えが指定されると、データソースを並べ替えしてあるリストを作って、それにアクセスしているようです。
あるいははじめから並び替えされているデータソース(DataViewやBindingSource)にアクセスします。
並べ替えられたデータにアクセスするため、常に並べ替えた状態でしか表示できません。
ですから通常の方法では希望されている動作は出来ません。
案1
DataTableに非表示のDataColumnを追加しておき、このソート用DataColumでソートを指定する。
表示されているDataGridViewColumnのSortModeはNotSortableかProgrammaticにしておきます。
DataGridViewのColumnHeaderMouseClickイベントのタイミングでのみこのDataColumnの値を新しい値に書き換えます。
デメリットとして、DataTableに行 列が増えてしまうのと、RowStateが変化してしまう問題がある。
案2
DataGridViewとDataTabeの間にBindingSourceを入れ、さらにIBindingListViewを入れて、
「DataGridView.DataSource <-> カスタムIBindingListView <-> BindingSource <-> DataTable」
という関係にします。
表示されているDataGridViewColumnのSortModeはNotSortableかProgrammaticにしておきます。
カスタムIBindingListViewはBindingSourceの並べ替え直後の並び順を保持するListを内部に持たせておき、DataGridViewから行データを要求されたら、この内部ListのIndexを使って取り出すようにします。
DataGridViewのColumnHeaderMouseClickイベントのタイミングでBindingSourceのSortを変更し、さらにカスタムIBindingListViewの内部ListをBindingSourceの新しい並びで更新します。
デメリットとして、実装する量が多くなるのと行追加削除の処理を同期させるのが面倒。
案3
DataGridViewをVirtualModeにして自分で並べ替え処理を管理する。
デメリットは表示行管理が面倒。
#案2をためしに実装してテストして並べ替えが遅延できることは確認済みですが、提示できる完成度になっていないのでソースは貼りません。 -
gekkaさんも書かれていますが、残念ながら簡単には実現できません。参考になりそうなページをご紹介しておきます。
DataGridView: how to stop / cancel sorting
http://social.msdn.microsoft.com/Forums/en/winformsdatacontrols/thread/ce630093-ed6c-4b54-9a98-67a2e8dc112bDataGridView - suppressing auto-sort / re-sort
http://social.msdn.microsoft.com/Forums/en/winforms/thread/91d65e58-60b3-4367-a580-07cdf7574eb3
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク 菊地俊介 2010年1月18日 9:45
すべての返信
-
可能か不可能かでいえば、かなり面倒な手段を使えば実現は可能です。
以下の内容でわからないのでしたら、特殊な並べ替えはあきらめたほうがいいですよ。
DataGridViewは並べ替えが指定されると、データソースを並べ替えしてあるリストを作って、それにアクセスしているようです。
あるいははじめから並び替えされているデータソース(DataViewやBindingSource)にアクセスします。
並べ替えられたデータにアクセスするため、常に並べ替えた状態でしか表示できません。
ですから通常の方法では希望されている動作は出来ません。
案1
DataTableに非表示のDataColumnを追加しておき、このソート用DataColumでソートを指定する。
表示されているDataGridViewColumnのSortModeはNotSortableかProgrammaticにしておきます。
DataGridViewのColumnHeaderMouseClickイベントのタイミングでのみこのDataColumnの値を新しい値に書き換えます。
デメリットとして、DataTableに行 列が増えてしまうのと、RowStateが変化してしまう問題がある。
案2
DataGridViewとDataTabeの間にBindingSourceを入れ、さらにIBindingListViewを入れて、
「DataGridView.DataSource <-> カスタムIBindingListView <-> BindingSource <-> DataTable」
という関係にします。
表示されているDataGridViewColumnのSortModeはNotSortableかProgrammaticにしておきます。
カスタムIBindingListViewはBindingSourceの並べ替え直後の並び順を保持するListを内部に持たせておき、DataGridViewから行データを要求されたら、この内部ListのIndexを使って取り出すようにします。
DataGridViewのColumnHeaderMouseClickイベントのタイミングでBindingSourceのSortを変更し、さらにカスタムIBindingListViewの内部ListをBindingSourceの新しい並びで更新します。
デメリットとして、実装する量が多くなるのと行追加削除の処理を同期させるのが面倒。
案3
DataGridViewをVirtualModeにして自分で並べ替え処理を管理する。
デメリットは表示行管理が面倒。
#案2をためしに実装してテストして並べ替えが遅延できることは確認済みですが、提示できる完成度になっていないのでソースは貼りません。 -
gekkaさんも書かれていますが、残念ながら簡単には実現できません。参考になりそうなページをご紹介しておきます。
DataGridView: how to stop / cancel sorting
http://social.msdn.microsoft.com/Forums/en/winformsdatacontrols/thread/ce630093-ed6c-4b54-9a98-67a2e8dc112bDataGridView - suppressing auto-sort / re-sort
http://social.msdn.microsoft.com/Forums/en/winforms/thread/91d65e58-60b3-4367-a580-07cdf7574eb3
★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://blogs.wankuma.com/trapemiya/- 回答としてマーク 菊地俊介 2010年1月18日 9:45