Results 1 to 4 of 4

Thread: Apply databinding to inherited control

  1. #1
    hermiod is offline VB.NET Forum Newbie
    .NET Framework
    .NET 2.0 (VS 2005)
    Join Date
    Mar 2008
    Posts
    6
    Reputation
    0

    Question Apply databinding to inherited control

    I'm trying to modify the listview to have similar databinding behaviour to a datagrid with the added bonus of having the ability to group by a column in the datasource.

    Below is the code I have developed so far. The only problem is that this code only binds to a datatable. I'd like to be able to bind to all the sources that a datagrid can (datatable, collection, etc).
    I've spent alot of time searching on the net and all the examples I have found either show what I have already done, implement much more complex databinding than I need, or I can't make enough sense of the code to be able to modify it to suits my needs!

    Could anyone point me to somewhere that will show me how to do what I need or give me a few pointers

    Code:
    Imports System.ComponentModel
    
    Public Class GroupingListView
        Inherits System.Windows.Forms.ListView
    
        Private _dataSource As Object
        Private _GroupBy As String
        Private _GroupTitle As String
        Private _GroupTag As String
        Private DoGrouping As Boolean = False
        Private DoGroupTitle As Boolean = False
        Private DoGroupTag As Boolean = False
    
        <TypeConverter("System.Windows.Forms.Design.DataSourceConverter, System.Design")> _
        <Category("Data")> _
        Public Property DataSource() As Object
            Get
                Return _dataSource
            End Get
            Set(ByVal value As Object)
                _dataSource = value
            End Set
        End Property
    
        <Category("Data")> _
        Public Property GroupBy() As String
            Get
                Return _GroupBy
            End Get
            Set(ByVal value As String)
                _GroupBy = value
            End Set
        End Property
    
        <Category("Data")> _
        Public Property GroupTitle() As String
            Get
                Return _GroupTitle
            End Get
            Set(ByVal value As String)
                _GroupTitle = value
            End Set
        End Property
    
        <Category("Data")> _
        Public Property GroupTag() As String
            Get
                Return _GroupTag
            End Get
            Set(ByVal value As String)
                _GroupTag = value
            End Set
        End Property
    
        Public Sub DataBind()
            If _dataSource Is Nothing Then
                Console.WriteLine("No datasource to bind to")
                Exit Sub
            End If
    
            If TypeOf _dataSource Is DataSet Then
                If CType(_dataSource, DataSet).Tables.Count > 0 Then
                    _dataSource = CType(_dataSource, DataSet).Tables(0)
                End If
            End If
    
            Dim lvwItem As New ListViewItem
            Dim lvwGroup As New ListViewGroup
            Dim Data As DataTable = CType(_dataSource, DataTable)
            Dim NoColumns As Integer = Data.Columns.Count
    
            For Each dc As DataColumn In Data.Columns
                Me.Columns.Add(dc.ColumnName, 100)
    
                If _GroupBy = dc.ColumnName Then
                    DoGrouping = True
                End If
            Next
    
            For Each dc As DataColumn In Data.Columns
                If _GroupTag = dc.ColumnName Then
                    'MsgBox("Column: " & dc.ColumnName & vbNewLine & "groupby: " & _GroupBy)
                    DoGroupTag = True
                End If
            Next
    
            For Each dc As DataColumn In Data.Columns
                If _GroupTitle = dc.ColumnName Then
                    DoGroupTitle = True
                End If
            Next
    
            If DoGrouping = True Then
                For Each dr As DataRow In Data.Rows
                    If lvwGroup.Name <> dr.Item(_GroupBy) Then
                        lvwGroup = New ListViewGroup()
                        lvwGroup.Name = dr.Item(_GroupBy)
    
                        If DoGroupTitle = True Then
                            lvwGroup.Header = dr.Item(_GroupTitle)
                        Else
                            lvwGroup.Header = dr.Item(_GroupBy)
                        End If
    
                        'If GroupTag property is a column that exists in the column 
                        'then assign the property of this column to the tag property.
                        If DoGroupTag = True Then
                            lvwGroup.Tag = dr.Item(_GroupTag)
                        End If
    
                        Me.Groups.Add(lvwGroup)
    
                        lvwItem = New ListViewItem
                        lvwItem.Text = dr.Item(0)
                        For i As Integer = 1 To NoColumns - 1
                            lvwItem.SubItems.Add(dr.Item(i))
                        Next
                        Me.Items.Add(lvwItem)
                        Me.Groups(lvwGroup.Name).Items.Add(lvwItem)
                    Else
                        lvwItem = New ListViewItem
                        lvwItem.Text = dr.Item(0)
                        For i As Integer = 1 To NoColumns - 1
                            lvwItem.SubItems.Add(dr.Item(i))
                        Next
                        Me.Items.Add(lvwItem)
                        Me.Groups(lvwGroup.Name).Items.Add(lvwItem)
                    End If
                Next
            Else
                For Each dr As DataRow In Data.Rows
                    lvwItem = New ListViewItem
                    lvwItem.Text = dr.Item(0)
                    For i As Integer = 1 To NoColumns - 1
                        lvwItem.SubItems.Add(dr.Item(i))
                    Next
                    Me.Items.Add(lvwItem)
                Next
            End If
    
            AutoSizeColumns()
    
        End Sub
    
    End Class

  2. #2
    JohnH's Avatar
    JohnH is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Dec 2005
    Location
    Norway
    Posts
    14,197
    Reputation
    2368
    Done quick and dirty, but it seems to work with all my small tests in the very short time this was done (about 1 hour or so)... see attached project. As for pointers, it is done with Reflection, it's the only way to iterate the properties of unknown objects. I removed GroupTitle property because I couldn't figure out what you meant with it, but added the standard DataMember property to choose between tables in a Dataset. Have a look.
    Attached Files Attached Files

  3. #3
    hermiod is offline VB.NET Forum Newbie
    .NET Framework
    .NET 2.0 (VS 2005)
    Join Date
    Mar 2008
    Posts
    6
    Reputation
    0

    Thumbs up

    Thanks JohnH, that is absolutely brilliant! I've only had a quick look but it seems that will do exactly what I need.

    As for GroupTitle, it is intended for use where you might want the title of the group to be different from the values in the GroupBy field, in my case I want to group by a course code but want the title to show the course description as there is the possibility that two different courses could have the same description, which will bugger up the grouping.

    Thanks again for that JohnH, much appreciated.

  4. #4
    JohnH's Avatar
    JohnH is offline VB.NET Forum Moderator
    .NET Framework
    .NET 4.0
    Join Date
    Dec 2005
    Location
    Norway
    Posts
    14,197
    Reputation
    2368
    Some more info, except handling IList types specifically (that includes arrays and collections) I just checked for Dataset/Datatable types. There is a common denominator for these also, they both implement IListSource. This is an interface with only two members, GetList method that returns an IList of items (for example DataTable rows), and ContainsListCollection property that tell if the returned IList items themselves are IList instances (for example True for Dataset which may contain multiple tables). Also other data sets/table types may implement IListSource and be bindable, so to take this class further it could be an idea to look more into reflecting IListSource.

Tags for this Thread

Bookmarks

Posting Permissions

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