Results 1 to 11 of 11

Thread: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error.

  1. #1

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Question I'm adding objects to a list linked to a dgv. When I click the dgv I get an error.

    Hello guys. I have this problem. I have a single form with two datagridview components (dgv1 and dgv2).

    Both are linked to two list of Tobjeto. I have code in dgv1 that when I double click, I add an object to the list2.

    All looks fine, but when I click on dgv2, I get a an error:

    An unhandled exception of type 'System.IndexOutOfRangeException' occurred in System.Windows.Forms.dll

    Additional information: Index -1 does not have a value.

    Any ideas? Here is the code. You just need to have 1 form with two dgv (1 and 2).

    Code:
    Public Class TestForm
        Dim list1 As New List(Of TObjecto)
    
        Dim list2 As New List(Of TObjecto)
    
        Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
            For i = 0 To 2
                Dim producto As New TObjecto
                producto.IDproducto = 0
                producto.Nombre = "NOMBRE" & i.ToString
                list1.Add(producto)
            Next
    
            dgv1.DataSource = list1
    
            dgv2.DataSource = list2
        End Sub
    
        Private Sub RefrescarGrillas()
            dgv2.DataSource = Nothing
            dgv2.DataSource = list2
        End Sub
    
        Private Sub dgv1_CellDoubleClick(sender As Object, e As DataGridViewCellEventArgs) Handles dgv1.CellDoubleClick
            Dim tmpPedido As New TObjecto
            tmpPedido.IDproducto = 0
            tmpPedido.Nombre = list1(e.RowIndex).Nombre
            list2.Add(tmpPedido)
            Me.RefrescarGrillas()
        End Sub
    
    End Class
    
    Public Class TObjecto
        Private _IDproducto As Integer
        Public Property IDproducto() As Integer
            Get
                Return _IDproducto
            End Get
            Set(ByVal value As Integer)
                _IDproducto = value
            End Set
        End Property
    
        Private _Nombre As String
        Public Property Nombre() As String
            Get
                Return _Nombre
            End Get
            Set(ByVal value As String)
                _Nombre = value
            End Set
        End Property
    End Class
    THANKS!

  2. #2
    Sinecure devotee
    Join Date
    Aug 2013
    Location
    Southern Tier NY
    Posts
    6,162

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    This fixes it for me.
    Code:
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For i = 0 To 2
          Dim producto As New TObjecto
          producto.IDproducto = 0
          producto.Nombre = "NOMBRE" & i.ToString
          list1.Add(producto)
        Next
    
        dgv1.DataSource = list1
    
        '  dgv2.DataSource = list2
      End Sub

  3. #3

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by passel View Post
    This fixes it for me.
    Code:
      Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        For i = 0 To 2
          Dim producto As New TObjecto
          producto.IDproducto = 0
          producto.Nombre = "NOMBRE" & i.ToString
          list1.Add(producto)
        Next
    
        dgv1.DataSource = list1
    
        '  dgv2.DataSource = list2
      End Sub
    Thanks, I would try it back at home.

  4. #4

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by passel View Post
    This fixes it for me.
    In fact it does, so the question is why is this happening, the error I mean.

  5. #5
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by kwanbis View Post
    In fact it does, so the question is why is this happening, the error I mean.
    This issue took a while to track down as the error did not present a stack trace. However, if you modify 'Sub RefrescarGrillas' like this:

    Code:
    Private Sub RefrescarGrillas()
       dgv2.DataSource = Nothing
       dgv2.DataSource = list2
       dgv2.CurrentCell = dgv2.Item(0, dgv2.Rows.Count - 1)
    End Sub
    The added line will throw the same error, but this time you get a stacktrace and it reveals that the problem is in the CurrencyManager for List2. A CurrencyManager object is part of the behind the scenes databinding mechanism. You can retrieve a reference to it like this:
    Code:
    Dim cmList2 As CurrencyManager = CType(Me.BindingContext(list2), CurrencyManager)
    I believe the problem arises due to the limited binding support for a simple IList object like List(Of T) and this is probably a bug in the .Net binding code that does not refresh the data bound list when it is bound to a object that does not support notification of changes.

    However, the fact that you forced DGV2 to reflect changes with code like 'Sub RefrescarGrillas' is a clue that you should probably be doing things differently.

    The simplest would be to declare the lists as 'System.ComponentModel.BindingList(Of TObjecto)' and eliminate 'Sub RefrescarGrillas'.

    An alternative would be to redefine 'RefrescarGrillas' like this:
    Code:
    Private Sub RefrescarGrillas()
       Dim cmList2 As CurrencyManager = CType(Me.BindingContext(list2), CurrencyManager)
       cmList2.Refresh()
    End Sub
    This forces data binding to repopulate itself from the data source and the datagridview will then reflect those changes as well.

  6. #6

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by TnTinMN View Post
    The simplest would be to declare the lists as 'System.ComponentModel.BindingList(Of TObjecto)' and eliminate 'Sub RefrescarGrillas'.
    Thanks, that worked perfectly.

    Quote Originally Posted by TnTinMN View Post
    An alternative would be to redefine 'RefrescarGrillas' like this:
    Code:
    Private Sub RefrescarGrillas()
       Dim cmList2 As CurrencyManager = CType(Me.BindingContext(list2), CurrencyManager)
       cmList2.Refresh()
    End Sub
    This forces data binding to repopulate itself from the data source and the datagridview will then reflect those changes as well.
    This also works perfectly. Can you explain a little bit more what the code does? THANKS!

  7. #7
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by kwanbis View Post
    ...This also works perfectly. Can you explain a little bit more what the code does?
    I can try, but no guaranty that it will make any sense.

    When you set the DataSource property on the DatagridView control, you are creating a data binding for which there are three parts:
    1. The data source. (in your case a List)
    2. A manager object. (CurrencyManager or PropertyManager Class)
    3. The data consuming control. (a DatagridView in your case)

    A data source can represent a single item such as the Text property of a Control and in this case, the manager object will be an instance of (you guessed it!) the Property Manager class. When the data source is collection of items such as a List, the manager object will be a CurrencyManager instance.

    The manager object handles the communication of data from the data source to the consuming control and also the reverse direction from the consuming control to the data source.

    The CurrencyManager maintains an internal List of references to the items in the data source. If the underlying data source object is capable of providing notifications (an Event) that its contents have changed (an item was added or removed), then the CurrencyManager can automatically update its internal List to reflect these changes. However, not all data sources provide this notification. The System.Collections.Generic.List(Of T) is an example of a data source that does not provide any such notifications were-as the System.ComponentModel.BindingList(Of T) provides two events (AddingNew and ListChanged) that the CurrencyManager can subscribe to to keep its internal list current.

    Since the CurrencyManager has no way of ascertaining of the List(Of T)'s current state, it is somewhat running blind when it tries to access the data source using references from its internal list. The only way to solve this issue, is for your code to tell it to update its internal list and hence the call to the CurrencyManager.Refreshmethod.
    Code:
    Dim cmList2 As CurrencyManager = CType(Me.BindingContext(list2), CurrencyManager)
    cmList2.Refresh()
    Hopefully that gives you a bit of the understanding about what is going on.

    P.S.: I should have previously mentioned that you could also use a BindingSource as the data source for the Datagridview. The BindingSource Class implements ICurrencyManagerProvider, so it acts as its own CurrencyManager. However, you would still need to tell it of changes to the List(Of T) class by calling its ResetBindings method similar to the CurrencyManager.Refresh method.

  8. #8

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by TnTinMN View Post
    Code:
    Dim cmList2 As CurrencyManager = CType(Me.BindingContext(list2), CurrencyManager)
    cmList2.Refresh()
    Thanks for the explanation.

    About the code, what I understand is

    1) you define cmList2 As CurrencyManager
    2) then you convert the list2 to a concurrencymanager type in CType(Me.BindingContext(list2), CurrencyManager)
    3) you then call refresh cmList2.Refresh()

    What I don't understand is this "Me.BindingContext(list2)". Why do you have to do that? Why can't you do CType(list2, CurrencyManager)?

    THANKS ONCE MORE!

  9. #9
    Registered User
    Join Date
    Aug 2015
    Posts
    2

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    I can try, but no guaranty that it will make any sense.
    บาคาร่าออนไลน์ 1688

  10. #10
    PowerPoster
    Join Date
    Oct 2010
    Posts
    2,141

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by kwanbis View Post
    ...
    What I don't understand is this "Me.BindingContext(list2)". Why do you have to do that? Why can't you do CType(list2, CurrencyManager)?
    The technical answer is because 'list2' is a instance of List(Of T) and as such it is not an instance of CurrencyManger nor does it derive from CurrencyManager.

    The form's BindingContext property returns either a CurrencyManager or a PropertyManager for the specified data source (list2) as a BindingManagerBase Class type.

    CurrencyManager derives from BindingManagerBase, so cast (CType) to CurrencyManager is valid. The BindingManagerBase Class does not implement the Refresh method. This method is implemented in the CurrencyManager Class.

    P.S: I do hope that you understand that the items appearing in light blue in the text such as:
    are links that you should click on for more information.

  11. #11

    Thread Starter
    Junior Member
    Join Date
    Sep 2015
    Posts
    19

    Re: I'm adding objects to a list linked to a dgv. When I click the dgv I get an error

    Quote Originally Posted by TnTinMN View Post
    P.S: I do hope that you understand that the items appearing in light blue in the text such as:
    are links that you should click on for more information.
    Thanks for all your help. It's been great.

    But somehow it is not working.

    RefrescarGrillas is now:

    Dim cmListaPedidos As CurrencyManager = CType(Me.BindingContext(listaPedidos), CurrencyManager)
    cmListaPedidos.Refresh()

    This works perfectly the first time the form is shown.

    But if I close the form and reopen, it does not works any more.

    EDIT: So I just finished changing all lists to BindingList. Now I'm seeing how can I raise a BindingList event.

    Apparently I need to create INotifyPropertyChanged.

    EDIT2: So I was able to do everything I wanted. Thanks so much for your help! (probably would have more questions latter )
    Last edited by kwanbis; Oct 4th, 2015 at 06:52 PM.

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