none
DataGridViewでの3つのカラムによる並べ替え、並び順 RRS feed

  • 質問

  • VB2008とSQL2008で開発を行ってなっているのですが

    戸惑ってしまい、投稿しました。

    マイクロソフトのサイトよりサンプルをコピーし実行しましたが

    思い通りの結果が得られず悩んでおります。

    DataGridViewで3つのカラムでの並べ替えをしたいと考えております

    サンプルでは2つのカラムでの動作で、以下のソースにどう手直ししたら

    いいか、開発の経験も浅いため解りません、ご教授よろしくお願いします。

    -------------------------------------------

    Imports System
    Imports System.Drawing
    Imports System.Windows.Forms

    Public Class Form1
        Inherits Form

        Private WithEvents DataGridView1 As New DataGridView()
        Private FlowLayoutPanel1 As New FlowLayoutPanel()
        Private WithEvents Button1 As New Button()
        Private RadioButton1 As New RadioButton()
        Private RadioButton2 As New RadioButton()

        <STAThreadAttribute()> _
        Public Shared Sub Main()
            Application.Run(New Form1())
        End Sub

        Private Sub PopulateDataGridView()

            DataGridView1.Size = New Size(300, 300)

            DataGridView1.ColumnCount = 3

            DataGridView1.Columns(0).Name = "LARGE"
            DataGridView1.Columns(1).Name = "MEDIUM"
            DataGridView1.Columns(2).Name = "SMALL"
            DataGridView1.Columns("LARGE").HeaderText = "大分類"
            DataGridView1.Columns("MEDIUM").HeaderText = "中分類"
            DataGridView1.Columns("SMALL").HeaderText = "小分類"

            DataGridView1.Columns("LARGE").SortMode = _
                DataGridViewColumnSortMode.Programmatic
            DataGridView1.Columns("MEDIUM").SortMode = _
                DataGridViewColumnSortMode.Programmatic
            DataGridView1.Columns("SMALL").SortMode = _
                DataGridViewColumnSortMode.Programmatic

            DataGridView1.Rows.Add(New String() {"11", "1009", "B"})
            DataGridView1.Rows.Add(New String() {"22", "10", "B"})
            DataGridView1.Rows.Add(New String() {"11", "109", "A"})
            DataGridView1.Rows.Add(New String() {"22", "10", "C"})
            DataGridView1.Rows.Add(New String() {"22", "10", "A"})
            DataGridView1.Rows.Add(New String() {"11", "10", "B"})
        End Sub

        Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles Button1.Click
            If RadioButton1.Checked = True Then
                DataGridView1.Sort(New RowComparer(SortOrder.Ascending))
            ElseIf RadioButton2.Checked = True Then
                DataGridView1.Sort(New RowComparer(SortOrder.Descending))
            End If
        End Sub

        Private Class RowComparer
            Implements System.Collections.IComparer

            Private sortOrderModifier As Integer = 1

            Public Sub New(ByVal sortOrder As SortOrder)
                If sortOrder = sortOrder.Descending Then
                    sortOrderModifier = -1
                ElseIf sortOrder = sortOrder.Ascending Then

                    sortOrderModifier = 1
                End If
            End Sub

            Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
                Implements System.Collections.IComparer.Compare

                Dim DataGridViewRow1 As DataGridViewRow = CType(x, DataGridViewRow)
                Dim DataGridViewRow2 As DataGridViewRow = CType(y, DataGridViewRow)

                Dim CompareResult As Integer = System.String.Compare( _
                    DataGridViewRow1.Cells(0).Value.ToString(), _
                    DataGridViewRow2.Cells(0).Value.ToString())

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(1).Value.ToString(), _
                        DataGridViewRow2.Cells(1).Value.ToString())
                End If
                Return CompareResult * sortOrderModifier
            End Function
        End Class
    End Class

    ---------------------------------------------------------------------

    実行後(昇順)          取得したい結果                    

    11    10     B         11     10      B  

    11    1009 B         11     109    A

    11    109   A         11     1009  B

    22    10     A         22     10      A

    22    10     C         22     10      B

    22    10     B         22     10      C 

    上記の結果が最終的に出力できればと思います

    何でもかまいません、参考になる意見よろしくお願いします。

     


    2011年11月1日 4:10

