VB.NET: lo que sucedió con las matrices de control

click fraud protection

La omisión de las matrices de control de VB.NET es un desafío para quienes enseñan sobre matrices.

  • Ya no es posible simplemente copiar un control, como un cuadro de texto, y luego pegarlo (una o varias veces) para crear una matriz de control.
  • El código de VB.NET para crear una estructura similar a una matriz de control ha sido, en todos los libros de VB.NET que he comprado y en línea, mucho más largo y mucho más complejo. Carece de la simplicidad de codificar una matriz de control que se encuentra en VB6.

Si hace referencia a la biblioteca de compatibilidad VB6, hay objetos allí que actúan más o menos como matrices de control. Para ver a qué me refiero, simplemente use el asistente de actualización de VB.NET con un programa que contenga una matriz de control. El código es feo de nuevo, pero funciona. La mala noticia es que Microsoft no garantizará que los componentes de compatibilidad continúen siendo compatibles, y no se supone que los use.

El código VB.NET para crear y usar "matrices de control" es mucho más largo y mucho más complejo.

instagram viewer

Según Microsoft, para hacer algo incluso cercano a lo que puede hacer en VB 6 se requiere la creación de un "componente simple que duplique la funcionalidad de la matriz de control".

Necesita tanto una nueva clase como un formulario de alojamiento para ilustrar esto. La clase en realidad crea y destruye nuevas etiquetas. El código de clase completo es el siguiente:

Etiqueta de clase pública
Hereda el sistema. Colecciones CollectionBase
PrivateForm de solo lectura como _
Sistema. Windows Formas Formar
Función pública AddNewLabel () _
Como sistema. Windows Formas Etiqueta
'Crear una nueva instancia de la clase Label.
Dim aLabel como nuevo sistema. Windows Formas Etiqueta
'Agregar la etiqueta a la colección
'lista interna.
Yo. Lista. Añadir (aLabel)
'Agregar la etiqueta a la colección de controles
'del formulario al que hace referencia el campo HostForm.
HostForm. Control S. Añadir (aLabel)
'Establecer propiedades iniciales para el objeto Label.
una etiqueta. Superior = Cuenta * 25
una etiqueta. Ancho = 50
una etiqueta. Izquierda = 140
una etiqueta. Etiqueta = Yo Contar
una etiqueta. Texto = "Etiqueta" y yo. Contar. Encadenar
Regresar aLabel
Función final
Public Sub New (_
ByVal host como sistema. Windows Formas Formar)
HostForm = host
Yo. AddNewLabel ()
End Sub
Propiedad pública de solo lectura predeterminada _
Artículo (índice ByVal como entero) como _
Sistema. Windows Formas Etiqueta
Obtener
Devolver CType (Me. List. Artículo (índice), _
Sistema. Windows Formas Etiqueta)
End Get
Terminar propiedad
Public Sub Remove ()
'Verifique para asegurarse de que haya una etiqueta para eliminar.
Si yo. Cuenta> 0 Entonces
'Eliminar la última etiqueta agregada a la matriz
'de la colección de controles de formulario de host.
'Tenga en cuenta el uso de la propiedad predeterminada en
'accediendo a la matriz.
HostForm. Control S. Eliminar (Me (Me. Count - 1))
Yo. Lista. RemoveAt (Me. Count - 1)
Terminara si
End Sub
Clase final

Para ilustrar cómo se usaría este código de clase, puede crear un formulario que lo llame. Tendría que usar el código que se muestra a continuación en el formulario:

Formulario de clase pública 1. Hereda el sistema. Windows Formas Formar. #Region "Código generado por el Diseñador de formularios de Windows" 'También debe agregar la declaración:' MyControlArray = New LabelArray (Me) 'después de la llamada InitializeComponent () en el. 'código de región oculto. 'Declarar un nuevo objeto ButtonArray. Dim MyControlArray como LabelArray. Private Sub btnLabelAdd_Click (_. Remitente ByVal como sistema. Objeto, _. ByVal e como sistema. EventArgs) _. Asas btnLabelAdd. Hacer clic. 'Llame al método AddNewLabel. 'de MyControlArray. MyControlArray. AddNewLabel () 'Cambiar la propiedad BackColor. 'del Botón 0. MyControlArray (0) .BackColor = _. Sistema. Dibujo. Color. Rojo. End Sub. Private Sub btnLabelRemove_Click (_. Remitente ByVal como sistema. Objeto, _. ByVal e como sistema. EventArgs) _. Maneja btnLabelRemove. Hacer clic. 'Llame al método Remove de MyControlArray. MyControlArray. Eliminar() End Sub. Clase final

