Estoy tratando de poner una DataGridViewComboBoxCell en una DataGridView
pero cuando la fila y la columna son iguales se cae entregando el siguiente
error:
"Operation is not valid because it results in a reentrant call to the
SetCurrentCellAddressCore function."
Alguien sabe como solucionar este problema?
Muchas Gracias.
Atte.
pev
Sin saber lo que estás haciendo, y cómo lo estás haciendo, para que obtengas
ese mensaje de error, es un poco complicado intentar solucionar el problema.
¿Qué quieres decir «cuando la fila y la columna son iguales»?
Cuando se obtiene ese error, generalmente es debido a que estás ejecutando
el código fuente en un evento que se desencadena cada vez que se modifica,
explícita o implícitamente, la propiedad «CurrentCell» del control
DataGridView, por lo que el evento no pararía de desencadenarse. Si éste es
tu caso, deberás de procurar establecer el valor de la propiedad
«CurrentCell» fuera de cualquier evento del control DataGridView que
conlleve llamadas reentrantes al mismo procedimiento de evento.
Insisto en que no quiero decir que tú expresamente establezcas el valor de
la propiedad «CurrentCell». Puede darse el caso que el código fuente que se
está ejecutando, modifique indirectamente el valor de la mencionada
propiedad.
--
Enrique Martínez
[MS MVP - VB]
Nota informativa: La información contenida en este mensaje, así como el
código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin
garantías de ninguna clase, y no otorga derecho alguno. Usted asume
cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o
sugerido en el presente mensaje.
Quería decir que NO CONLLEVE llamadas reentrantes al mismo procedimiento de
evento.
--
Cuando me posiciono en la fila 3,columna 3 de la grilla.
en todo caso estube buscando en internet y este error es bastante
recurrente......
Otra Vez: ¿alguien que le hayya ocurrido lo ha solucionado?
Gracias.
Atte.
pev
Porque te posiciones en dicha celda, no es motivo para que obtengas el error
que nos comentas. En condicones normales no tienes por qué obtener el error
"La operación no es válida porque origina una llamada reentrante a la
función SetCurrentCellAddressCore" cuando te posicionas en la fila 3 columna
3, o en la fila 5 columna 5, o en cualquier otra celda del control
DataGridView.
> en todo caso estube buscando en internet y este error es bastante
> recurrente......
Es bastante frecuente en aquellos proyectos donde el código fuente
indirectamente está efectuando de una manera constante llamadas a la función
SetCurrentCellAddressCore. Si deseas provocar el error, simplemente tienes
que seleccionar la celda actual en el evento «RowEnter» del control
DataGridView de la siguiente manera:
Private Sub DataGridView1_RowEnter(ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.RowEnter
If Me.DataGridView1.CurrentCell Is Nothing Then Return
Me.DataGridView1.CurrentCell = _
Me.DataGridView1.Rows(3).Cells(3)
End Sub
Pero no se produce simplemente porque te posiciones en la fila 3 columna 3,
porque también sucede cuando te posiciones en cualquier otra celda.
> Otra Vez: ¿alguien que le haya ocurrido lo ha solucionado?
A mí no me ha ocurrido, pero en mi anterior mensaje ya te he comentado lo
que tienes que procurar evitar para que no se produzca dicho error: procurar
establecer el valor de la propiedad «CurrentCell» fuera de cualquier evento
del control DataGridView que no conlleve llamadas reentrantes al mismo
procedimiento de evento.
Continuando con el ejemplo anterior, evitaríamos el error ejecutando el
código de la siguiente manera:
Private Sub DataGridView1_RowEnter(ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.RowEnter
If Me.DataGridView1.CurrentCell Is Nothing Then Return
' Eliminamos la selección de la celda actual.
'
Me.DataGridView1.Rows(e.RowIndex).Selected = False
' Cuando seleccionemos una fila, quedar seleccionada
' la celda correspondiente a su cuarta columna.
'
Dim textBoxCell As DataGridViewTextBoxCell = _
TryCast(Me.DataGridView1.Item(3, e.RowIndex), _
DataGridViewTextBoxCell)
textBoxCell.Selected = True
End Sub
Pero, en fín, como todavía no has dicho lo que estás haciendo y cómo lo
estás haciendo, pues ignoro cómo te puedo ayudar para evitar el error.
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Me.DataGridView1.Rows.Add(4)
End Sub
Private Sub DataGridView1_CellEnter(ByVal sender As Object, ByVal e As
System.Windows.Forms.DataGridViewCellEventArgs) Handles
DataGridView1.CellEnter
Dim COMBO = New DataGridViewComboBoxCell
Debug.WriteLine(e.ColumnIndex.ToString & " " & e.RowIndex.ToString)
If (e.ColumnIndex = 3) Then
DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
End If
End Sub
End Class
Y este es el resultado:
0 0
0 0
1 0
2 0
3 0
3 1
3 2
3 3
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
y me da el error ya conocido.
Saludos
pev.
> Private Sub DataGridView1_CellEnter( ...)
>
> Dim COMBO = New DataGridViewComboBoxCell
> Debug.WriteLine(e.ColumnIndex.ToString & " " & e.RowIndex.ToString)
> If (e.ColumnIndex = 3) Then
> DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
> End If
> End Sub
Tal y como te indiqué en mis anteriores mensajes, es normal que obtengas el
error que estás obteniendo, porque en el evento «CellEnter» le estás
indicando que se sitúe en una determinada celda cuando el valor de
«ColumnIndex» sea igual a 3, por lo que el evento «CellEnter» no pararía de
ejecutarse, de ahí que obtengas la excepción "La operación no es válida
porque origina una llamada reentrante a la función
SetCurrentCellAddressCore", y se produce cuando entras en la celda 3 - 3,
porque así se lo estás indicando:
> If (e.ColumnIndex = 3) Then
> DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
> End If
Le estás diciendo que cuando el índice de la columna sea 3 se establezca en
la celda situada en la intersección de la fila 3 y la columna 3, que
precisamente es donde se encuentra situada la celda actual del control
DataGridView, es decir, el valor devuelto por la propiedad CurrentCell, por
tanto, como lo estás ejecutando dentro del evento «CellEnter», éste evento
no pararía de ejecutarse, de ahí que obtengas el error.
Si al código le quitaras
If (e.ColumnIndex = 3) Then
Entonces obtendrías el error cada vez que seleccionaras cualquier celda.
La solución pasa por ejecutar el código fuera de cualquier evento que no
produzca llamadas reentrantes al mismo procedimiento de evento que está
ejecutando el código, tal y como así te indiqué en mi primera respuesta.
(columna, fila
0, 0
0, 0
1, 0
2, 0
3, 0 (columna=3, fila=0) no pasa nada
3, 1 (columna=3, fila=1) no pasa nada
3, 2 (columna=3, fila=2) no pasa nada
3, 3 (columna=3, fila=0) SOLO EN ESTA CELDA SE CAE!!!!!!!
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
Gracias.
pev
> y entonces por qué no da el error en las demás filas de la misma columna?
¡Jeje! Seguramente, no he sabido explicarme bien.
¡Vamos a ver! Ejecuta el código de la siguiente manera, y observarás que en
todas las celdas obtendrás el mismo error. ¡Es más! Vas a obtener el error
una vez que pulses F5, es decir, cuando inicies la ejecución del código en
el IDE de Visual Studio:
Private Sub DataGridView1_CellEnter( _
ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
Dim COMBO = New DataGridViewComboBoxCell
Debug.WriteLine(e.ColumnIndex.ToString & " " & e.RowIndex.ToString)
' If (e.ColumnIndex = 3) Then
DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
' End If
End Sub
Una vez que observes que obtienes el error nada más iniciar la depuración
del proyecto, elimina los comentarios de las líneas If ... End If, y
observarás que entonces sólo se produce la excepción cuando seleccionas la
celda 3-3, porque TÚ MISMO LE ESTÁS DICIENDO QUE ASÍ SEA:
If (e.ColumnIndex = 3) Then
Es decir, cuando el índice de la columna sea 3 ejecuta
DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
La excepción ÚNICAMENTE SE PRODUCIRÁ cuando el índice de la celda sea Fila
3, Columna 3, que se corresponde con la celda que ACTUALMENTE se encuentra
seleccionada, es decir, cuando el valor de la propiedad «CurrentCell» sea
ColumnIndex = 3 y RowIndex = 3; no se producirá el error cuando el índice de
la fila (RowIndex) sea distinto de 3, aunque el índice de la columna sea 3,
ya que le estás indicando el valor de la variable objeto COMBO, que tal y
como se encuentra definida en el evento «CellEnter», el índice de sus
propiedades RowIndex y ColumnIndex son -1, por tanto, ¿donde deseas que se
sitúe la celda situada en la intersección de la columna y la fila con los
índices -1?
Realmente no sé el motivo de utilizar la propiedad «Item» con un valor
«DataGridViewComboBoxCell». Si tu intención es seleccionar una celda en
concreto, para eso está la propiedad «CurrentCell» del control DataGridView.
Por ejemplo, en el mismo evento «CellEnter» puedes ejecutar lo siguiente,
aunque poco sentido tiene ejecutarlo en dicho evento:
Private Sub DataGridView1_CellEnter( _
ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
If Me.DataGridView1.CurrentCell Is Nothing Then Return
' Eliminamos la selección de la celda actual.
'
Me.DataGridView1.Rows(e.RowIndex).Selected = False
' Cuando seleccionemos una fila, quedará seleccionada
' la celda correspondiente a su cuarta columna.
'
Dim textBoxCell As DataGridViewTextBoxCell = _
TryCast(Me.DataGridView1.Item(3, e.RowIndex), _
DataGridViewTextBoxCell)
If textBoxCell IsNot Nothing Then
textBoxCell.Selected = True
End If
End Sub
Digo que tiene poco sentido, porque estarás seleccionando la misma celda que
actualmente se encuentra seleccionada. Este código es para ejecutarlo fuera
del evento «CellEnter», porque este evento se produce cuando cambia el valor
de la celda actual, o cuando el control DataGridView recibe el foco de
entrada.
Eso es verdad, ya que la primera celda que toma la grilla al iniciar es la
0,0 (condición que puse en el primer post "cuando la fila y la columna son
iguales, se cae".
Este es el codigo que probé ahora:
Public Class Form1
Private Sub DataGridView1_CellEnter( _
ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
Dim COMBO = New DataGridViewComboBoxCell
Try
Debug.WriteLine(e.ColumnIndex.ToString & " " &
e.RowIndex.ToString)
' If (e.ColumnIndex = 3) Then
DataGridView1.Item(e.ColumnIndex, e.RowIndex) = COMBO
' End If
Catch ex As Exception
Debug.WriteLine(ex.Message.ToString.Trim)
Finally
End Try
End Sub
Private Sub Form1_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles
Me.Load
Me.DataGridView1.Rows.Add(4)
End Sub
End Class
Y este es su resultado:
0 0
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
La operación no es válida porque origina una llamada reentrante a la función
SetCurrentCellAddressCore.
0 0
0 0
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
La operación no es válida porque origina una llamada reentrante a la función
SetCurrentCellAddressCore.
1 0
2 0
3 0
0 1
1 1
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
La operación no es válida porque origina una llamada reentrante a la función
SetCurrentCellAddressCore.
2 1
3 1
0 2
1 2
2 2
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
La operación no es válida porque origina una llamada reentrante a la función
SetCurrentCellAddressCore.
3 2
0 3
1 3
2 3
3 3
A first chance exception of type 'System.InvalidOperationException' occurred
in System.Windows.Forms.dll
La operación no es válida porque origina una llamada reentrante a la función
SetCurrentCellAddressCore.
Como puedes seguir observando el error sólo se produce cuando la fila y
columna son iguales.
¿Existe solución para este problema?
Atte.
pev
> Como puedes seguir observando el error sólo se produce cuando
> la fila y columna son iguales.
¡Yo, me rindo! ¡Me doy por vencido! :-(
> ¿Existe solución para este problema?
Sí, no efectuar llamadas reentrantes. No sé si es la tercera o cuarta vez
que te digo que procures establecer el valor de la propiedad «CurrentCell»
fuera de cualquier evento del control DataGridView que no conlleve llamadas
reentrantes al mismo procedimiento de evento.
Pero, ¡nada! Como parece ser que te empeñas en utilizar el evento
«CellEnter» para establecer el valor de la propiedad «Item», no pararás de
obtener la excepción «la operación no es válida porque origina una llamada
reentrante a la función SetCurrentCellAddressCore».
Ignoro si existe una solución para lo que pretendes hacer sin obtener la
excepción comentada.
La única solución que veo por ahora para no obtener la excepción, pasa por
especificar expresamente la propiedad «Value» de la variable objeto COMBO a
la propiedad «Value» de la propiedad «Item» del control DataGridView:
Private Sub DataGridView1_CellEnter( _
ByVal sender As Object, _
ByVal e As DataGridViewCellEventArgs) _
Handles DataGridView1.CellEnter
Dim COMBO = New DataGridViewComboBoxCell
Debug.WriteLine(e.ColumnIndex.ToString & " " & e.RowIndex.ToString)
If (e.ColumnIndex = 3) Then
DataGridView1.Item(e.ColumnIndex, e.RowIndex).Value = _
COMBO.Value
End If
End Sub
Pero, ¡claro! Como la variable objeto COMBO no tiene ningún valor, el valor
de la celda será «Nothing». Su tuviera un valor adecuado a los elementos
existentes en la columna tipo ComboBox, le podrías asignar un valor a la
propiedad «Value» de cualquier elemento existente:
COMBO.Value = "Valor elemento existente en la columna ComboBox."
Por ahora, no veo otra solución, salvo que digas claramente qué es lo que
realmente deseas hacer.