Windows Develop Bookmark and Share   
 index > Windows Forms Data Controls and Databinding > Datagridview Issue
 

Datagridview Issue

I am trying to move focus to the previous column in a datagridview if the column is empty

I get this with this code

What am I doin wrong

Operation is not valid because it results in a reentrant call to the SetCurrentCellAddressCore function.

Code Snippet

Private Sub DataGridView1_CellEnter(ByVal sender As Object, ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) Handles DataGridView1.CellEnter

If DataGridView1.CurrentCell.ColumnIndex = 1 Or DataGridView1.CurrentCell.ColumnIndex = 2 Then

If DataGridView1.CurrentRow.Cells(0).Value = Nothing Then

Dim counter As Integer = DataGridView1.CurrentRow.Index

MsgBox("Please select a Name before continuing", MsgBoxStyle.Exclamation)

DataGridView1.CurrentCell = DataGridView1.Rows(e.RowIndex).Cells(e.ColumnIndex - 1)

Exit Sub

End If

End If

End Sub

Davids Learning

Davids Learning  Monday, April 21, 2008 7:10 PM

Hi Davids Learning,

This exception is caused by reentering Cell in CellEnter event.

When you set CurrentCell in CellEnter event, it would cause the program enter Cell twice just as Asif Shaikh said. Actually, in the background, this problem is caused by calling SetCurrentCellAddressCore method twice in CellEnter event.

I would like to suggest you using BeginInvoke in RowEnter Event of DataGridView. BeginInvoke is used for executing code immediately and without interrupt. So it’s nice to set CurrentCell in BeginInvoke, thus you will not receive any reentrance exception.

Here is the solution:

Code Snippet

// Define a delegate for BeginInvoke.

public delegate void ChangeCellDelegate(DataGridViewCellEventArgs e);

//Call BeginInvoke in RowEnter and let it finish the job of setting CurrentCell.

private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)

{

dataGridView1.BeginInvoke(new ChangeCellDelegate(ChangeCell), e);

}

// Delegate method used for setting CurrentCell.

private void ChangeCell(DataGridViewCellEventArgs e)

{

if (dataGridView1.Rows[e.RowIndex].Cells[2].Value == DBNull.Value)

{

dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[2];

MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString());

dataGridView1.BeginEdit(false);

}

}

Hope it helps. If there is anything unclear, please feel free to let me know.

Best wishes,

Jun Wang

Jun Wang Tim  Friday, April 25, 2008 8:25 AM

I think setting CurrentCell in event CellEnter or in CurrentCellChanged event make a recursive call to itself. You can use CellValidating event instead of these two events. Example

private void dataGridView1_CellValidating(object sender, DataGridViewCellValidatingEventArgs e)

{

if (e.ColumnIndex == 0)

{

if (Convert.ToString(e.FormattedValue).Length == 0)

{

int counter = dataGridView1.CurrentRow.Index;

MessageBox.Show("Please select a Name before continuing");

e.Cancel = true;

}

}

}

Asif Shaikh  Tuesday, April 22, 2008 5:51 AM

Hi Davids Learning,

This exception is caused by reentering Cell in CellEnter event.

When you set CurrentCell in CellEnter event, it would cause the program enter Cell twice just as Asif Shaikh said. Actually, in the background, this problem is caused by calling SetCurrentCellAddressCore method twice in CellEnter event.

I would like to suggest you using BeginInvoke in RowEnter Event of DataGridView. BeginInvoke is used for executing code immediately and without interrupt. So it’s nice to set CurrentCell in BeginInvoke, thus you will not receive any reentrance exception.

Here is the solution:

Code Snippet

// Define a delegate for BeginInvoke.

public delegate void ChangeCellDelegate(DataGridViewCellEventArgs e);

//Call BeginInvoke in RowEnter and let it finish the job of setting CurrentCell.

private void dataGridView1_RowEnter(object sender, DataGridViewCellEventArgs e)

{

dataGridView1.BeginInvoke(new ChangeCellDelegate(ChangeCell), e);

}

// Delegate method used for setting CurrentCell.

private void ChangeCell(DataGridViewCellEventArgs e)

{

if (dataGridView1.Rows[e.RowIndex].Cells[2].Value == DBNull.Value)

{

dataGridView1.CurrentCell = dataGridView1.Rows[e.RowIndex].Cells[2];

MessageBox.Show(dataGridView1.Rows[e.RowIndex].Cells[2].Value.ToString());

dataGridView1.BeginEdit(false);

}

}

Hope it helps. If there is anything unclear, please feel free to let me know.

Best wishes,

Jun Wang

Jun Wang Tim  Friday, April 25, 2008 8:25 AM
You can do the following if you want to be very compact :


        private void dataGridViewPieces_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            DataGridView DGSender = (DataGridView)sender;

            if (DGSender.CurrentCell.ReadOnly)
            {
                System.Threading.Thread t = new System.Threading.Thread(new System.Threading.ThreadStart(() =>
                {
                    DGSender.Invoke(new 
                        Action(() => 
                            { 
                                //Code to execute here (example)
                                DGSender.CurrentCell = DGSender.Rows[e.RowIndex].Cells[e.ColumnIndex + 1]; 
                            }));

                }));

                t.Start();
            }
        }

I use this code to skip readonly cells when navigating with tab in datagridview
  • Proposed As Answer bySebastien g. Thursday, September 17, 2009 4:54 PM
  •  
Sebastien g.  Thursday, September 17, 2009 4:51 PM

You can use google to search for other answers

Custom Search

More Threads

• DatagridView With multicolumn Combobox
• grid dispay
• BindingSource Filter max lenght and stack overflow
• DataGridView with CheckBox - I'm stuck
• Column Size Persistence in Datagridview
• Two Controls Sharing Same Data Source Moves Both List Positions
• DataGridView Column Visible=False still visible.
• How to allow user to edit DataGridView column HeaderText
• passing parameters to tableadaptor from code
• Numeric Only Cell/Column in DataGridView