回答

  • > DataGridView1.Rows.Add(New String() {"11", "1009", "B"})

    DataGridViewに直接データを入れるのではなく、
    (1)DataTableにいれて
    (2)ソートしたDataViewをつくり
    (3)それをDataGridViewとバインド
    という手順でどうでしょうか。

    • 回答としてマーク ジョウジ 2011年11月2日 7:26
    2011年11月1日 4:17
  • mars12様参考になる意見ありがとうございます

    (1)~(3)の方法で正常な結果が得られました。

    DataGridViewColumnSortMode.Programmaticを
    DataGridViewColumnSortMode.Automaticに変え

    列ヘッダーをクリックすると並ぶ機能も付加しました

    並び順はどうにかならないでしょうか

    尚、中分類の先頭には全角文字が入る時もあります

    まず半角の数字順次に文字プラス半角数字順にしたいと

    考えております

    例 10-10-10-10-109-1009-通100-通110-特10-特109

    上記の順番で並ばないでしょうか


    2011年11月1日 5:20
  •         Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
                Implements System.Collections.IComparer.Compare

                Dim DataGridViewRow1 As DataGridViewRow = CType(x, DataGridViewRow)
                Dim DataGridViewRow2 As DataGridViewRow = CType(y, DataGridViewRow)

                Dim CompareResult As Integer = System.String.Compare( _
                    DataGridViewRow1.Cells(0).Value.ToString(), _
                    DataGridViewRow2.Cells(0).Value.ToString())

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(1).Value.ToString(), _
                        DataGridViewRow2.Cells(1).Value.ToString())
                End If
                Return CompareResult * sortOrderModifier
            End Function
        End Class
    End Class

    DataGridViewは提供されたCompareメソッドを利用して、行を2つずつ比較しながら並べ替えて行きます。どちらが大きいかを決めるロジックは以下の部分です。

                Dim CompareResult As Integer = System.String.Compare( _
                    DataGridViewRow1.Cells(0).Value.ToString(), _
                    DataGridViewRow2.Cells(0).Value.ToString())

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(1).Value.ToString(), _
                        DataGridViewRow2.Cells(1).Value.ToString())
                End If
                Return CompareResult * sortOrderModifier

    System.String.Compareメソッドを使用して、2つの行の1列目の大小をまず判断しています。同じであれば、2列目の値を同様に比較し、最終的な2つの列の大小関係を決定しています。
    2列目も同じであれば3列目を比較すれば良いことになります。もうおわかりでしょうか? 以下の3列目の比較を、Return CompareResult * sortOrderModifier の前に追加すれば良いはずです。

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(2).Value.ToString(), _
                        DataGridViewRow2.Cells(2).Value.ToString())
                End If

    #ご提示されたコードからはデータベースを利用されているようには見えないのですが、もし利用されているのであれば、最終的にはmars12さんが書かれている手順が一般的だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:27
    2011年11月1日 5:26
    モデレータ
  • いろいろ調べましたが自分には難しいようで

    SQLの方で中分類を10ケタで同じ桁数になるよう

    ゼロ編集したところ並び、上記例の結果通り並べる事ができました

    しかし、中分類の列ヘッダーをクリックすると並びが前のままで

    並順判定用に追加した列をクリックすると思い通りに並びます

    DataGridViewのColumnHeaderMouseClickイベント

    (中分類ヘッダー)のタイミングで追加した列のクリックイベントは起せないでしょうか。

    尚、中分類ヘッダーの右端に表示される三角マークはそのままで可能でしょうか。

    ご意見よろしくお願いします。


    2011年11月1日 10:57
  • SQLの方で中分類を10ケタで同じ桁数になるよう

    ゼロ編集したところ並び、上記例の結果通り並べる事ができました

    う~ん、中分類を10ケタで揃えたとしても小分類の並びは不定ですから、小分類まで含めた全体として正しく並ぶ保障はありませんが、それでよろしいのでしょうか?

     

    DataGridViewのColumnHeaderMouseClickイベント

    (中分類ヘッダー)のタイミングで追加した列のクリックイベントは起せないでしょうか。

    DataGridViewにソートした結果を表示するには大きく2通りあって、一つがDataGridView自身がソートを行って表示する場合と、もう一つは他でソートされた結果をその順番通りにDataGridViewに表示する方法です。
    前者については以下が参考になります。

    DataGridView.ColumnHeaderMouseClick イベント
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.columnheadermouseclick.aspx#Y0

    上記で、dataGridView1.Sort(newColumn, direction)の部分をジョウジさんが最初の投稿で掲載されたButton1_Clickイベントハンドラ内で実行されているSortメソッドに変更し、私の先の投稿も合わせて修正すれば、3つのカラムでソートできるようになると思います。

    DataGridViewのDataSourceプロパティにデータソースを指定されているのでしたら、DataViewやBindingSourceのSortプロパティを使用できます。
    DataViewのSortプロパティについては以下を、

    DataGridViewの行の並び替えの方法を変更する
    http://dobon.net/vb/dotnet/datagridview/customsort.html

    BindingSourceのSortプロパティについては以下を参考にしてみて下さい。

    How to sort a datagridview by two columns
    http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/7f819d92-5bd9-4b5b-b08c-fb15bb5331c4/

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月1日 15:32
    モデレータ
  • trapemiya様親切丁寧な説明ありがとうございます

    いろいろと参考にさせていただきました。

    開発初心者なもので大変理解するまでに時間がかかり

    もうちょっと解りやすいコードに手直ししましたので確認して

    いただければ幸いです

    Imports System.Data.SqlClient
    Public Class Form1
        Private table As New DataTable

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Using cn As New SqlConnection(My.Settings.SqlConnectionString)
                cn.Open()
                Dim sql As String = "SELECT 大分類,中分類,小分類,中分類並替用 FROM 在庫"
                Dim Adapter As New SqlDataAdapter(sql, cn)
                Adapter.Fill(table)
                DataGridView1.DataSource = table
                'DataGridView1.Columns(3).Visible = False
            End Using
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim dv As DataView = table.DefaultView
            dv.Sort = "大分類,中分類並替用,小分類"
            table = dv.ToTable
        End Sub

    -------------------------------------------

    DataView.Sortを使う方法で検討する事にしました

    フォームロード時にデータベースのレコードを全件表示し

    Button1_Clickイベントハンドラ内で大分類、中分類並替用、小分類の昇順で並べ替えして

    各カラムヘッダーをクリックすると列単位で並ぶというプログラムができました。

    ですが、中分類並替用のVisible=Falseの状態で中分類のヘッダークリlクを

    中分類並替用ヘッダークリックに置き換えて並び変え出来ないでしょうか。

    何度もすいません、よろしくお願いします。

    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 1:34
  • ですが、中分類並替用のVisible=Falseの状態で中分類のヘッダークリlクを

    中分類並替用ヘッダークリックに置き換えて並び変え出来ないでしょうか。

    私が掲載したページの内容を合わせれば実現可能です。おそらく以下のようになるでしょう。 

    Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
    
        If DataGridView1.Columns(e.ColumnIndex).HeaderText = "中分類" Then
            Dim dv As DataView = table.DefaultView
            dv.Sort = "中分類並替用"
        End If
    
    End Sub
    

    ところでデータベースからデータをDataTableに読み込み、そこからどのようにDataGridViewに表示させているのでしょうか? DataTableの行を一行ずつ読みながら一行ずつDataGridViewに追加しているように思えなくもないのですが、もしそうでしたらそのようなことは通常行わず、

    DataGridView1.DataSource = データテーブル

    と、一行書くだけで済みます。このようにしておけば、私が上に掲載したように、

    dv.Sort = "中分類並替用"

    とするだけで自動的にDataGridView1に並び替えられた結果が表示されます。なぜなら、
    DataGridView1.DataSource = データテーブル
    と書いた場合、DataGridView1には実はそのデータテーブルのDefaultViewがバインドしているからです。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 2:14
    モデレータ
  • お世話になります。

    table = dv.ToTableをコメントし

    'DataGridView1.Columns(3).Visible = Falseのコメントを外してみました

    trapemiya様、思っていた動きが実現できるようになりました、ありがとうございます。

    すいません、ここまで出来たのに、もう一つ質問よろしいでしょうか?

    中分類カラムヘッダーをクリックした時、昇順→降順→昇順と他のカラムと同じような

    動作は可能でしょうか、出来れば同時に三角マークも表示されれば嬉しいです、よろしくお願いします。

    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 4:26
  • 再掲になりますが、

     

    を応用すれば可能です。説明するよりコードを見ていただいた方が早いと思いますので、コードを掲載します。以下のようになると思います。

    Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) _
        Handles DataGridView1.ColumnHeaderMouseClick
    
        Dim newColumn As DataGridViewColumn = DataGridView1.Columns(e.ColumnIndex)
        Dim oldColumn As DataGridViewColumn = DataGridView1.SortedColumn
        Dim direction As ListSortDirection
    
        If DataGridView1.Columns(e.ColumnIndex).HeaderText = "中分類" Then
    
            '中分類カラムをクリックしたら中分類並替用列で並べ替えられるので、中分類並替用列であれば中分類カラムで並び替えられたことに読み替えておく。
            If oldColumn IsNot Nothing AndAlso oldColumn.Name = "中分類並替用" Then
                oldColumn = DataGridView1.Columns("中分類")
            End If
    
        End If
    
        ' If oldColumn is null, then the DataGridView is not currently sorted.
        If oldColumn IsNot Nothing Then
    
            ' Sort the same column again, reversing the SortOrder.
            If oldColumn Is newColumn AndAlso DataGridView1.SortOrder = _
                SortOrder.Ascending Then
                direction = ListSortDirection.Descending
            Else
    
                ' Sort a new column and remove the old SortGlyph.
                direction = ListSortDirection.Ascending
                oldColumn.HeaderCell.SortGlyphDirection = SortOrder.None
            End If
        Else
            direction = ListSortDirection.Ascending
        End If
    
        Dim dv As DataView = table.DefaultView
    
        If direction = ListSortDirection.Ascending Then
            If newColumn.HeaderText = "中分類" Then
                dv.Sort = "中分類並替用"
            Else
                dv.Sort = newColumn.Name
            End If
            newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending
        Else
            If newColumn.HeaderText = "中分類" Then
                dv.Sort = "中分類並替用 desc"
            Else
                dv.Sort = newColumn.Name + " desc"
            End If
            newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending
        End If
    
    End Sub
    

    なお、上記に再掲したページにもありますように、DataGridViewの各列のSortModeを以下のようにProgrammaticにして下さい。このコードは最初にDataGridViewに表示した後に一度実行しておけば良いでしょう。なぜ全ての列についてProgrammaticにするかというと、このようにしておいた方が将来的に応用が効きやすく、またロジック的に考えやすいと思ったからです。

    For Each column As DataGridViewColumn In DataGridView1.Columns
        column.SortMode = DataGridViewColumnSortMode.Programmatic
    Next
    

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 5:58
    モデレータ
  • すみません。上記で再掲の箇所が空白になっています。再掲したかったのは以下です。

    DataGridView.ColumnHeaderMouseClick イベント
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.columnheadermouseclick.aspx#Y0

    #コードブロックを含む投稿を編集するとコードブロック部分に余計な空白行が入るため、修正しづらく新しく追記の形で投稿しました。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 6:00
    モデレータ

