DOBON.NETプログラミング道掲示板

ツリー一括表示

Nomalアイコン データバインド時のDataGridViewのカスタムソート /ミンミン (18/11/15(Thu) 14:02) #34034
Nomalアイコン Re[1]: データバインド時のDataGridViewのカスタムソート /魔界の仮面弁士 (18/11/16(Fri) 12:03) #34035
  └Nomalアイコン Re[2]: データバインド時のDataGridViewのカスタムソート /ミンミン (18/11/26(Mon) 15:03) #34041 解決み!


親記事 / ▼[ 34035 ]
■34034 / 親階層)  データバインド時のDataGridViewのカスタムソート
□投稿者/ ミンミン 一般人(1回)-(2018/11/15(Thu) 14:02:24)
  • アイコン環境/言語:[VB2013] 
    分類:[.NET] 

    DataGridViewのカスタマイズソートについて、以下には
    IComparerインターフェイスを使用する方法が紹介されています。

    DataGridViewの行の並び替えの方法を変更する
    〜DataGridView.Sortメソッドを使用する方法〜
    https://dobon.net/vb/dotnet/datagridview/customsort.html#section2

    この方法だと、かなり特殊なソート方法を定義できるので便利なのですが、
    「DataGridViewのDataSourceプロパティが設定されておらず...」
    という注釈があります。

    これは、DataGridViewにデータバインドしている場合には
    IComparerインターフェイスの方法が使用できない、と理解したのですが、
    データバインドを行った場合でも、IComparerインターフェイスのように
    かなり自由にソート方法を定義する方法はないでしょうか?
    バインドしたデータにソート値用の列を設けることも考えたのですが、
    新しい項目をバインド元データに用意するのもどうかと思い、
    質問した次第です。
違反を報告
[ □ Tree ] 返信 削除キー/

▲[ 34034 ] / ▼[ 34041 ]
■34035 / 1階層)  Re[1]: データバインド時のDataGridViewのカスタムソート
□投稿者/ 魔界の仮面弁士 大御所(1168回)-(2018/11/16(Fri) 12:03:48)
  • アイコン
    No34034に返信(ミンミンさんの記事)
    > データバインドを行った場合でも、IComparerインターフェイスのように
    > かなり自由にソート方法を定義する方法はないでしょうか?
    
    手抜き実装だとこんな感じ。
    
    Imports System.ComponentModel
    
    Public Class Form1
        Private list As New SortableBindingList(Of Record)()
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            list.Add(New Record(4, "あああ"))
            list.Add(New Record(1, "いいい"))
            list.Add(New Record(999, "これを先頭にする"))
            list.Add(New Record(3, "ううう"))
            list.Add(New Record(5, "えええ"))
            list.Add(New Record(2, "あああ"))
            DataGridView1.DataSource = list
        End Sub
    End Class
    
    Public Class Record
        Implements IComparable, IComparable(Of Record)
        Public Property Id As Integer
        Public Property Name As String
        Public Sub New(id As Integer, name As String)
            Me.Id = id
            Me.Name = name
        End Sub
    
        Public Function CompareTo(other As Record) As Integer Implements IComparable(Of Record).CompareTo
            '★ここが独自の比較処理★
            If Id = 999 Then
                Return -1
            ElseIf other.Id = 999 Then
                Return 1
            Else
                Return Id.CompareTo(other.Id)
            End If
        End Function
    
        Private Function CompareTo(obj As Object) As Integer Implements IComparable.CompareTo
            Return Me.CompareTo(DirectCast(obj, Record))
        End Function
    End Class
    
    Public Class SortableBindingList(Of T)
        Inherits BindingList(Of T)
        Protected Overrides ReadOnly Property SupportsSortingCore As Boolean
            Get
                Return True
            End Get
        End Property
        Protected Overrides Sub ApplySortCore(prop As PropertyDescriptor, direction As ListSortDirection)
            Dim list = TryCast(Items, List(Of T))
            If list Is Nothing Then
                Return
            End If
            list.Sort()
            OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, -1))
        End Sub
    End Class
    
    
    上記は、レコード側に IComparable を付けただけなので、
    昇順/降順の切り替えや、別の列をソートするなどの対応が出来ません。
    
    降順などにも対応させたい場合には、ApplySortCore の引数もチェックします。
    また、その場合はレコード側に IComparable を実装するのではなく、
    IComparer(Of T) を実装したカスタムソート用のクラスを用意して、
    『list.Sort()』の代わりに『list.Sort( IComparer(Of T) )』を呼びだします。
    
    参考リンク
    https://garafu.blogspot.com/2016/09/cs-sorablebindinglist.html

違反を報告
[ 親 34034 / □ Tree ] 返信 削除キー/

▲[ 34035 ] / 返信無し
■34041 / 2階層)  Re[2]: データバインド時のDataGridViewのカスタムソート
□投稿者/ ミンミン 一般人(2回)-(2018/11/26(Mon) 15:03:36)
  • アイコン魔界の仮面弁士 さん、ありがとうございました。
    色々と試してみます。
解決み!
違反を報告
[ 親 34034 / □ Tree ] 返信 削除キー/


Mode/  Pass/


- Child Tree -