Eliminar objeto (metodo remove)

18/12/2006 - 16:08 por Hugo Gsell | Informe spam
Tengo una clase base que tiene un formulario con unos controles... y
programo que en el evento clic de un boton de ese formulario base se
eliminen ciertos objetos estos objetos estan dentro de un groupbox
Esta clase base la uso en otro proyecto... donde creo una clase nueva y como
primer linea pongo
inherits miclaseformbase
notese que utilizo removebykey... ya que probando directamente sobre un
formulario con remove no me funcionaba y con remve key si.

el código es como sigue:
Dim ctrl1 As Control
For Each d As System.Windows.Forms.Control In Me.Controls
If TypeOf d Is System.Windows.Forms.GroupBox Then
If Microsoft.VisualBasic.Left(d.Name, 9) = "GBDinamic" Then
For d1 As Integer = 0 To d.Controls.Count - 1
ctrl1 = d.Controls(d1)

If TypeOf ctrl1 Is TextBox Then
If Microsoft.VisualBasic.Left(CType(ctrl1,
TextBox).Name, 9) = "GbTextBox" Then
MsgBox(ctrl1.Name)
MyBase.Controls.RemoveByKey(ctrl1.Name)
End If
End If
If TypeOf ctrl1 Is ComboBox Then
If Microsoft.VisualBasic.Left(CType(ctrl1,
ComboBox).Name, 10) = "GbComboBox" Then
MsgBox(ctrl1.Name)
MyBase.Controls.RemoveByKey(ctrl1.Name)
End If
End If
If TypeOf ctrl1 Is Label Then
If Microsoft.VisualBasic.Left(CType(ctrl1,
Label).Name, 7) = "GbLabel" Then
MsgBox(ctrl1.Name)
MyBase.Controls.RemoveByKey(ctrl1.Name)
End If
End If

Next
End If
End If
Next
 

Leer las respuestas

#1 Carlos Gómez
18/12/2006 - 17:32 | Informe spam
Hugo Gsell ha escrito:

Tengo una clase base que tiene un formulario con unos controles... y
programo que en el evento clic de un boton de ese formulario base se
eliminen ciertos objetos estos objetos estan dentro de un groupbox
Esta clase base la uso en otro proyecto... donde creo una clase nueva y como
primer linea pongo
inherits miclaseformbase
notese que utilizo removebykey... ya que probando directamente sobre un
formulario con remove no me funcionaba y con remve key si.





Supongo que la pregunta es porque no funciona remove.

Bueno, el problema que tienes es que estas recorriendo una colección
de objetos, y a su vez estás eliminando objetos de esa colección. O
dicho de otra forma, tienes un bucle for:

For d1 As Integer = 0 To d.Controls.Count - 1

en el que los valores de d.Controls.Count - 1 varían sobre la marcha,
y lo que es peor, cuando eliminas un elemento,

ctrl1 = d.Controls(d1)

se desmadra "literalmente", ya que el elemento d.Controls(d1), es decir
el elemento que ocupa la posición d1, una vez eliminado ese elemento,
pasa a ser ocupado por el elemento que ocupaba la posicion d1+1, y en
la siguiente iteración del bucle, revisa el elemento d1+1 que antes de
eliminar el d1, ese era ocupado por d1+2... En fin, como te puedes
imaginar se hace un poco lioso seguir el flujo del programa.

Por tanto, tienes dos posibles soluciones, la más sencilla, es
recorrer la collección en sentido inverso, de modo que ahora no se
producen 'movimientos extraños' colaterales al eliminar un elemento de
la colección:

For d1 As Integer = d.Controls.Count -1 To 0 Step -1

y otra es realizar lo mismo pero haciendo uso de un While, que a mi
modo de ver es más elegante, porque la idea usar valores que varíen
en un bucle For (concretamente me refiero a d.Controls.Count - 1) no me
gusta nada (es cuestion de gustos)


Con respecto al código, piensate la posibilidad de crear controles
heredados que se ajusten a una Interfaz, ya que de ese modo el bucle
sería bastante más claro y más flexible:

Por ejemplo si defines una Interfaz llamada
IMisControlesDeFormularioComun:
Public Interface IMisControlesDeFormularioComun
Sub QuitameDeLaColeccion()
End Interface

y ahora por ejemplo para el TextBox
Public Class MiTextBox
Inherits TextBox
Implements IMisControlesDeFormularioComun

Public Sub QuitameDeLaColeccion()
Me.Parent.Controls.Remove(Me)
End Sub
End Class

ahora, el código central quedaría así

Dim i As Integer = d.Controls.Count - 1
While i>=0
If TypeOf d.Controls(i) Is IMisControlesDeFormularioComun

DirectCast(d.Controls(i),IMIsControlesDeFormularioComun).QuitameDeLaColeccion
End If
i -= 1
End While

que a mi me parece bastante más claro y conciso.

Preguntas similares