Results 1 to 18 of 18

Thread: [RESOLVED] [2008] DataGridView Can't Be Sorted

  1. #1

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Resolved [RESOLVED] [2008] DataGridView Can't Be Sorted

    Hi

    I am using a List of (T) which is bound to a BindingSource component, and this component is bound to a grid, however when I have come to try and sort the list programmatically, I get the following error:

    DataGridView control cannot be sorted if it is bound to an IBindingList that does not support sorting.

    The thing is I really, really need the grid to be sortable programmatically by any means necessary, if you have any suggestions I would appreciate hearing them.

    Code Used to Sort (Line that produces the error):
    Code:
    Me.dgvuserdetails.Sort(Me.dgvuserdetails.Columns(5), System.ComponentModel.ListSortDirection.Descending)
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  2. #2
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    Um, you say that you want to sort the grid programmatically but what you actually mean is that you want it to sort itself automatically. You absolutely can sort it programmatically, but that means that you would write the code to sort the items yourself, not just expect the grid to do it for you.

    The thing is, the only way that a DataGridView will sort automatically for you is if its data source implements the IBindingList interface and supports sorting. The generic List class does NOT implement the IBindingList interface so it will not sort automatically. If you want the grid to be able to sort automatically then you'll need to create your own class that does implement IBindingList and dies support sorting. You can use the generic BindingList class as a base for such a class. I suggest that you read the documentation for the IBindingList interface and the BindingList class.

    Note that the DataView class DOES implement the IBindingList interface and DOES support sorting. That's why a DataGridView bound to a DataTable will sort automatically. The DataView class actually implements the IBindingListView interface, which is more advanced that IBindingList. IBindingList provides for simple sorting, i.e. by a single column. IBindingListView provides for complex sorting, i.e. by multiple columns, and filtering.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  3. #3

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Thanks for the information, really useful.

    One thing I forgot to mention is that my list is bound to a BindingSource componenet, and this is what populates the datagridview with data. I have had a good read on MSDN about IBindingList.

    This is what i have managed to put together

    Code:
    Public Class List(Of T) : Inherits BindingList(Of User)
        Implements IBindingList
    
    End Class
    Here's what I use to created the BindingList (Note I changed from List of (t) to bindinglist from my previous post)

    Code:
    Dim Users As New BindingList(Of User)
    The thing is if the first block of code is correct, do I simple paste the class in with my form class, or inherit from it etc?

    Thanks for your help once again
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  4. #4
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    First up, the BindingList class already implements the IBindingList interface so, if you inherit BindingList, there's no need or point to explicitly implementing IBindingList.

    Secondly, the BindingList class is generic to begin with. If you want your class to be generic too then you do NOT fix the generic type of the BindingList when you inherit it:
    vb.net Code:
    1. Public Class List(Of T)
    2.     Inherits BindingList(Of T)
    if you want your class to be strongly-typed then you DO fix the generic type of the BindingList when you inherit it, but you do NOT make your class generic:
    vb.net Code:
    1. Public Class UserList
    2.     Inherits BindingList(Of User)
    I think you'll need to go with the second option if you expect to implement your own sorting routine.

    That brings me to the last point. Now you have to override the appropriate members of the BindingList class and implement your own sorting routine.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  5. #5

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Thanks for the feedback

    Okay well I'm going to use the sorting routines already available because I don't required anything special, and its much easier for me.

    The thing is, I'm not really sure what to do with the List of (T) class, I mean do I simply insert:

    Code:
     
          Public Class List(Of T)
              Inherits BindingList(Of T)
    End Class
    Within my form or a module because its got the exact same name as the default List (Of T) class, therefore the default class will just inherit BindingList of (T)'s properties and methods etc. I'm probably totally wrong, its just that I only create a list by declaring it and then pass my User class through it which just has a few properties and a construct.

    If it helps I can copy my code, as I'm confusing myself here

    Thanks
    Last edited by Bopo; Nov 29th, 2008 at 07:05 PM. Reason: noticed typo's
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  6. #6

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Late night bump
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  7. #7
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    No, the System.Collections.Generic.List(Of T) class will not inherit the System.ComponentModel.BindingList(Of T) class. You can't change the base class of an existing class. You're declaring a new type: the WindowsApplication1.List(Of T) class, or whatever the default namespace is for your project.

    That said, it's probably better to use a name other than "List" to avoid confusion. Follow the Custom Collection link in my signature for an explanation. I haven't got as far as sorting yet but what you'll need to do is:

    1. Define your own class that implements the IComparer interface by taking a property name and comparing on the property with that name.

    2. Override the SupportsSortingCore property to return True, to indicate that sorting is supported.

    3. Override the ApplySortCore method to sort the items using an instance of your IComparer class.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  8. #8

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Edit:

    Okay here's what I have managed to do so far:

    Code:
    Public Class RowComparer
        Implements System.Collections.IComparer
    
    
        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements System.Collections.IComparer.Compare
           
            
        End Function
    End Class
    I actually found an example of sorting an unbound datagridview and tried it out just for the sake of it, obviously it threw an exception:

    Code:
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            dgvuserdetails.Sort(New RowComparer(SortOrder.Ascending))
        End Sub
    
    Public Class RowComparer
        Implements System.Collections.IComparer
        Private Shared SortOrderModifier As Integer = 1
    
        Public Sub New(ByVal sortOrder_1 As SortOrder)
            If sortOrder_1 = 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 DGVRow1 As DataGridViewRow = DirectCast(x, DataGridViewRow)
            Dim DGVRow2 As DataGridViewRow = DirectCast(y, DataGridViewRow)
    
            Dim CompareResults As Integer = System.String.Compare(DGVRow1.Cells(0).Value.ToString(), DGVRow2.Cells(0).Value.ToString())
        End Function
    End Class
    Last edited by Bopo; Nov 30th, 2008 at 11:05 AM.
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  9. #9
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    You would be better served implementing the generic IComparer interface. It will need to accept a column/property to compare by and a sort direction. These values are set by the collection when it creates an instance. Those values are then used in the Compare method.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  10. #10

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Okay I am now using the generic ICompare interface, however I can't find an example of how I would write code to tell the interface to accept the column/property to compare by, I known your a busy guy, but I would really appreciate an example when you have some free time

    Code:
    Imports System.Collections.Generic
    
    Public Class RowComparer
        Implements IComparer
    
    
        Public Function Compare(ByVal x As Object, ByVal y As Object) As Integer Implements IComparer.Compare
    
        End Function
    Thanks
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  11. #11
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    You don't need an example. You already know how to get data into an object because you do it all the time. You set a property or call a method and pass an argument. This is no different. The most logical choice is to add a constructor with a parameter for the property to sort by. That way you can't create an instance without providing that data.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  12. #12
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    If you can wait about 8 hours I'll be posting more code in the CodeBank.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  13. #13
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    Attached is the code I intend to post in the CodeBank. It's not quite complete and it's undocumented but it will work as is and it shows you how to implement the IComparer interface and how to use that class to sort the collection.
    Attached Files Attached Files
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  14. #14

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Hi

    Sorry about the late reply, been away for a few days, anyway that class looks amazing, however no matter how hard I try, I just can't get it to work for me, I been using trial and error for the past hour or so and Im not getting anywhere, its not actually throwing an error either .

    Anyway to make sure my coding was not interfering, I re-made the data binding and sorting part in another project, and once again no error occured but nothing happened, below is the code which is identical to my original project

    Form:

    Code:
    Imports System.ComponentModel
    
    Public Class Form1
    
        Dim Users As New BindingList(Of User)
        Dim People As New PersonCollection
    
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Users.Add(New User(TextBox1.Text, TextBox2.Text, TextBox3.Text))
        End Sub
    
        Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
            DataGridView1.DataSource = BindingSource1
            BindingSource1.DataSource = Me.Users
        End Sub
    
        Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
            People.Sort = "FirstName"
        End Sub
    End Class
    User Class:

    Code:
    Imports System.ComponentModel
    
    Public Class User
    
        Private _firstName As String
        Private _lastName As String
        Private _age As Integer
    
        Public Property FirstName()
            Get
                Return _firstName
            End Get
            Set(ByVal value)
                _firstName = value
            End Set
        End Property
    
        Public Property LastName()
            Get
                Return _lastName
            End Get
            Set(ByVal value)
                _lastName = value
            End Set
        End Property
    
        Public Property Age()
            Get
                Return _age
            End Get
            Set(ByVal value)
                _age = value
            End Set
        End Property
    
        Public Sub New(ByVal FName As String, ByVal LName As String, ByVal AG As Integer)
            _firstName = FName
            _lastName = LName
            _age = AG
        End Sub
    End Class
    JMC's Class:

    Code:
    Imports System.ComponentModel
    
    Public Class PersonCollection
        Inherits System.ComponentModel.BindingList(Of Person)
    
    #Region " Types "
    
        Private Class PersonComparer
            Implements System.Collections.Generic.IComparer(Of Person)
    
            Private prop As PropertyDescriptor
            Private direction As ListSortDirection
    
            Public Function Compare(ByVal x As Person, _
                                    ByVal y As Person) As Integer Implements IComparer(Of Person).Compare
                Dim result As Integer = DirectCast(Me.prop.GetValue(x), IComparable).CompareTo(Me.prop.GetValue(y))
    
                If Me.direction = ListSortDirection.Descending Then
                    result = -result
                End If
    
                Return result
            End Function
    
            Public Sub New(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
                Me.prop = prop
                Me.direction = direction
            End Sub
    
        End Class
    
    #End Region 'Types
    
    #Region " Variables "
    
        Private _sort As String
        Private _sortProperty As PropertyDescriptor
        Private _sortDirection As ListSortDirection
    
    #End Region 'Variables
    
    #Region " Properties "
    
        Public Property Sort() As String
            Get
                Return Me._sort
            End Get
            Set(ByVal value As String)
                Dim prop As PropertyDescriptor = Nothing
                Dim direction As ListSortDirection
    
                Me.ParseSortClause(value, prop, direction)
                Me._sort = value
    
                If prop Is Nothing Then
                    Me.RemoveSortCore()
                Else
                    Me.ApplySortCore(prop, direction)
                End If
            End Set
        End Property
    
        Protected Overrides ReadOnly Property SortDirectionCore() As System.ComponentModel.ListSortDirection
            Get
                Return Me._sortDirection
            End Get
        End Property
    
        Protected Overrides ReadOnly Property SortPropertyCore() As System.ComponentModel.PropertyDescriptor
            Get
                Return Me._sortProperty
            End Get
        End Property
    
        Protected Overrides ReadOnly Property SupportsSortingCore() As Boolean
            Get
                Return True
            End Get
        End Property
    
    #End Region 'Properties
    
    #Region " Methods "
    
        Protected Overrides Sub ApplySortCore(ByVal prop As PropertyDescriptor, ByVal direction As ListSortDirection)
            Me._sortProperty = prop
            Me._sortDirection = direction
    
            Dim upperBound As Integer = Me.Items.Count - 1
            Dim items(upperBound) As Person
    
            Me.Items.CopyTo(items, 0)
    
            Array.Sort(items, _
                       New PersonComparer(prop, _
                                          direction))
    
            For index As Integer = 0 To upperBound
                Me.Items(index) = items(index)
            Next
    
            Me.OnListChanged(New ListChangedEventArgs(ListChangedType.Reset, 0))
        End Sub
    
        Protected Overrides Sub RemoveSortCore()
            Me._sortProperty = Nothing
            Me._sortDirection = Nothing
        End Sub
    
        Private Sub ParseSortClause(ByVal clause As String, _
                                    ByRef prop As PropertyDescriptor, _
                                    ByRef direction As ListSortDirection)
            If clause IsNot Nothing AndAlso clause.Trim() <> String.Empty Then
                Dim parts As String() = clause.Split(" "c)
    
                If parts.Length > 2 Then
                    Throw New ArgumentException("Invalid sort clause")
                End If
    
                For index As Integer = 0 To parts.GetUpperBound(0)
                    parts(index) = parts(index).Trim()
                Next
    
                prop = TypeDescriptor.GetProperties(GetType(Person))(parts(0))
    
                If prop Is Nothing Then
                    Throw New ArgumentException("Invalid property name")
                End If
    
                If parts.Length = 1 OrElse _
                   parts(1) = String.Empty OrElse _
                   String.Compare(parts(1), "ASC", True) = 0 Then
                    direction = ListSortDirection.Ascending
                ElseIf String.Compare(parts(1), "DESC", True) = 0 Then
                    direction = ListSortDirection.Descending
                Else
                    Throw New ArgumentException("Invalid sort direction")
                End If
            End If
        End Sub
    
    #End Region 'Methods
    
    End Class
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  15. #15
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    Um, you are creating a PersonCollection but you aren't binding it to your grid. You're binding a plain old BindingList, which doesn't support sorting, to the grid. Why 2 collections?
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  16. #16
    Super Moderator jmcilhinney's Avatar
    Join Date
    May 2005
    Location
    Sydney, Australia
    Posts
    111,221

    Re: [2008] DataGridView Can't Be Sorted

    I'm on a mobile phone at the moment and it's not ideal for jumping between threads and reading long code listings. As a result I may be missing something but it seems that you've missed the point of what I was trying to say.

    My code is an EXAMPLE of a CUSTOM collection. It allows you to sort a collection of Person objects, but you don't want to sort Person objects. You want to sort User objects. You're supposed to define your own UserCollection using the pattern I've provided.
    Why is my data not saved to my database? | MSDN Data Walkthroughs
    VBForums Database Development FAQ
    My CodeBank Submissions: VB | C#
    My Blog: Data Among Multiple Forms (3 parts)
    Beginner Tutorials: VB | C# | SQL

  17. #17

    Thread Starter
    Hyperactive Member
    Join Date
    Dec 2006
    Location
    UK
    Posts
    489

    Re: [2008] DataGridView Can't Be Sorted

    Yeah I was missing the point before, I understand it now and is working, thanks
    Learning C♯

    Data Binding & Bound Controls - Objects and wizards will never be as intelligent as you, do it yourself! (Unless your Pro)

  18. #18
    New Member
    Join Date
    Jan 2013
    Posts
    1

    Re: [2008] DataGridView Can't Be Sorted

    UnFreakingBelievable... I can't tell you how much I learned from going through your code about how many different things!!!!!

    It's amazing that it's more than 4 years old...

    Geez, you are the same guy who helped me get started last month when I couldn't get an MSDN example to run. Thank you, again, Mr. jmcilhinney.. Thank you, very, very much.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width