Primero, ¡esto ni siquiera hace el trabajo en Design Time como solíamos hacerlo en VB 6! Y segundo, no están en una matriz, están en una Colección VB.NET, algo muy diferente a una matriz.

La razón por la que VB.NET no admite la "matriz de control" de VB 6 es que no existe una "matriz" de "control" (tenga en cuenta el cambio de comillas). VB 6 crea una colección detrás de escena y la hace aparecer como una matriz para el desarrollador. Pero no es una matriz y tiene poco control sobre ella más allá de las funciones proporcionadas a través del IDE.

VB.NET, por otro lado, lo llama lo que es: una colección de objetos. Y le entregan las llaves del reino al desarrollador al crear todo al aire libre.

Como ejemplo del tipo de ventajas que esto le da al desarrollador, en VB 6 los controles tenían que ser del mismo tipo y tenían que tener el mismo nombre. Dado que estos son solo objetos en VB.NET, puede convertirlos en diferentes tipos y darles diferentes nombres y aún así administrarlos en la misma colección de objetos.

En este ejemplo, el mismo evento Click maneja dos botones y una casilla de verificación y muestra en cuál se hizo clic. ¡Haga eso en una línea de código con VB 6!

Private Sub MixedControls_Click (_
Remitente ByVal como sistema. Objeto, _
ByVal e como sistema. EventArgs) _
Botón de manijas 1.Haga clic en _
Button2.Click, _
CheckBox1.Click
'¡La siguiente declaración tiene que ser una declaración larga!
'Está en cuatro líneas aquí para mantenerlo angosto
'suficiente para caber en una página web
Label2.Text =
Microsoft VisualBasic. Derecha (remitente. GetType. Encadenar,
Len (remitente. GetType. Encadenar) -
(InStr (remitente. GetType. ToString, "Formularios") + 5))
End Sub

El cálculo de la subcadena es un poco complejo, pero no es realmente de lo que estamos hablando aquí. Podrías hacer cualquier cosa en el evento Click. Podría, por ejemplo, usar el Tipo de control en una instrucción If para hacer diferentes cosas para diferentes controles.

Comentarios de Frank's Computing Studies Group sobre matrices

Frank's Study Group proporcionó un ejemplo con un formulario que tiene 4 etiquetas y 2 botones. El botón 1 borra las etiquetas y el botón 2 las llena. Es una buena idea volver a leer la pregunta original de Frank y observar que el ejemplo que usó fue un bucle que se usa para borrar la propiedad Caption de una matriz de componentes Label. Aquí está el equivalente VB.NET de ese código VB 6. ¡Este código hace lo que Frank pidió originalmente!

Formulario de clase pública 1. Hereda el sistema. Windows Formas Formar. #Region "Código generado por el Diseñador de formularios de Windows" Dim LabelArray (4) como etiqueta. 'declara una serie de etiquetas. Private Sub Form1_Load (_. Remitente ByVal como sistema. Objeto, _. ByVal e como sistema. EventArgs) _. Maneja MyBase. Carga. SetControlArray () End Sub. Sub SetControlArray () LabelArray (1) = Etiqueta1. LabelArray (2) = Label2. LabelArray (3) = Label3. LabelArray (4) = Label4. End Sub. Private Sub Button1_Click (_. Remitente ByVal como sistema. Objeto, _. ByVal e como sistema. EventArgs) _. Botón de manijas 1. Haga clic en. 'Botón 1 Borrar matriz. Dim a As Integer. Para a = 1 a 4. LabelArray (a) .Text = "" Próximo. End Sub. Private Sub Button2_Click (_. Remitente ByVal como sistema. Objeto, _. ByVal e como sistema. EventArgs) _. Botón de manijas 2. Haga clic. 'Matriz de relleno del botón 2. Dim a As Integer. Para a = 1 a 4. LabelArray (a) .Text = _. "Matriz de control" y CStr (a) Próximo. End Sub. Clase final

Si experimenta con este código, descubrirá que además de establecer las propiedades de las Etiquetas, también puede llamar a los métodos. Entonces, ¿por qué yo (y Microsoft) nos tomamos tantas molestias para crear el código "Feo" en la Parte I del artículo?

