Datagridview grid references change after showing a new form - help please!

DoJa

Member
Joined
Jul 26, 2011
Messages
21
Programming Experience
Beginner
Hi All,

I'm using a datagridview to display a list of names added to a register (in a datatable) which then later get copied to an external database. The system worked perfectly until recently when I added a second form to my project. I noticed if I changed forms from the one with the dgv to another and then back again, I lose the ability to delete items from my dgv using the buttons in the 'delete button' column.

A bit of investigation revealed that the reason for this was because when changing between forms, the grid reference for the dgv changed. To begin with the column with my 'x' buttons was '5' but after flicking between forms this changed to '0' , the other column reference values also changed. There is nothing in the onload/onshow or on leave/hide events for either form which could cause this and I'm at a total loss as to why this is happening. Anyone able to point me in the right direction or give some advice?

Here's a copy of the code i've got in the onclick event for the datagridview:

Private Sub dgvRegister_CellContentClick(ByVal sender As System.Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles dgvRegister.CellContentClick
        MessageBox.Show(varRowcount)
        'Prevent every name from being deleted from the register list (If all names are removed, new names cannot be added)
        If varRowcount > 0 Then
            MessageBox.Show(e.ColumnIndex)
            'Ensure that rows are only deleted when the X button is pressed (column index 5)
            If e.ColumnIndex = 5 Then

                'Confirm deletion of member from register
                Dim msg As DialogResult = MessageBox.Show("Are you sure you want to remove " & dgvRegister.Item(1, dgvRegister.CurrentRow.Index).Value & "from today's register?", "Question", MessageBoxButtons.YesNo, MessageBoxIcon.Question)
                If msg = vbNo Then
                    Exit Sub
                End If

                'Remove Selected Row
                dgvRegister.Rows.Remove(dgvRegister.CurrentRow)

                'Update row count
                varRowcount = varRowcount - 1
                lblTotalval.Text = varRowcount
            End If
        Else
            lblStatus.Text = "You cannot delete another name from the register list until you add another member"
        End If

    End Sub
 
Last edited by a moderator:
Instead of hard-coding '5' as the column index, actually get the Index property of the column of interest and compare that to e.ColumnIndex. If you added the column in the designer, which I assume that you would have for a button column, then the form has a member variable for that column, from which you can get the Index.
 
Thanks for your quick reply. I think I understand the jist of what you are saying, but my knowledge is too limited to actually translate it into anything useful. Please could you explain in a bit more detail what line of code/function are you saying I should use?

Your assumption is incorrect. I am actually creating the button column in code.

Here is the code i'm using to create the data table/populate the datagrid view. The following is run once when the first person is added to the register.

    ' Create New Data Table
            table = New DataTable()


            'Declare Column Variables
            Dim colCustomerid As DataColumn
            Dim colFullname As DataColumn
            Dim colFromcash As DataColumn
            Dim colFromaccount As DataColumn
            Dim colUpdateValue As DataColumn

            ' Create Empty Columns
            colCustomerid = New DataColumn("ID", Type.GetType("System.String"))
            colFullname = New DataColumn("Name", Type.GetType("System.String"))
            colFromcash = New DataColumn("Cash", Type.GetType("System.String"))
            colFromaccount = New DataColumn("Account", Type.GetType("System.String"))
            colUpdateValue = New DataColumn("Update Value", Type.GetType("System.String"))

            ' Add Coulumns to table
            table.Columns.Add(colCustomerid)
            table.Columns.Add(colFullname)
            table.Columns.Add(colFromcash)
            table.Columns.Add(colFromaccount)
            table.Columns.Add(colUpdateValue)

            'Add datatable to dataset
            dataset.Tables.Add(table)

            'Bind Table to datagridview
            dgvRegister.DataSource = table

            'Set Width of 'Name' Column in datagridview
            Dim column As DataGridViewColumn = dgvRegister.Columns("Name")
            column.Width = 199

            ' Add delete button column. 
            Dim buttonColumn As New DataGridViewButtonColumn()
            buttonColumn.HeaderText = "X"
            buttonColumn.Name = "X"
            buttonColumn.Text = "X"
            buttonColumn.Width = "20"
            buttonColumn.UseColumnTextForButtonValue = True
            dgvRegister.Columns.Add(buttonColumn)

            'Hide irrelevant columns
            dgvRegister.Columns("ID").Visible = False
            dgvRegister.Columns("Cash").Visible = False
            dgvRegister.Columns("Account").Visible = False
            dgvRegister.Columns("Update Value").Visible = False

        End If
 
How do you usually access a member variable? If you want to get the Text of a TextBox, how do you do that? If you want to get the SelectedIndex of a ComboBox, how do you do that? Getting the Index of a DataGridViewButtonColumn is exactly the same. When you add something in the designer, a member variable is added to your form class.
 
Sometimes I think you are intentionally blunt, however I thank you as your suggestions have lead me in the direction of a solution.

A few things to ponder though ..

I remember now the reason I added the delete button column in code and not design .. it was because I wanted it on the far right hand side not the far left. If i added it in code after creating the other columns it would be in the place I wanted but adding it in design view puts it on the left. Do you know a way to change its position to move it to the right hand side?
 
I want people to solve their own problems as much as possible; both those that they post and those that they haven't encountered yet. By making them think for themselves I hope to make them employ the sort of logic that will help them in the future.

As for the latest question, you simply set the DisplayIndex of a column to make it display where you want. This is an example of why you should read the documentation. Anything that takes a single property or method can usually be found by reading the appropriate documentation.
 
I want people to solve their own problems as much as possible; both those that they post and those that they haven't encountered yet. By making them think for themselves I hope to make them employ the sort of logic that will help them in the future.
I guessed as much! :adoration:

Although your previous suggestion has in effect solved my problem, do you know why it was necessary for me to do it this way? Why did switching between forms cause the column indexes to change? It would be nice to understand why, so as to avoid similar situations in future.
 
I don't know the details but I would assume that, for some reason, the other columns were destroyed and recreated, thus being added after the button column. Maybe it's something you did or maybe it's something inherent to the DataGridView, although I've not see it before.
 
Is it possible to create all my columns in design view for both text and button? I know physically it is possible as I have done it, but I encountered a problem where when binding the datagrid view to my dataset/datatable I would get duplicate columns. I had hoped that by using the same name/identifier for the column headings in the data table and datagrid view that when binding the two the data would be put into the already existing columns of the same name rather than creating a duplicate set.

Any suggestions for getting around this ?
 
Lots of useful info there thanks, unfortunately everything there seems to relate to creating datagridview columns manually in code rather than how to bind to colums that were made in design view.
 
You are trying to make this more difficult than it is. Whether a column is created in the designer or in code is irrelevant. It's still the same column. If you add one TextBox in the designer and one in code, how do you then display text in each? You set the Text property, right? It's the same regardless because a TextBox is a TextBox. The same goes for columns in a DataGridView. They still have exactly the same properties regardless of how they are created. It's also worth noting that your actions in the designer are converted to code anyway, so all controls are created in code regardless. JohnH has provided you with the very information you need to bind a column created in the designer.
 
Am I complicating matters by using both a dataset and a datagrid view? Should I be doing away with the dataset and entering data directly into the datagridview itself?
 
Back
Top