Mech_Engineer
Mech_Engineer

Reputation: 555

Custom collection as datagridview datasource

I am learning to create custom class and collection class. Now to put my newly learned skills to the test, I would like to display the collection class in a datagridview object.

If I set the collection class as datasource, no data is populated in the datagridview..

My sample contains a purchase class object containing some properties. The purchases are collected in one collect class called purchases.

The datagridview should show all purchases in the collection to the user.

Below is my code.

Public Class PurchasesEditor

Private Property Purchases As New Purchases

Public Sub New()

    ' This call is required by the designer.
    InitializeComponent()

    ' Add any initialization after the InitializeComponent() call.
    Dim oPurchase As New Purchase
    oPurchase.ID = Purchases.Count + 1
    oPurchase.Description = "Test item"
    oPurchase.Supplier = "Wallmart"
    oPurchase.PurchaseDate = "13/09/2018"
    oPurchase.VAT = 21
    oPurchase.Amount = 100

    Purchases.Add(oPurchase)

    dgvPurchases.DataSource = Purchases

End Sub

End Class

Purchases collection class Public Class Purchases

Private PurchaseList As New List(Of Purchase)

Public Sub Add(purchase As Purchase)
    PurchaseList.Add(purchase)
End Sub

Public Function Remove(purchase As Purchase) As Boolean
    Return PurchaseList.Remove(purchase)
End Function

Public Function GetEnumerator() As IEnumerator(Of Purchase)
    Return PurchaseList.GetEnumerator
End Function

Public ReadOnly Property Count() As Integer
    Get
        Return PurchaseList.Count
    End Get
End Property


End Class

Purchase class Public Class Purchase

Public Property ID As Long
Public Property Description As String
Public Property Supplier As String
Public Property PurchaseDate As Date
Public Property Amount As Decimal
Public Property VAT As Double

Public ReadOnly Property VATamount As Decimal
    Get
        Return Amount + Amount * (VAT / 100)
    End Get
End Property


' TODO custom collection
'Public Property AttachedDocuments As List(Of Document)

End Class

Upvotes: 0

Views: 625

Answers (1)

jmcilhinney
jmcilhinney

Reputation: 54457

The problem is that your Purchases class is NOT a collection. It CONTAINS a collection, i.e. the List(Of Purchase) you assign to the PurchaseList field, but that is hidden inside. The DataGridView won't magically get at that data and display it.

In order for your class to be a list/collection then, at the very least, it must implement the IEnumerable and/or IEnumerable(Of T) interface. You can also implement ICollection and/or ICollection(Of T), which extend the previous interfaces. You can also implement IList and/or IList(Of T), which extend the previous interfaces even further. In order to be useful in binding to a DataGridView you would need to implement IList and you should implement IList(Of T) too.

You can implement those interfaces from scratch if you want but you shouldn't. The System.Collections.ObjectModel.Collection(Of T) class provides a base implementation of IList and IList(Of T) that you can extend by inheriting and then overriding and/or adding your own functionality. If you are aiming to bind specifically then you should instead inherit the System.ComponentModel.BindingList(Of T) class, which inherits Collection(Of T) and adds specific binding support by implementing the IBindingList interface. If you need filtering functionality too then you can implement the IBindingListView interface as well.

Unless you need specific custom functionality, you should just stick with the List(Of T). If you use one in data-binding scenarios though, it doesn't raise the events required for the UI to update on changes. In that case, you can bind the list to a BindingSource and bind that to your UI, then call methods like ResetBindings as required to update the UI.

I suggest that you read this for more detailed information.

Upvotes: 4

Related Questions