Tengo que estar en desacuerdo con que es realmente una "matriz de control" en el sentido clásico de VB. La matriz de control VB 6 es una parte compatible de la sintaxis de VB 6, no solo una técnica. De hecho, tal vez la forma de describir este ejemplo es que es una matriz de controles, no una matriz de controles.

En la Parte I, me quejé de que el ejemplo de Microsoft SOLO funcionaba en tiempo de ejecución y no en tiempo de diseño. Puede agregar y eliminar controles de un formulario dinámicamente, pero todo tiene que implementarse en código. No puede arrastrar y soltar controles para crearlos como puede hacerlo en VB 6. Este ejemplo funciona principalmente en tiempo de diseño y no en tiempo de ejecución. No puede agregar y eliminar controles dinámicamente en tiempo de ejecución. En cierto modo, es todo lo contrario del ejemplo de la Parte I.

El clásico ejemplo de matriz de control VB 6 es el mismo que se implementa en el código VB .NET. Aquí en el código VB 6 (esto está tomado de Mezick & Hillier, Guía de examen de certificación de Visual Basic 6, p 206 - ligeramente modificado, ya que el ejemplo en el libro da como resultado controles que no se pueden ver):

Dim MyTextBox como VB.TextBox. IntNumber estático como entero. intNumber = intNumber + 1. Establecer MyTextBox = _. Yo. Control S. Agregar ("VB.TextBox", _. "Texto" e intNumber) MyTextBox. Texto = MyTextBox. Nombre. MyTextBox. Visible = Verdadero. MyTextBox. Izquierda = _. (intNumber - 1) * 1200

Pero como Microsoft (y yo) estamos de acuerdo, las matrices de control VB 6 no son posibles en VB.NET. Entonces, lo mejor que puede hacer es duplicar la funcionalidad. Mi artículo duplicó la funcionalidad encontrada en el ejemplo de Mezick & Hillier. El código del Grupo de estudio duplica la funcionalidad de poder establecer propiedades y métodos de llamada.

Entonces, la conclusión es que realmente depende de lo que quieras hacer. VB.NET no tiene todo incluido como parte del lenguaje, aún así, pero en última instancia es mucho más flexible.

La toma de control de John Fannon sobre matrices

John escribió: necesitaba matrices de control porque quería poner una tabla simple de números en un formulario en tiempo de ejecución. No quería las náuseas de colocarlos todos individualmente y quería usar VB.NET. Microsoft ofrece una solución muy detallada a un problema simple, pero es un mazo muy grande para romper una tuerca muy pequeña. Después de experimentar un poco, finalmente encontré una solución. Así es como lo hice.

El ejemplo de Acerca de Visual Basic anterior muestra cómo puede crear un cuadro de texto en un formulario creando una instancia del objeto, estableciendo propiedades y agregándolo a la colección Controls que forma parte del Formulario objeto.

Dim txtDataShow As New TextBox
txtDataShow. Altura = 19
txtDataShow. Ancho = 80
txtDataShow. Ubicación = Nuevo punto (X, Y)
Yo. Control S. Agregar (txtDataShow)
Aunque la solución de Microsoft crea una Clase, razoné que sería posible incluir todo esto en una subrutina. Cada vez que llama a esta subrutina, crea una nueva instancia del cuadro de texto en el formulario. Aquí está el código completo:

Formulario de clase pública1
Hereda el sistema. Windows Formas Formar

#Region "Código generado por el Diseñador de formularios de Windows"

Private Sub BtnStart_Click (_
Remitente ByVal como sistema. Objeto, _
ByVal e como sistema. EventArgs) _
Manijas btnStart. Hacer clic

Dim I como entero
Dim sData As String
Para I = 1 a 5
sData = CStr (I)
Llame a AddDataShow (sData, I)
próximo
End Sub
Sub AddDataShow (_
ByVal sText As String, _
ByVal I como entero)

Dim txtDataShow As New TextBox
Dim UserLft, UserTop como entero
Dim X, Y como entero
UserLft = 20
UserTop = 20
txtDataShow. Altura = 19
txtDataShow. Ancho = 25
txtDataShow. TextAlign = _
Alineación horizontal. Centrar
txtDataShow. BorderStyle = _
Estilo de borde. Fijo simple
txtDataShow. Texto = sText
X = UserLft
Y = UserTop + (I - 1) * txtDataShow. Altura
txtDataShow. Ubicación = Nuevo punto (X, Y)
Yo. Control S. Agregar (txtDataShow)
End Sub
Clase final
Muy buen punto, John. Esto es ciertamente mucho más simple que el código de Microsoft... así que me pregunto por qué insistieron en hacerlo de esa manera.