すべての返信

  • > DataGridView1.Rows.Add(New String() {"11", "1009", "B"})

    DataGridViewに直接データを入れるのではなく、
    (1)DataTableにいれて
    (2)ソートしたDataViewをつくり
    (3)それをDataGridViewとバインド
    という手順でどうでしょうか。

    • 回答としてマーク ジョウジ 2011年11月2日 7:26
    2011年11月1日 4:17
  • mars12様参考になる意見ありがとうございます

    (1)~(3)の方法で正常な結果が得られました。

    DataGridViewColumnSortMode.Programmaticを
    DataGridViewColumnSortMode.Automaticに変え

    列ヘッダーをクリックすると並ぶ機能も付加しました

    並び順はどうにかならないでしょうか

    尚、中分類の先頭には全角文字が入る時もあります

    まず半角の数字順次に文字プラス半角数字順にしたいと

    考えております

    例 10-10-10-10-109-1009-通100-通110-特10-特109

    上記の順番で並ばないでしょうか


    2011年11月1日 5:20
  •         Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer _
                Implements System.Collections.IComparer.Compare

                Dim DataGridViewRow1 As DataGridViewRow = CType(x, DataGridViewRow)
                Dim DataGridViewRow2 As DataGridViewRow = CType(y, DataGridViewRow)

                Dim CompareResult As Integer = System.String.Compare( _
                    DataGridViewRow1.Cells(0).Value.ToString(), _
                    DataGridViewRow2.Cells(0).Value.ToString())

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(1).Value.ToString(), _
                        DataGridViewRow2.Cells(1).Value.ToString())
                End If
                Return CompareResult * sortOrderModifier
            End Function
        End Class
    End Class

    DataGridViewは提供されたCompareメソッドを利用して、行を2つずつ比較しながら並べ替えて行きます。どちらが大きいかを決めるロジックは以下の部分です。

                Dim CompareResult As Integer = System.String.Compare( _
                    DataGridViewRow1.Cells(0).Value.ToString(), _
                    DataGridViewRow2.Cells(0).Value.ToString())

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(1).Value.ToString(), _
                        DataGridViewRow2.Cells(1).Value.ToString())
                End If
                Return CompareResult * sortOrderModifier

    System.String.Compareメソッドを使用して、2つの行の1列目の大小をまず判断しています。同じであれば、2列目の値を同様に比較し、最終的な2つの列の大小関係を決定しています。
    2列目も同じであれば3列目を比較すれば良いことになります。もうおわかりでしょうか? 以下の3列目の比較を、Return CompareResult * sortOrderModifier の前に追加すれば良いはずです。

                If CompareResult = 0 Then
                    CompareResult = System.String.Compare( _
                        DataGridViewRow1.Cells(2).Value.ToString(), _
                        DataGridViewRow2.Cells(2).Value.ToString())
                End If

    #ご提示されたコードからはデータベースを利用されているようには見えないのですが、もし利用されているのであれば、最終的にはmars12さんが書かれている手順が一般的だと思います。


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:27
    2011年11月1日 5:26
    モデレータ
  • いろいろ調べましたが自分には難しいようで

    SQLの方で中分類を10ケタで同じ桁数になるよう

    ゼロ編集したところ並び、上記例の結果通り並べる事ができました

    しかし、中分類の列ヘッダーをクリックすると並びが前のままで

    並順判定用に追加した列をクリックすると思い通りに並びます

    DataGridViewのColumnHeaderMouseClickイベント

    (中分類ヘッダー)のタイミングで追加した列のクリックイベントは起せないでしょうか。

    尚、中分類ヘッダーの右端に表示される三角マークはそのままで可能でしょうか。

    ご意見よろしくお願いします。


    2011年11月1日 10:57
  • SQLの方で中分類を10ケタで同じ桁数になるよう

    ゼロ編集したところ並び、上記例の結果通り並べる事ができました

    う~ん、中分類を10ケタで揃えたとしても小分類の並びは不定ですから、小分類まで含めた全体として正しく並ぶ保障はありませんが、それでよろしいのでしょうか?

     

    DataGridViewのColumnHeaderMouseClickイベント

    (中分類ヘッダー)のタイミングで追加した列のクリックイベントは起せないでしょうか。

    DataGridViewにソートした結果を表示するには大きく2通りあって、一つがDataGridView自身がソートを行って表示する場合と、もう一つは他でソートされた結果をその順番通りにDataGridViewに表示する方法です。
    前者については以下が参考になります。

    DataGridView.ColumnHeaderMouseClick イベント
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.columnheadermouseclick.aspx#Y0

    上記で、dataGridView1.Sort(newColumn, direction)の部分をジョウジさんが最初の投稿で掲載されたButton1_Clickイベントハンドラ内で実行されているSortメソッドに変更し、私の先の投稿も合わせて修正すれば、3つのカラムでソートできるようになると思います。

    DataGridViewのDataSourceプロパティにデータソースを指定されているのでしたら、DataViewやBindingSourceのSortプロパティを使用できます。
    DataViewのSortプロパティについては以下を、

    DataGridViewの行の並び替えの方法を変更する
    http://dobon.net/vb/dotnet/datagridview/customsort.html

    BindingSourceのSortプロパティについては以下を参考にしてみて下さい。

    How to sort a datagridview by two columns
    http://social.msdn.microsoft.com/Forums/en-US/winformsdatacontrols/thread/7f819d92-5bd9-4b5b-b08c-fb15bb5331c4/

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月1日 15:32
    モデレータ
  • trapemiya様親切丁寧な説明ありがとうございます

    いろいろと参考にさせていただきました。

    開発初心者なもので大変理解するまでに時間がかかり

    もうちょっと解りやすいコードに手直ししましたので確認して

    いただければ幸いです

    Imports System.Data.SqlClient
    Public Class Form1
        Private table As New DataTable

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Using cn As New SqlConnection(My.Settings.SqlConnectionString)
                cn.Open()
                Dim sql As String = "SELECT 大分類,中分類,小分類,中分類並替用 FROM 在庫"
                Dim Adapter As New SqlDataAdapter(sql, cn)
                Adapter.Fill(table)
                DataGridView1.DataSource = table
                'DataGridView1.Columns(3).Visible = False
            End Using
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim dv As DataView = table.DefaultView
            dv.Sort = "大分類,中分類並替用,小分類"
            table = dv.ToTable
        End Sub

    -------------------------------------------

    DataView.Sortを使う方法で検討する事にしました

    フォームロード時にデータベースのレコードを全件表示し

    Button1_Clickイベントハンドラ内で大分類、中分類並替用、小分類の昇順で並べ替えして

    各カラムヘッダーをクリックすると列単位で並ぶというプログラムができました。

    ですが、中分類並替用のVisible=Falseの状態で中分類のヘッダークリlクを

    中分類並替用ヘッダークリックに置き換えて並び変え出来ないでしょうか。

    何度もすいません、よろしくお願いします。

    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 1:34
  • ですが、中分類並替用のVisible=Falseの状態で中分類のヘッダークリlクを

    中分類並替用ヘッダークリックに置き換えて並び変え出来ないでしょうか。

    私が掲載したページの内容を合わせれば実現可能です。おそらく以下のようになるでしょう。 

    Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
    
        If DataGridView1.Columns(e.ColumnIndex).HeaderText = "中分類" Then
            Dim dv As DataView = table.DefaultView
            dv.Sort = "中分類並替用"
        End If
    
    End Sub
    

    ところでデータベースからデータをDataTableに読み込み、そこからどのようにDataGridViewに表示させているのでしょうか? DataTableの行を一行ずつ読みながら一行ずつDataGridViewに追加しているように思えなくもないのですが、もしそうでしたらそのようなことは通常行わず、

    DataGridView1.DataSource = データテーブル

    と、一行書くだけで済みます。このようにしておけば、私が上に掲載したように、

    dv.Sort = "中分類並替用"

    とするだけで自動的にDataGridView1に並び替えられた結果が表示されます。なぜなら、
    DataGridView1.DataSource = データテーブル
    と書いた場合、DataGridView1には実はそのデータテーブルのDefaultViewがバインドしているからです。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 2:14
    モデレータ
  • お世話になります。

    table = dv.ToTableをコメントし

    'DataGridView1.Columns(3).Visible = Falseのコメントを外してみました

    trapemiya様、思っていた動きが実現できるようになりました、ありがとうございます。

    すいません、ここまで出来たのに、もう一つ質問よろしいでしょうか?

    中分類カラムヘッダーをクリックした時、昇順→降順→昇順と他のカラムと同じような

    動作は可能でしょうか、出来れば同時に三角マークも表示されれば嬉しいです、よろしくお願いします。

    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 4:26
  • 再掲になりますが、

     

    を応用すれば可能です。説明するよりコードを見ていただいた方が早いと思いますので、コードを掲載します。以下のようになると思います。

    Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) _
        Handles DataGridView1.ColumnHeaderMouseClick
    
        Dim newColumn As DataGridViewColumn = DataGridView1.Columns(e.ColumnIndex)
        Dim oldColumn As DataGridViewColumn = DataGridView1.SortedColumn
        Dim direction As ListSortDirection
    
        If DataGridView1.Columns(e.ColumnIndex).HeaderText = "中分類" Then
    
            '中分類カラムをクリックしたら中分類並替用列で並べ替えられるので、中分類並替用列であれば中分類カラムで並び替えられたことに読み替えておく。
            If oldColumn IsNot Nothing AndAlso oldColumn.Name = "中分類並替用" Then
                oldColumn = DataGridView1.Columns("中分類")
            End If
    
        End If
    
        ' If oldColumn is null, then the DataGridView is not currently sorted.
        If oldColumn IsNot Nothing Then
    
            ' Sort the same column again, reversing the SortOrder.
            If oldColumn Is newColumn AndAlso DataGridView1.SortOrder = _
                SortOrder.Ascending Then
                direction = ListSortDirection.Descending
            Else
    
                ' Sort a new column and remove the old SortGlyph.
                direction = ListSortDirection.Ascending
                oldColumn.HeaderCell.SortGlyphDirection = SortOrder.None
            End If
        Else
            direction = ListSortDirection.Ascending
        End If
    
        Dim dv As DataView = table.DefaultView
    
        If direction = ListSortDirection.Ascending Then
            If newColumn.HeaderText = "中分類" Then
                dv.Sort = "中分類並替用"
            Else
                dv.Sort = newColumn.Name
            End If
            newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending
        Else
            If newColumn.HeaderText = "中分類" Then
                dv.Sort = "中分類並替用 desc"
            Else
                dv.Sort = newColumn.Name + " desc"
            End If
            newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending
        End If
    
    End Sub
    

    なお、上記に再掲したページにもありますように、DataGridViewの各列のSortModeを以下のようにProgrammaticにして下さい。このコードは最初にDataGridViewに表示した後に一度実行しておけば良いでしょう。なぜ全ての列についてProgrammaticにするかというと、このようにしておいた方が将来的に応用が効きやすく、またロジック的に考えやすいと思ったからです。

    For Each column As DataGridViewColumn In DataGridView1.Columns
        column.SortMode = DataGridViewColumnSortMode.Programmatic
    Next
    

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 5:58
    モデレータ
  • すみません。上記で再掲の箇所が空白になっています。再掲したかったのは以下です。

    DataGridView.ColumnHeaderMouseClick イベント
    http://msdn.microsoft.com/ja-jp/library/system.windows.forms.datagridview.columnheadermouseclick.aspx#Y0

    #コードブロックを含む投稿を編集するとコードブロック部分に余計な空白行が入るため、修正しづらく新しく追記の形で投稿しました。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    • 回答としてマーク ジョウジ 2011年11月2日 7:28
    2011年11月2日 6:00
    モデレータ
  • trapemiya様mars12様のお陰で無事解決することが出来ました

    ありがとうございます。

    自分なりに少し手直ししてみましたので確認の程よろしくお願いします。

    Imports System.Data.SqlClient
    Public Class Form1
        Private table As New DataTable

        Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
            Using cn As New SqlConnection(My.Settings.SqlConnectionString)
                cn.Open()
                Dim sql As String = "SELECT 大分類,中分類,小分類,中分類並替用 FROM 在庫"
                Dim Adapter As New SqlDataAdapter(sql, cn)
                Adapter.Fill(table)
                DataGridView1.DataSource = table
                DataGridView1.Columns(3).Visible = False
                For Each column As DataGridViewColumn In DataGridView1.Columns
                    column.SortMode = DataGridViewColumnSortMode.Programmatic
                Next
            End Using
        End Sub

        Private Sub DataGridView1_ColumnHeaderMouseClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles DataGridView1.ColumnHeaderMouseClick
            Dim newColumn As DataGridViewColumn = DataGridView1.Columns(e.ColumnIndex)
            Dim dv As DataView = table.DefaultView

            If newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending Then
                If newColumn.HeaderText = "中分類" Then
                    dv.Sort = "中分類並替用 desc"
                Else
                    dv.Sort = newColumn.Name + " desc"
                End If
                newColumn.HeaderCell.SortGlyphDirection = SortOrder.Descending
            Else
                If newColumn.HeaderText = "中分類" Then
                    dv.Sort = "中分類並替用 asc"
                Else
                    dv.Sort = newColumn.Name + " asc"
                End If
                newColumn.HeaderCell.SortGlyphDirection = SortOrder.Ascending
            End If
        End Sub

        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim dv As DataView = table.DefaultView
            dv.Sort = "大分類,中分類並替用,小分類"
            DataGridView1.Columns("大分類").HeaderCell.SortGlyphDirection = SortOrder.Ascending
            DataGridView1.Columns("中分類並替用").HeaderCell.SortGlyphDirection = SortOrder.Ascending
            DataGridView1.Columns("小分類").HeaderCell.SortGlyphDirection = SortOrder.Ascending
        End Sub

    2011年11月2日 7:26
  • DataGridViewのカラムをクリックした際のソートは、中分類並替用だけでよかったのですね。詳しい仕様はわかりませんが、掲載されているコードに関しては見た限り問題ないと思います。

     


    ★良い回答には回答済みマークを付けよう! わんくま同盟 MVP - Visual C# http://d.hatena.ne.jp/trapemiya/
    2011年11月2日 8:18
    モデレータ