Para comenzar nuestra investigación, intentemos cambiar una de las asignaciones de propiedad en el código. Cambiemos

txtDataShow. Altura = 19
a

txtDataShow. Altura = 100
solo para asegurarse de que haya una diferencia notable.

Cuando volvemos a ejecutar el código, obtenemos... Whaaaat??? ... la misma cosa. No hay cambio en absoluto. De hecho, puede mostrar el valor con una declaración como MsgBox (txtDataShow. Altura) y aún obtiene 20 como valor de la propiedad sin importar lo que le asigne. ¿Por qué pasa eso?

La respuesta es que no estamos derivando nuestra propia Clase para crear los objetos, solo estamos agregando cosas a otra Clase, así que tenemos que seguir las reglas de la otra clase. Y esas reglas establecen que no puede cambiar la propiedad Altura. (Wellllll... usted puede. Si cambia la propiedad Multilínea a Verdadero, puede cambiar la Altura).

¿Por qué VB.NET sigue adelante y ejecuta el código sin siquiera un gemido de que podría haber algo mal cuando, de hecho, ignora por completo su declaración? Sin embargo, podría sugerir al menos una advertencia en la compilación. (¡Insinuación! ¡Insinuación! ¡Insinuación! ¿Microsoft está escuchando?)

El ejemplo de la Parte I hereda de otra Clase, y esto hace que las propiedades estén disponibles para el código en la Clase heredada. Cambiar la propiedad Altura a 100 en este ejemplo nos da los resultados esperados. (De nuevo... un descargo de responsabilidad: cuando se crea una nueva instancia de un componente Label grande, cubre el anterior. Para ver realmente los nuevos componentes de Label, debe agregar el método llamado aLabel. Traer al frente().)

Este simple ejemplo muestra que, aunque PODEMOS simplemente agregar objetos a otra Clase (y a veces esto es lo correcto), el control de programación sobre los objetos requiere que los derivemos en una clase y la forma más organizada (¿me atrevo a decir, "la forma .NET"?) es crear propiedades y métodos en la nueva clase derivada para cambiar cosas. John no se convenció al principio. Dijo que su nuevo enfoque se adapta a su propósito a pesar de que existen limitaciones de no ser "COO" (Orientado correctamente a objetos). Más recientemente, sin embargo, John escribió:

"... Después de escribir un conjunto de 5 cuadros de texto en tiempo de ejecución, quería actualizar los datos en una parte posterior del programa, pero nada cambió, los datos originales todavía estaban allí.

Descubrí que podía solucionar el problema escribiendo código para quitar los cuadros antiguos y volviéndolos a poner con datos nuevos. Una mejor manera de hacerlo sería usarme. Actualizar. Pero este problema me ha llamado la atención sobre la necesidad de proporcionar un método para restar los cuadros de texto y agregarlos ".

El código de John utilizó una variable global para realizar un seguimiento de cuántos controles se habían agregado al formulario, por lo que un método ...

Private Sub Form1_Load (_
Remitente ByVal como sistema. Objeto, _
ByVal e como sistema. EventArgs) _
Maneja MyBase. Carga
CntlCnt0 = Me. Control S. Contar
End Sub

Entonces el "último" control podría eliminarse ...

N = yo. Control S. Cuenta - 1
Yo. Control S. RemoveAt (N)
John señaló que "tal vez esto sea un poco torpe".

Es la forma en que Microsoft realiza un seguimiento de los objetos en COM Y en su código de ejemplo "feo" anterior.

Ahora he vuelto al problema de crear dinámicamente controles en un formulario en tiempo de ejecución y he estado mirando nuevamente los artículos 'Qué pasó con las matrices de control'.

He creado las clases y ahora puedo colocar los controles en el formulario de la manera que quiero que sean.

John demostró cómo controlar la ubicación de los controles en un cuadro de grupo usando las nuevas clases que ha comenzado a usar. ¡Quizás Microsoft tenía razón en su solución "fea" después de todo!

instagram story viewer