You are on page 1of 167

layo

http://www.cuatrovientos.org
Autoras: Mara Martn y Susana Moreno
Emails: maria_martin@cuatrovientos.org
susana_moreno@cuatrovientos.org
Mdulo: Programacin

Desarrollo de Aplicaciones Multiplataforma

Cap 1. Introduccin a VB.Net .................................................................................... 9


Qu es la plataforma .NET? .............................................................................................. 9
.Net Framework ................................................................................................................. 9
Visual Studio .NET .......................................................................................................... 10
Visual Basic.Net .............................................................................................................. 11
Explorando el entorno de desarrollo. Nuestra primera aplicacin .................................. 11
Mens y Barras de herramientas .................................................................................. 13
Cuadro de herramientas ............................................................................................... 14
Diseador de Windows Forms ..................................................................................... 14
Ventana de Propiedades .............................................................................................. 15
Eventos: acciones que se producen sobre los controles .................................................... 17
Editor de cdigo .......................................................................................................... 17

Cap 2. Formularios y controles ................................................................................ 21


Introduccin ...................................................................................................................... 21
Propiedades, mtodos y eventos de un formulario ........................................................... 22
Propiedades ..................................................................................................................... 22
Mtodos ........................................................................................................................... 24
Eventos ............................................................................................................................ 24
Controles ms habituales .................................................................................................. 25
Button.............................................................................................................................. 25
Label ............................................................................................................................... 26
TextBox ........................................................................................................................... 27
Foco de entrada ........................................................................................................... 27
Control de entrada en las cajas de texto. Eventos KeyPress y TextChanged ................. 28
Seleccin de texto en un TextBox ............................................................................... 30
CheckBox ........................................................................................................................ 32
RadioButton y GroupBox ................................................................................................ 33
ListBox ............................................................................................................................ 35
ComboBox ...................................................................................................................... 39
PictureBox ....................................................................................................................... 40
Anclaje de controles........................................................................................................... 42
Acople de controles ............................................................................................................ 42
Orden de tabulacin de controles ..................................................................................... 43

Cap 3. El lenguaje ..................................................................................................... 45


Variables, definicin y entorno ......................................................................................... 45
Notacin Camel ............................................................................................................... 45
Tipos de datos primitivos .................................................................................................. 46
Declaracin mltiple en lnea ....................................................................................... 47
Asignacin de valor ..................................................................................................... 47
Valor inicial ................................................................................................................ 48
mbito de las variables ..................................................................................................... 49
Perodo de vida o duracin de las variables ...................................................................... 50

VB.Net (ndice)

Pg. 3

Desarrollo de Aplicaciones Multiplataforma

Constantes.......................................................................................................................... 50
Alcance de las constantes definidas por el usuario ....................................................... 51
Operadores ........................................................................................................................ 51
Diferencia entre And y AndAlso as como entre Or y OrElse ....................................... 52
Prioridad de operadores ............................................................................................... 53
Uso de parntesis para alterar la prioridad de operadores ............................................. 53
Comentarios ....................................................................................................................... 54
Instrucciones en VB.Net .................................................................................................... 54
Asignacin (=) y operadores abreviados +=, *=, -=. /=, &= .............................................. 55
Instruccin Condicional simple y mltiple: If ................................................................... 55
Condicional mltiple: Select Case .................................................................................... 56
Usando la Select Case para determinar los botones chequeados ................................... 58
Bucles While..Wend y Do..Loop ....................................................................................... 58
Bucle For ........................................................................................................................ 59
Declaracin de variables a nivel de bloque ....................................................................... 60
Manejo de excepciones: Bloque Try..Catch ...................................................................... 61
Bloque Try....................................................................................................................... 61
Bloque Catch ................................................................................................................... 61
Varias capturas de errores en un mismo bloque Try/Catch ................................................ 62
Bloque Finally ................................................................................................................. 62
Lanzar una excepcin por cdigo...................................................................................... 63

Cap 4. Funciones estndar y mtodos de interes ..................................................... 65


Funciones del lenguaje ...................................................................................................... 65
Requerir datos con InputBox ............................................................................................ 65
Visualizar datos mediante la clase MessageBox ............................................................... 66
Funciones de conversiones de tipos ................................................................................... 68
CByte, CDate, ............................................................................................................. 68
Clase Convert .................................................................................................................. 69
Int y Fix ........................................................................................................................... 69
Funciones y contantes matemticas. Clase Math.............................................................. 69
Constantes Pi y E ............................................................................................................. 69
Floor y Ceiling ................................................................................................................. 70
Sqrt.................................................................................................................................. 70
Abs .................................................................................................................................. 71
Logaritmos: Log, Log10 .................................................................................................. 72
Exp .................................................................................................................................. 72
Funciones de comprobacin de tipos de datos .................................................................. 73
Fechas ................................................................................................................................ 73
Funciones de fechas: Mdulo DateAndTime y mtodos de datos de tipo fecha............... 73
Propiedades ..................................................................................................................... 74
Mtodos ........................................................................................................................... 74
Mtodos ms utilizados de datos de tipo fecha.................................................................. 75
Mtodos de la clase String y de variables de tipo cadena ................................................. 77

VB.Net (ndice)

Pg. 4

Desarrollo de Aplicaciones Multiplataforma

String.Compare ................................................................................................................ 77
Longitud y caracteres de una cadena ................................................................................ 78
Ver si una cadena est includa en otra: Contains, IndexOf, StartsWith y EndWith ........... 78
Manipular cadenas: SubString, Remove, Replace, Insert, Trim, ToUpper y ToLower ....... 79
Creacin de nmeros aleatorios ........................................................................................ 79

Cap 5. Procedimientos y funciones: Sub y Function................................................ 81


Qu son los procedimientos? ........................................................................................... 81
mbito de los procedimientos ........................................................................................... 82
Funciones (Function) ......................................................................................................... 82
Sintaxis en la definicin de una funcin ........................................................................... 82
Llamada a una funcin ..................................................................................................... 84
Procedimientos (Sub)......................................................................................................... 84
Sintaxis que define un procedimiento Sub ........................................................................ 84
Llamada a un procedimiento Sub ..................................................................................... 85
Cmo declarar argumentos en los procedimientos ........................................................... 85
Declarar argumentos ........................................................................................................ 85
Paso por valor (ByVal) ................................................................................................ 85
Paso por referencia (ByRef) ........................................................................................ 86
Resumen del paso ByVal y ByRef.................................................................................... 88
Paso de parmetros por posicin y por nombre. Parmetros opcionales.............................. 88
Sobrecarga de procedimientos: Overloads ........................................................................ 89

Cap 6. Programacin orientada a objetos (OOP) .................................................... 91


Fundamentos de la Programacin Orientada a Objetos (OOP) ...................................... 91
Objeto.............................................................................................................................. 91
Clase................................................................................................................................ 91
Instancias de una clase ..................................................................................................... 92
Creando la clase ................................................................................................................. 92
Miembros de la clase ......................................................................................................... 93
Propiedades ..................................................................................................................... 93
Mtodos ........................................................................................................................... 95
Propiedad o mtodo? Propiedades que no tienen variable asociada............................. 96
Definiendo y creando objetos a partir de la clase ............................................................. 97
Uso de las propiedades y/o mtodos ................................................................................. 98
Mtodos constructores ....................................................................................................... 99
Sobrecarga de mtodos o polimorfismo, en una misma clase......................................... 101
Caractersticas bsicas de un sistema orientado a objeto ............................................... 102
Abstraccin.................................................................................................................... 102
Encapsulacin ................................................................................................................ 103
Polimorfismo ................................................................................................................. 103
Herencia ........................................................................................................................ 103
Jerarquas de clases ........................................................................................................ 104
Relaciones entre objetos ................................................................................................. 105

VB.Net (ndice)

Pg. 5

Desarrollo de Aplicaciones Multiplataforma

Herencia ................................................................................................................... 105


Pertenencia ............................................................................................................... 105
Utilizacin ................................................................................................................ 105
Reutilizacin ............................................................................................................. 105

Cap 7. Arrays y Colecciones ................................................................................... 107


Arrays o Matrices ............................................................................................................ 107
Declaracin.................................................................................................................... 107
Asignar y recuperar el valor a/de un elemento del array.................................................. 108
Averiguar los elementos de un array............................................................................... 108
Inicializar el array al declararlo ...................................................................................... 108
Cambiar el tamao: ReDim ............................................................................................ 109
Cambiar el tamao conservando sus valores .............................................................. 110
Eliminar su contenido .................................................................................................... 110
Inicializar los valores de sus elementos .......................................................................... 111
Copiar un array en otro .................................................................................................. 111
Crear un array al vuelo ............................................................................................... 112
Otros mtodos interesantes de arrays .............................................................................. 112
Clase Array.................................................................................................................... 113
Mtodos que crean arrays ............................................................................................... 116
Crear una cadena a partir de un array.............................................................................. 117
Arrays de objetos ........................................................................................................... 117
Declaracin e inicializacin de un array de objetos .................................................... 117
Miembros que son arrays (Propiedades o Mtodos) ................................................... 117
Colecciones....................................................................................................................... 120
Operaciones con una coleccin. ..................................................................................... 120
Tipos de coleccin. ........................................................................................................ 120
Uso del bucle For Each para las colecciones o arrays...................................................... 120
Coleccin de tems en las ListBox, ComboBox, ......................................................... 122
Colecciones de solo lectura. Ejemplo: coleccin de formularios abiertos en la aplicacin 123
Coleccin de controles ................................................................................................... 124
Agregar controles a un formulario o control en tiempo de ejecucin. Add y AddRange
................................................................................................................................. 125
Eliminar un control: Remove, RemoveAt y RemoveByKey ....................................... 127
Eliminar todos los controles: Clear ............................................................................ 127
Eliminar controles de forma selectiva: bucle descendente .......................................... 127
Busqueda de un control en la coleccin de los controles ............................................ 128
Copiar la coleccin en un array ................................................................................. 129
Creando nuestras propias colecciones ............................................................................ 130
La clase ArrayList.......................................................................................................... 131
Instanciacin de objetos ArrayList............................................................................. 131
Clases que vamos a usar para los siguientes ejemplos: ............................................... 132
Inicializadores de una coleccin: From ...................................................................... 132
Agregar valores a un ArrayList: Add, AddRange, Insert, InsertRange y SetRange ..... 133
El tipo de datos de almacenamiento en un ArrayList: GetType .................................. 134
Obtencin de subarrays a partir de un objeto ArrayList: GetRange, FixedSize, Repeat,
ToArray, ReadOnly ................................................................................................... 134
Bsquedas en colecciones ArrayList: Contains, IndexOf y LastIndexOf .................... 136
Borrado de elementos en una coleccin ArrayList: Remove, RemoveAt, RemoveRange
y Clear ...................................................................................................................... 137
Ordenar elementos en un objeto ArrayList: Sort y Reverse ........................................ 137
ArrayList de objetos .................................................................................................. 138

VB.Net (ndice)

Pg. 6

Desarrollo de Aplicaciones Multiplataforma

Colecciones generic ....................................................................................................... 139


List (Of T) ................................................................................................................ 139
Dictionary (Of TKey, TValue) .................................................................................. 140

Cap 8. Herencia ....................................................................................................... 141


Jerarquas de clases ......................................................................................................... 141
Todas las clases necesitan una clase base ........................................................................ 142
Reglas de mbito especficas para clases ......................................................................... 143
Protected........................................................................................................................ 143
Friend ............................................................................................................................ 143
Protected Friend ............................................................................................................. 144
Herencia y sobrecarga de mtodos .................................................................................. 144
Herencia y sobre-escritura de mtodos ........................................................................... 144
MyBase, acceso a los mtodos de la clase base ................................................................ 145
Herencia y mtodos constructores .................................................................................. 146
Clases selladas o no heredables ....................................................................................... 147
Clases abstractas o no instanciables ................................................................................ 148
Resumiendo ..................................................................................................................... 149

Cap 9. Eventos en .NET .......................................................................................... 151


Un escenario de trabajo sin eventos ................................................................................ 151
Programacin basada en eventos .................................................................................... 151
Esquema bsico de un sistema orientado a eventos ........................................................ 152
El emisor de eventos ........................................................................................................ 152
El receptor de eventos ..................................................................................................... 153
Conexin de un emisor de eventos con un manipulador de eventos .............................. 153
Enlace esttico de eventos .............................................................................................. 154
Enlace dinmico de eventos ........................................................................................... 154
La clase EventArgs, o cmo obtener informacin del objeto emisor del evento ............ 155

Cap 10. Ficheros...................................................................................................... 159


Clases StreamReader y StreamWriter ............................................................................ 159
Clase File .......................................................................................................................... 161
Carpeta del proyecto ....................................................................................................... 162

Cap 11. Varias intancias de un formulario. Formularios Mdi .............................. 163


Aplicaciones de estilo SDI ............................................................................................... 163
Aplicaciones Mdi ............................................................................................................. 163
Creacin de un formulario MDI ..................................................................................... 163
Creacin de formularios hijos o MDI secundarios ......................................................... 163
Colecciones de formularios hijos: MdiChildren ............................................................. 164

VB.Net (ndice)

Pg. 7

Desarrollo de Aplicaciones Multiplataforma

Formulario activo: ActiveMdiChild................................................................................ 165


Organizacin de los formularios secundarios en el MDI ................................................ 166
Creacin de varias instancias de un fomulario ............................................................... 166
Coleccin de formularios abiertos: OpenForms ............................................................. 166

VB.Net (ndice)

Pg. 8

Desarrollo de Aplicaciones Multiplataforma

Cap 1. Introduccin a VB.Net


Qu es la plataforma .NET?
.NET es toda una arquitectura tecnolgica, desarrollada por Microsoft para la creacin y
distribucin del software como un servicio. Esto quiere decir, que mediante las herramientas de
desarrollo proporcionadas por esta nueva tecnologa, los y las programadoras podrn crear
nuevas y personales aplicaciones.
Las caractersticas principales que conforman .NET son las siguientes:
La plataforma .NET Framework, que proporciona la infraestructura para crear
aplicaciones y el entorno de ejecucin para las mismas.
Los productos de Microsoft enfocados hacia .NET, entre los que se encuentran
Windows.NET Server, como sistema operativo que incluir de forma nativa la
plataforma .NET Framework; Visual Studio .NET, como herramienta integrada para
el desarrollo de aplicaciones; Office .NET; etc.
Servicios para .NET desarrollados por terceros fabricantes, que podrn ser utilizados
por otras aplicaciones que se ejecuten en Internet.

.Net Framework
.NET Framework constituye la plataforma y elemento principal sobre el que se asienta
Microsoft .NET. De cara al programador o programadora, es la pieza fundamental de todo este
nuevo modelo de trabajo, ya que proporciona las herramientas y servicios que necesitar en su
labor habitual de desarrollo.
.NET Framework permite el desarrollo de aplicaciones a travs del uso de un conjunto de
herramientas y servicios que proporciona, y que pueden agruparse en tres bloques principales: el
Entorno de Ejecucin Comn o Common Language Runtime (CLR a partir de ahora); la
jerarqua de clases bsicas de la plataforma o .NET Framework Base Classes; y el motor de
generacin de interfaz de usuari@, que permite crear interfaces para la web o para el tradicional
entorno Windows, as como servicios para ambos entornos operativos.

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 9

Desarrollo de Aplicaciones Multiplataforma

Cuando creamos una nueva aplicacin Windows en VB.Net .NET, se nos proporciona un
cdigo inicial que incluye el espacio de nombres System.Windows.Forms y la clase Form.
Con esta clase, podemos crear fcilmente ventanas, botones, mens, barras de herramientas y
otros elementos de pantalla. Cuando compilamos la aplicacin, el cdigo se traduce al lenguaje
comn del entorno de ejecucin, Microsoft Intermediate Language (MSIL). Una vez la
aplicacin se ha compilado, el entorno de ejecucin gestiona su ejecucin.
El entorno de ejecucin incluye una caracterstica denominada compilacin just-in-time
(JIT), que traduce cdigo MSIL al lenguaje mquina del sistema en el que la aplicacin se
ejecutar. Cuando un dispositivo cliente con la plataforma .NET lanza la aplicacin en VB.Net
.NET, se ejecuta en el lenguaje mquina del sistema cliente y puede integrarse totalmente e
interactuar con otras aplicaciones y servicios basados en .NET independientemente del lenguaje
en el que hayan sido desarrollados.

Visual Studio .NET


Es la nueva versin de la familia de herramientas de desarrollo de software de Microsoft,
naturalmente orientadas hacia su nuevo entorno de programacin: .NET
Visual Studio .NET (VS.Net a partir de ahora), al tratarse de un entorno de desarrollo
integrado (Integrated Development Environment o IDE como tambin lo denominaremos a lo
largo del texto), ana todas las herramientas del SDK: compiladores, editores, ayuda, etc.,
facilitando en gran medida la creacin de programas.
La plataforma .NET es independiente del lenguaje (el .NET Framework proporciona todos
los servicios comunes necesarios para permitir la ejecucin de los programas). El .NET
Framework ofrece soporte para numerosos lenguajes de programacin, incluyendo lenguajes de
Microsoft y de terceros

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 10

Desarrollo de Aplicaciones Multiplataforma

Visual Basic.Net
Visual Basic.Net (VB.Net a partir de ahora) es uno de los diferentes lenguajes que componen
VS.Net.
VB.Net ofrece importantes innovaciones del lenguaje respecto a versiones anteriores de
Visual Basic .NET soporta herencia, constructores, polimorfismo, sobrecarga, excepciones
estructuradas, estricta verificacin de tipos, free threading, y muchas otras caractersticas que
iremos viendo a lo largo del curso.
En nuestro caso utilizaremos este lenguaje para crear aplicaciones de escritorio, basadas en
la Programacin Orientada a Objetos u POO a partir de ahora (Object Oriented Programming
con las siglas OOP).
Las aplicaciones de escritorio son aquellas basadas en ventanas y controles comunes de
Windows que se ejecutan en local.

Explorando el entorno de desarrollo. Nuestra primera


aplicacin
Abre el Visual Studio y te encontrars con una pantalla del tipo:

Lo primero que vamos a hacer es crear un nuevo proyecto. Un proyecto contiene todos
los archivos necesarios para la aplicacin y almacena informacin sobre la misma. Incluso,
una aplicacin puede contener ms de un proyecto, por ejemplo, un proyecto de aplicacin
para Windows y uno o varios proyectos de biblioteca de clases. La aplicacin se denomina
solucin, y se guarda en un fichero de extensin sln.
Para realizar lo que estamos diciendo, elige Nuevo proyecto y te aparecer una nueva
ventana del tipo:

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 11

Desarrollo de Aplicaciones Multiplataforma

Como puedes observar Visual Studio .NET ofrece varias plantillas de aplicaciones para
soportar el desarrollo de diferentes tipos de aplicaciones y componentes. Antes de iniciar un
nuevo proyecto, debemos escoger el tipo de plantilla que deseamos utilizar.
En nuestro caso escogeremos la primera opcin: Aplicacin de Windows Forms dentro de la
plantilla de VB.Net.

Sugerencia: Observa en la parte de abajo, que en la caja de texto etiquetada con Nombre
pone WindowsApplication1, que ser el adjudicado a nuestra aplicacin. Lo mejor ser poner
un nombre identificativo que nos indique lo que realiza el programa, como puede apreciarse en
las siguientes figuras:

Ahora haz clic en el botn Aceptar. Te aparece una ventana parecida a la que te muestro a
continuacin? Es posible que en la parte izquierda o derecha tengas otra presentacin,
mostrando el Cuadro de herramientas (fjate a la izquierda de la siguiente figura) o no
apareciendo tan visible el Explorador de soluciones o la ventana de Propiedades. Verlo o no
depender de cmo est configurado el entorno de desarrollo. Hacerlo ser fcilmente
modificable. Sitate sobre la que est minimizada (en la imagen el Cuadro de herramientas) y
vers que se expande al lado. Si por el contrario deseas minimizarla (como en el caso del
Explorador de soluciones y Propiedades) solo debers situarte sobre el icono semejante a una
chincheta que tienes en el marco de la ventana. Hazlo y vers que pasa.

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 12

Desarrollo de Aplicaciones Multiplataforma

Fichas ocultas

Fichas visibles

Sugerencia: Al igual que antes para el proyecto, vamos a cambiar el nombre del
formulario. Para eso te posicionas con el botn secundario del ratn sobre el icono del
formulario y tras elegir Cambiar nombre escribes el que puedes ver a continuacin.

Veamos que significan el resto de ventanas.

Mens y Barras de herramientas

Los comandos del men principal funcionan igual que en todas las aplicaciones basadas en
Windows, y podemos acceder a ellos utilizando el teclado o el ratn.
La barra de herramientas estndar proporciona botones que sirven como accesos directos a la
mayora de los comandos ms habituales, como Abrir, Guardar, Inicio, Aadir nuevo
elemento, Ir hacia atrs e Ir hacia adelante. Tambin contiene botones que abren el
Explorador de soluciones, la ventana de Propiedades, el Cuadro de herramientas, y otros
elementos importantes del entorno de desarrollo. Puede ser que tambin tengas la de
Depuracin. Esta proporciona accesos directos a las funcionalidades de depuracin, como ir
paso a paso en el cdigo y establecer puntos de interrupcin.

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 13

Desarrollo de Aplicaciones Multiplataforma

Las barras de herramientas pueden estar acopladas (adjuntas) o desacopladas (flotantes). De


forma predeterminada, la mayora de barras de herramientas estn acopladas; sin embargo,
podemos desacoplar o acoplar una barra de herramientas en cualquier momento.

Cuadro de herramientas

Para crear los objetos del interfaz de usuario de nuestra aplicacin, aadimos controles desde
el Cuadro de herramientas a un formulario. Inicialmente, el Cuadro de herramientas se
encuentra ubicado en el lado izquierdo del entorno de desarrollo. Hay varias pestaas para
diferentes categoras de controles, como Todos los formularios Windows Forms, Controles
comunes, Contenedores, Mens y barras de herramientas, Datos, etc.
El Cuadro de herramientas contiene diversos controles que podemos utilizar para aadir
ilustraciones, etiquetas, botones, cuadros de lista, barras de desplazamiento, mens y formas
geomtricas a un interfaz de usuario. Cada control que aadimos a un formulario se convierte en
un objeto de interfaz de usuario programable en nuestra aplicacin. Estos objetos son visibles
para los usuarios cuando la aplicacin se ejecuta y funcionan como los objetos estndares de
cualquier aplicacin basada en Windows.

Diseador de Windows Forms


Como hemos visto cuando iniciamos un proyecto en VB .NET, el Diseador de Windows
Forms se abre en la vista Diseo, mostrando un formulario llamado por defecto Form1.
Ahora vamos a disear la interfaz de usuari@. Para ello, debers arrastrar al formulario
los distintos controles, como botones y cuadros de texto. Puedes establecer propiedades que
definan el aspecto y comportamiento del formulario y de sus controles.
Arrastra un par de etiquetas (Label) y otro de botones (Button) en la forma:

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 14

Desarrollo de Aplicaciones Multiplataforma

Si ahora pulsas sobre el icono de ejecucin


la tecla <F5> o en el men Depurar ->
Iniciar Depuracin vers la ejecucin del mismo. Observa que aunque pulses sobre un botn,
no ocurre nada, si exceptuamos los iconos de minimizar, restaurar o cerrar tpicos de cualquier
ventana de Windows.
Cmo conseguimos que los botones realicen diferentes tareas? Para ello debemos saber
cmo cambiar determinadas propiedades de los controles y cmo aadir cdigo en el programa.

Ventana de Propiedades
La ventana de Propiedades muestra una lista de las propiedades que pueden configurarse
para el formulario o control seleccionado y que podemos modificar mientras creamos o
editamos la aplicacin. Una propiedad describe una caracterstica de un objeto, como el tamao,
ttulo o color.
Para situarte en las propiedades de un control o formulario en concreto tenemos varias
posibilidades. Hacer doble clic sobre el control (o formulario) siempre que la ventana de
propiedades est desplegada, elegir la opcin Propiedades si hacemos clic con el botn
secundario (en el caso de que la ventana de Propiedades no estuviese desplegada), elegir el
control desde el combo de la propia ventana como puedes apreciar en la figura.
Nota. Si la ventana Propiedades no est visible, haz clic en Ventana Propiedades en el men
Ver o pulsa la tecla F4, y si est visible pero no desplegada, acrcate a ella con el puntero del
ratn y se desplegar.

Observa que las propiedades se pueden visualizar por orden alfabtico o agrupadas por
categoras, dependiendo del icono elegido, pero independientemente de cmo las agrupes,
siempre la primera es la asociada al nombre del control (propiedad Name). Para cambiar en la
forma de verlas haz clic sobre los iconos correspondientes:

Vamos a cambiar las propiedades en nuestro ejemplo:

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 15

Desarrollo de Aplicaciones Multiplataforma

Control

Propiedad

Valor actual

Nuevo valor

Formulario

Text

Form1

Mi primer programa

Label1

Text

Label1

Cantidad de saludos

Label2

Text

Label2

Name

Button1

lblCantSaludos

BackColor

Control

Elige el que desees

Text

Button1

&Aceptar

Name
Button2

Text
Name

btnAceptar
Button2

&Fin
btnFin

Si ahora ejecutas el programa te encontrars con el siguiente formulario:

Pero, al igual que antes, aunque hagas clic sobre algn control, no pasa nada. Para ello
debemos incorporar el cdigo necesario. Cmo lo conseguimos? Gracias al Editor de cdigo.
Antes de continuar vamos a guardar el proyecto. Es una buena costumbre ir guardando de
vez en cuando. Como buen@s informtic@s no debemos dejar que la mala suerte nos tire al
traste un buen rato de trabajo.
Te saldr una nueva ventana del tipo:

De nuevo te aconsejo que (si no lo habas hecho antes) cambies el nombre del proyecto y en
cuanto a la Ubicacin elijas la carpeta o lugar del disco que a ti te interese utilizando el botn de
examinar. Si no lo haces, por defecto se guardar en la carpeta visual studio que ha creado
VS.Net.

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 16

Desarrollo de Aplicaciones Multiplataforma

Eventos: acciones que se producen sobre los controles


Windows es un sistema basado en eventos. Esto quiere decir que cualquier cosa que ocurra
dentro de un formulario, bien sobre el propio formulario, o a cualquiera de los controles que lo
componen, se detecta a travs de un suceso o evento: pasar el ratn sobre un control, hacer
clic, escribir en un control de texto, cerrar el formulario, redimensionarlo, etc. Cualquier
accin de este tipo provoca el evento correspondiente.
Todos los controles y formularios tienen eventos y aunque no lo percibamos, se estn
produciendo constantemente. Al dibujar los controles en el formulario, dichos controles
inicialmente no estn programados para responder a los eventos, hasta que no escribamos el
cdigo deseado para que el programa realice cuando se produzca el evento sobre el control o
formulario.

Editor de cdigo
VS .NET proporciona un Editor de cdigo en el que escribir y mantener el cdigo de nuestro
proyecto. Cada formulario tendr su propio editor de cdigo distinto, facilitando la
organizacin, visualizacin y desplazamiento por el cdigo.
Este Editor contiene dos listas
desplegables en la parte superior de la
ventana: la lista Nombre de Clase a la
izquierda y la lista Nombre de mtodo a la
derecha. Nombre de Clase muestra todos los
controles del formulario asociado. Si
hacemos clic en el nombre de un control de
la lista, Nombre de mtodo muestra los
eventos de dicho control (los eventos son
acciones que el control puede realizar y que
nuestra aplicacin puede interpretar).
Utilizando estas listas conjuntamente, podemos localizar rpidamente y editar el cdigo de
nuestra aplicacin.
Cmo abrimos esta ventana?
En el Explorador de soluciones, tras elegir el
formulario sobre el que se quiere editar su
cdigo, haciendo clic en el icono correspondiente
al cdigo.
(el de su derecha es para ver en
modo diseo).
En el men Ver, clic en Cdigo.
Haciendo doble clic sobre el formulario. Automticamente aparecer tambin la
misma ventana.
Haciendo doble clic sobre un control. En ese caso aparecer la ventana de cdigo con
algo semejante a lo que puedes apreciar en la figura: (Supongamos que el clic ha sido
sobre el botn btnAceptar).

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 17

Desarrollo de Aplicaciones Multiplataforma

Estando situada la ventana de propiedades en un control y eligiendo el icono referente


a eventos
. Ahora haz doble clic en la parte derecha de un evento (en el ejemplo
de Click). Con esta forma vemos que la ventana de propiedades, tambin lo es de
Eventos y que nos permitirn decir que queremos que haga el programa cuando se
produce dicha accin. En el ejemplo, qu queremos que haga el proyecto cuando el o
la usuaria haga clic sobre el botn de Aceptar?

Lo que vamos a hacer ahora, es escribir el cdigo que se ejecutar cuando se haga click en
los dos botones. Este evento se producir si se hace un click propiamente dicho, es decir con el
ratn, o bien porque se pulse Intro o la barra espaciadora cuando el botn tenga el foco. La
nomenclatura, para los eventos de VB.Net siguen el siguiente "esquema": [nombre del control]
[guin bajo] [nombre del evento] Pero esto slo es una sugerencia que VB.Net nos hace, en las
versiones anteriores no era una sugerencia, era una imposicin. Podemos dejar el nombre que
VB.Net nos sugiere o podemos poner el nombre que nosotros queramos; lo importante aqu es
la parte final de la lnea de declaracin del procedimiento: Handles btnAceptar.Click, con esto
es con lo que el compilador/intrprete de VB.Net sabe que este procedimiento es un evento y
que dicho evento es el evento Click del objeto btnAceptar.
Copia el siguiente cdigo y ejecuta el programa.

Ejecuta el programa y haz clic sobre el botn Aceptar, vers cmo obtienes algo semejante a:

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 18

Desarrollo de Aplicaciones Multiplataforma

Si por el contrario ahora pulsas sobre el botn de Cancelar, vers como el formulario se
cierra. Observa que si pulsas <ALT> a o <ALT>f se corresponder con el clic del botn
Aceptar y Fin respectivamente (por tener la letra subrayada, lo cual hemos conseguido gracias a
que en la propiedad Text pusimos la & antes de la letra a resear (&Aceptar o &Fin
respectivamente).
Ahora veamos con detalle el cdigo que hemos usado en los dos eventos:
Para el evento clic del botn con nombre btnAceptar hemos escrito:
MessageBox.Show("Hola mundo", "Saludo", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
lblCantSaludos.Text = CInt(lblCantSaludos.Text) + 1

MessageBox que es una clase, cuya tarea es mostrar en un cuadro de dilogo lo que le
indiquemos en el primer parmetro (en nuestro caso "Hola mundo"), con ttulo Saludo en el 2
parmetro, con el botn de

en el 3 y el icono de exclamacin del 4

Y la segunda lnea, lo que hace es escribir en la etiqueta de nombre lblCantSaludos, el n


entero que ya tena ms 1. Es decir, si en la etiqueta estaba escrito un 4 (en realidad el nmero
est en la propiedad Text del control) al sumarle 1 obtenemos el n 5 que lo dejamos de nuevo
en la misma etiqueta, con lo que conseguimos que cambie de valor.
De la misma forma, y como puedes observar, si hacemos clic sobre el botn btnFin, le
estamos diciendo Me.Close() (que me cierre), es decir, que cierre el formulario activo.

VB.Net (Cap 1. Introduccin a VB.Net)

Pg. 19

Desarrollo de Aplicaciones Multiplataforma

Cap 2. Formularios y controles


Introduccin
Un formulario sirve, como ya hemos dicho en varias ocasiones, de contenedor de controles,
o como soporte de textos o dibujos. Es la ventana de Windows de nuestra aplicacin. Una
aplicacin puede tener varios formularios y dentro de cada uno de ellos, los controles necesarios
para cada paso o estado de la aplicacin.
Como venimos diciendo los formularios y controles (que veremos ms adelante) son
objetos que exponen sus propios mtodos, propiedades y eventos.
Las propiedades se pueden considerar como atributos de un objeto, es decir, aquello que le
define, los mtodos como las acciones que puede realizar el objeto. Por otra parte debemos tener
en cuenta que Windows es un sistema basado en eventos. Esto quiere decir que cualquier cosa
que ocurra, bien sobre el propio formulario, o a cualquiera de los controles que lo componen, se
detecta a travs de un suceso o evento: pasar el ratn sobre un control, hacer clic, escribir
en un control de texto, cerrar el formulario, redimensionarlo, etc. Cualquier accin de este tipo
provoca el evento correspondiente. Nosotr@s realmente trabajaremos con la respuesta que
queremos que d el programa cuando se produce el evento.

Veamos esto con un ejemplo: Una persona.


Propiedades: Entre sus propiedades se incluyen aquellas caractersticas que la definen
como el Nombre, Direccin, Telfono, Fecha de Nacimiento, Estatura, Por
definicin, todas las personas tendran las mismas tienen estas propiedades; lo que
vara de una a otra son los valores de estas propiedades.
Mtodos: Acciones inherentes que puede efectuar. Por ejemplo, una persona puede
Moverse, Hablar, De nuevo, todas las personas pueden efectuar estos mtodos.
Eventos: De una persona nos enteraremos de cuando Nace, Muere, Y lo importante
ser saber que queremos hacer en esos momentos. Por ejemplo, cuando nace
guardaremos esa fecha como la Fecha de Nacimiento de esa persona,
. Resumiendo, todas las personas tendran esas mismas caractersticas pero cada una
con unos valores concretos o reacciones concretas, es decir: Los objetos tienen
propiedades, responden a eventos y ejecutan mtodos.
La asignacin de valores a las propiedades puede hacerse, en tiempo de diseo o de
ejecucin, existiendo propiedades que slo pueden manejarse en uno de estos dos ciclos de vida
de la aplicacin.
Tiempo de diseo. Es el tiempo en el que estamos creando los formularios, controles
y cdigo de la aplicacin.
Tiempo de ejecucin. Tiempo durante el cual se ejecuta la aplicacin.

VB.Net (Cap 2. Formularios y Controles)

Pg. 21

Desarrollo de Aplicaciones Multiplataforma

Propiedades, mtodos y eventos de un formulario


Algunas propiedades pueden ser comunes para formularios, controles y objetos en general,
es decir, pueden estar presentes en varios objetos al mismo tiempo. Este es el caso de la
propiedad Name, las propiedades que indican el tamao del objeto, etc.
Ya vimos antes como modificar las propiedades en tiempo de diseo gracias a la Ventana de
Propiedades.
En tiempo de ejecucin, es decir, por cdigo, tanto en las propiedades como en los mtodos,
pondremos el nombre de la propiedad o mtodo tras la palabra reservada Me, que indica la
instancia actual del formulario:
Me.Text = "Ejemplo de Uso de Controles"
Me.BackColor = Color.Aqua
Me.Close()

Y recuerda! Si estamos hablando de una propiedad (los dos primeros ejemplos) se utiliza el
operador de asignacin = (le damos un valor), pero si es un mtodo (el tercero) no, ya que en
estos casos se trata de realizar una accin, no recibir un valor.

Propiedades
Veremos ciertas propiedades de los formularios, pero recuerda que tanto para formularios
como controles, siempre puedes consultarlas empleando las mltiples formas de ayuda que nos
da el propio Visual Studio.
Name. Cadena de caracteres con el nombre identificativo del objeto utilizado en el
cdigo fuente de la aplicacin. Asignaremos siempre un nombre que empiece por frm.
Ejemplo: frmDatosPers
El nombre tiene que seguir las reglas de los identificadores. Es decir frmN1 no sera un
nombre de formulario vlido.
El valor de esta propiedad se asignar obligatoriamente en tiempo de diseo, en la
Ventana de Propiedades.
Text. Texto que se visualiza en la barra de ttulo del formulario. En este caso se suele
dar valor en tiempo de diseo pero podemos tambin hacerlo en tiempo de ejecucin.
Ejemplo: Si deseamos que un formulario de nombre frmPrincipal reciba el ttulo:
Ejemplo de Uso de operadores lo haremos con una de las 2 instrucciones siguientes,
dependiendo de si nos encontramos en el mismo formulario o en otro.
Me.Text = "Ejemplo de Uso de operadores" ' Nos encontramos en el mismo
formulario
frmPrincipal.Text = "Ejemplo de Uso de operadores" ' Si estamos en otro
formulario

Esto generar que la barra del formulario tenga la siguiente forma:

FormBorderStyle. Establece el tipo de borde y de la barra de ttulo del formulario, en


funcin del cual tendr un comportamiento determinado. La siguiente tabla muestra
los valores constantes disponibles para esta propiedad.

VB.Net (Cap 2. Formularios y Controles)

Pg. 22

Desarrollo de Aplicaciones Multiplataforma

Dependiendo del valor elegido nos encontraremos con un formulario sin borde, con
barra de ttulo pero con el tamao fijo (Fixed)o modificable (Sizable), con los botones
de Minimizar, Restaurar o no,

ControlBox. Propiedad lgica (admite los valores True o False), que sirve para
indicar si el formulario dispondr de un men de control, es decir, los iconos que
aparecen a la derecha del formulario para permitir Minimizar, Restaurar o Cerrarlo. Su
valor por defecto es True.

StartPosition. Establece la posicin de comienzo para un formulario la primera vez


que se visualiza. Te recomiendo que generalmente la cambies a CenterScreen
(centrado en la pantalla)

Sugerencia: Crea un nuevo proyecto de nombre PrMisPropiedades con un formulario y


consigue que tenga una presentacin como la de abajo, es decir, con el ttulo de la ventana Mis
propiedades, el borde del formulario que se pueda modificar pero sin los iconos de Minimizar,
Restaurar, con una imagen que est totalmente integrada en el formulario (ver propiedades
BackgroundImage y BackgroundImageLayout), que al pasar el ratn sobre el formulario su
puntero sea como el de la figura

(ver propiedad Cursor).

VB.Net (Cap 2. Formularios y Controles)

Pg. 23

Desarrollo de Aplicaciones Multiplataforma

Mtodos
En cuanto a los mtodos, uno de los ms utilizado es el mtodo Close, que lo que hace es
cerrar o descargar el formulario. Dependiendo del formulario al que hagamos referencia,
pondremos la palabra Me (si estamos hablando del mismo sobre el que se escribe el cdigo) u
otro, ejemplo: frmDatos.Close significara que debe cerrar el formulario con ese nombre.
Private Sub btnFin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFin.Click
Me.Close() ' cierra (descarga) el formulario actual
End Sub

Otros mtodos que tambin vamos a utilizar mucho son: Show y ShowDialog que sirven
para lo contrario, mostrar un formulario en pantalla.
Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCargar.Click
frmDatos.Show()' carga en pantalla el formulario frmDatos
End Sub

La diferencia entre ambos mtodos es la forma en que se mostrar el formulario en pantalla,


en lo que se llama modal o no modal.
Un formulario de comportamiento no modal, permite el libre cambio de foco entre el
resto de formularios de la aplicacin, mientras que un formulario cargado en forma modal
(tambin denominados cuadros o ventanas de dilogo), al ser visualizado, bloquea el paso a
otros formularios de la aplicacin hasta que no es cerrado (aceptado o completado) por el o la
usuaria.

Eventos
Y por ltimo veamos algunos de procedimientos orientados a los eventos que ms vamos a
utilizar:
Load: Este evento se produce cuando el formulario se carga en memoria, y lo que
programaremos es para indicar las acciones que queremos realizar cuando esto ocurra. Veamos
un ejemplo:
Private Sub frmHolaMundo_Load(ByVal sender As Object, ByVal e As
System.EventArgs) Handles Me.Load
' Instrucciones que queremos ejecutar al cargarse el formulario
Me.FormBorderStyle = Windows.Forms.FormBorderStyle.FixedSingle ' Borde fijo de
una sola lnea
Me.lblCantSaludos.Text = 0 ' La etiqueta comienza con este valor
End Sub

El evento FormClosing que se produce antes de cerrar el formulario. Cuando un formulario


est cerrado, se elimina, liberando todos los recursos que tenga asociados. Si se cancela este

VB.Net (Cap 2. Formularios y Controles)

Pg. 24

Desarrollo de Aplicaciones Multiplataforma

evento, el formulario permanece abierto. Para cancelarlo estableceremos la propiedad Cancel


del FormClosingEventArgs que se pasa al controlador de eventos en True.
Private Sub frmHolaMundo_FormClosing(ByVal sender As Object, ByVal e As
System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
' Este procedimiento se ejecuta cuando, por algn motivo, se va a cerrar el
formulario
Dim resp As DialogResult
' Preguntamos al usuari@ si realmente desea cerrarlo
resp = MessageBox.Show("Cerrar el formulario?", "Atencin",
MessageBoxButtons.YesNo, MessageBoxIcon.Question)
If resp = Windows.Forms.DialogResult.No Then
' Si responde que No cancelamos el cierre, es decir, se queda en pantalla
e.Cancel = True
End If
End Sub

Controles ms habituales
Como habr comprobado, el nmero de controles del cuadro de herramientas es muy
numeroso, por lo que en los prximos apartados, vamos a trabajar con los que se consideran
controles bsicos o estndar, dada su gran frecuencia de uso.
Recuerda que cada vez que insertemos un control, tomar una serie de propiedades por
defecto (nombre incluido), que podremos cambiar para adaptar a los requerimientos de la
aplicacin.
La siguiente tabla relaciona este conjunto de controles bsico, junto a una breve descripcin.
Control

Descripcin

Button

Botn de pulsacin

Convencin para la inicial del


nombre. Ejemplo
btn - btnAceptar

Label

Etiqueta de literal

lbl - lblDatosPersonales

TextBox

Cuadro de texto

txt - txtNombre

ListBox

Lista de valores

lst - lstCiudades

ComboBox

Lista de valores desplegable, y cuadro de texto cbo - cboCursos

CheckBox

Casilla de verificacin

chk - chkTrabajando

RadioButton

Botn autoexcluyente

rad - radMujer

GroupBox

Caja de agrupacin de controles

grb grbDatos

Button
Este control representa un botn de pulsacin. Entre el nutrido conjunto de propiedades de
este control, destacaremos las siguientes.
Text. Cadena con el ttulo del botn.
TextAlign. Alineacin o disposicin del ttulo dentro del rea del botn; por defecto
aparece centrado.
BackColor. Color de fondo para el botn.
Cursor. Permite modificar el cursor del ratn que por defecto tiene el botn.
Image. Imagen que podemos mostrar en el botn como complemento a su ttulo, o
bien, en el caso de que no asignemos un texto al botn, nos permitir describir su
funcionalidad.

VB.Net (Cap 2. Formularios y Controles)

Pg. 25

Desarrollo de Aplicaciones Multiplataforma

ImageAlign. Al igual que para el texto, esta propiedad nos permite situar la imagen
en una zona del botn distinta de la central, que es en la que se ubica por defecto.
BackgroundImage. Imagen de fondo para el botn.
FlatStyle. Tipo de resaltado para el botn. Por defecto, el botn aparece con un cierto
relieve, que al ser pulsado, proporciona el efecto de hundirse y recuperar nuevamente
su estado, pero podemos, mediante esta propiedad, hacer que el botn se muestre
en modo plano, con un ligero remarcado al pulsarse, etc.
Font. Cambia el tipo de letra y todas las caractersticas del tipo elegido, para el
texto del botn.
La siguiente figura muestra un ejemplo de control Button, sobre el que se han modificado
algunos valores por defecto de sus propiedades.

Y generalmente para qu queremos un botn? Pues para que el programa realice alguna
tarea cuando se presiona sobre l.
Para programar esto, tendremos el evento ms utilizado de los botones, que es el evento
Click, al que le aplicaremos el subprograma asociado, en la forma:
Private Sub btnFin_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFin.Click
Me.Close() ' cierra (descarga) el formulario actual
End Sub

Label
El control Label o Etiqueta, muestra un texto informativo al usuario. Podemos utilizar este
control como complemento a otro control, por ejemplo, situndolo junto a un TextBox, de modo
que indiquemos al o a la usuaria el tipo de dato que esperamos que introduzca en la caja de
texto.
Se trata de un control esttico; esto quiere decir que el usuario o usuaria no suele
interaccionar con l, a diferencia, por ejemplo, de un control Button, sobre el que actuamos
pulsndolo; o de un TextBox, en el que podemos escribir texto.
Una de sus propiedades es BorderStyle, que permite definir un borde o recuadro alrededor
del control, o que dicho borde tenga un efecto 3D; por defecto se muestra sin borde. Veamos
unos ejemplos en la Figura

Controles Label.

VB.Net (Cap 2. Formularios y Controles)

Pg. 26

Desarrollo de Aplicaciones Multiplataforma

TextBox
Un control TextBox muestra un recuadro en el que podemos introducir texto. Para poder
escribir texto en un control de este tipo, debemos darle primeramente el foco, lo que
detectaremos cuando el control muestre el cursor de escritura en su interior.
Entre las propiedades disponibles por este control, destacaremos las siguientes.
Text. Cadena con el texto del control.
Multiline. Permite establecer si podemos escribir una o varias lneas. Por defecto
contiene False, por lo que slo podemos escribir el texto en una lnea.
Enabled. Contiene un valor lgico mediante el que indicamos si el control est o no
habilitado para poder escribir texto sobre l.
ReadOnly. Permite indicar si el contenido del control ser de slo lectura o bien,
podremos editarlo.
CharacterCasing. Esta propiedad, permite que el control convierta automticamente
el texto a maysculas o minsculas segn lo estamos escribiendo.
MaxLength. Valor numrico que establece el nmero mximo de caracteres que
podremos escribir en el control.
PasswordChar. Carcter de tipo mscara, que ser visualizado por cada carcter que
escriba el usuario en el control. De esta forma, podemos dar a un cuadro de texto
el estilo de un campo de introduccin de contrasea.
AutoSize. Cuando esta propiedad tenga el valor True, al modificar el tamao del tipo
de letra del control, dicho control se redimensionar automticamente, ajustando su
tamao al del tipo de letra establecido.
CharacterCasing. Tiene 3 posibles valores Normal, Lower o Upper para indicar que
el carcter tecleado se escriba como se teclea, en minsculas o maysculas.
ScrollBar: Permite aadir barras de desplazamiento. Posibles valores: None, Vertical,
Horizontal o Both. Para ser efectivo, la caja de texto deber tener establecida la
propiedad MultiLine a True y si ponemos Both deberemos cambiar la propiedad
WordWrap a False.

Foco de entrada
Para que las pulsaciones de teclado puedan ser recibidas por un determinado control,
dicho control debe tener lo que se denomina el foco de entrada.
El modo de dar a un control el foco de entrada, consiste en hacer clic sobre l, o bien, pulsar
la tecla [TAB], pasando el foco hasta el control deseado. Cuando un control recibe el
foco, el sistema operativo lo remarca visualmente o en el caso de controles de escritura,
muestra el cursor de escritura en su interior.
La siguiente figura muestra un formulario con varios controles TextBox, a los cuales se
han aplicado diferentes efectos mediante sus propiedades.

Pruebas con controles TextBox.

VB.Net (Cap 2. Formularios y Controles)

Pg. 27

Desarrollo de Aplicaciones Multiplataforma

Al comenzar a ejecutar el programa, observaremos que el foco de entrada est situado en el


algn control del formulario (en la caja de texto o botn que hayamos creado el primero). Si
queremos asignar por cdigo el foco a un determinado control, disponemos del mtodo
Focus().
Vamos a hacer que al pulsar el botn Foco nombre, desviemos el foco al primer TextBox del
formulario.
Private Sub btnFoco_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnFoco.Click
Me.txtNombre.Focus() ' le da el foco a la caja de texto txtNombre
End Sub

Observa, que en el botn Foco nombre, que acabamos de mencionar, la letra F se encuentra
subrayada, actuando de acelerador o hotkey. De este modo, no es necesario pulsar con el
ratn sobre ese botn para ejecutarlo, basta con pulsar la tecla [CONTROL] junto a la letra
subrayada para conseguir el mismo efecto.
Para definir una tecla aceleradora en un control, debemos anteponer el carcter & a la letra
que vamos a definir como acelerador, en este ejemplo se ha logrado con &Foco nombre.
Por otro lado, mediante el botn btnSoloLectura vamos a activar/desactivar la propiedad
ReadOnly del TextBox txtNombre, cambiando el estado de dicha propiedad en cada pulsacin
del botn.
Private Sub btnSoloLectura_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSoloLectura.Click
Me.Nombre.ReadOnly = Not Me.Nombre.ReadOnly ' Cambia el estado de la
propiedad ReadOnly de True a False o viceversa (a lo contrario de lo que estaba)
End Sub

Al establecerse esta propiedad en true, el usuario no puede cambiar el contenido del control
en tiempo de ejecucin, pero si puede darle el foco y, por ejemplo, Copiar su texto en el
portapapeles gracias al tpico Copiar.
Otra cosa diferente es deshabilitar totalmente el control, no permitiendo el acceso al mismo,
ni tan siquiera recibira el foco.
Supongamos que deseamos hacer esto con la caja de texto txtApellidos. Escribe el cdigo
correspondiente para el evento Clic del botn btnActivar.

Control de entrada en las cajas de texto. Eventos KeyPress y


TextChanged
En muchas ocasiones necesitamos controlar los datos que se introducen en una caja de texto.
Por ejemplo, si tenemos una caja de texto en la cual se va a introducir el sueldo de una persona,
es lgico pensar que no se podrn teclear caracteres no numricos. Cmo realizaremos el
control en el mismo momento en que se est introduciendo el dato? Para ello tenemos varios
eventos a considerar: TextChanged, KeyPress, KeyDown, KeyUp. Veamos la forma ms
adecuada de hacerlo normalmente.
Empecemos por el evento KeyPress. Este se produce cada vez que el o la usuaria pulsa una
tecla sobre un control (en este caso sobre una caja de texto). El carcter tecleado se guarda en la
propiedad KeyChar de la variable e (e.KeyChar). Si no se hace nada (porque no se invoca este
subprograma o porque en l todo se considera correcto), el carcter aparece en el control, pero si
modifica el valor de la propiedad Handled de la variable e (e.Handled) y se pone a True, el
carcter no aparece.

VB.Net (Cap 2. Formularios y Controles)

Pg. 28

Desarrollo de Aplicaciones Multiplataforma


Private Sub txtSueldo_KeyPress(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles txtSueldo.KeyPress
' Este evento se produce cada vez que el o la usuaria pulsa una tecla.
' No se detecta la tecla de Supr (si la de Retroceso)
' ni las teclas de funcin <F1>...<ESC>. Para ello existen KeyDown y KeyUp
' Considera caracteres vlidos los dgitos, la , el . y la tecla de retroceso
Const validos = "0123456789,." & ControlChars.Back
If Not validos.Contains(e.KeyChar) Then
' si el carcter tecleado no se encuentra entre los que admitimos, no se
' muestra en la caja de texto
e.Handled = True
MessageBox.Show(e.KeyChar & " no es un carcter vlido, para un dato
numrico", "Atencin", MessageBoxButtons.OK, MessageBoxIcon.Exclamation) '
sacamos un mensaje para que quien teclea se entere de lo ocurrido
End If
End Sub

Sugerencia: Piensa como sera este subprograma si quisiramos controlar que la, solo se
pudiese teclear una vez.
Por otra parte est el evento TextChanged, que se produce, como su nombre indica, cada vez
que alguien cambia el texto de la caja de texto. Veamos una forma de trabajar con l:
Private Sub txtSueldo_TextChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles txtSueldo.TextChanged
' Se produce cada vez que cambia el texto de la caja de texto, porque lo cambia
' (escribiendo sobre ella o con Pegar) la o el usuario o por el propio programa
' en instrucciones como txtSueldo.Text = 1.600,20
If txtSueldo.Text = "" Then Exit Sub ' Si se ha quedado en blanco no lo
' consideramos error
If Not IsNumeric(txtSueldo.Text) Then
MessageBox.Show(txtSueldo.Text & " no es un dato numrico", "Atencin",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtSueldo.Text = "" ' limpiamos el dato de la caja de texto
End If
End Sub

Y ahora tal vez te preguntes, para qu vamos a poner los 2 subprogramas en la misma caja
de texto?, con uno vale. Habr ocasiones en que as sea, pero analicemos las diferencias:
En el caso del KeyPress, si se pulsa una tecla errnea solo se anula esa tecla, no hace falta
borrar todo lo que ya contena. Vale, pues entonces por qu no dejar solo el KeyPress? Piensa
en el caso, muy probable de que en lugar de teclear en la caja de texto se haga el tpico Pegar.
En ese caso, no se habr producido el evento KeyPress y por tanto no se habra detectado el
error.
Y por ltimo, si ponemos ambos, cul se produce primero? Pues el KeyPress. Es decir, si en
el ejemplo anterior, se pulsa una letra, el KeyPress detectar que no es vlida y no se modificar
la caja de texto (por lo que no se ir al otro subprograma) y si el dato es vlido ir a los 2.
Y ahora piensa que hara el siguiente ejemplo:
Private Sub txtNombre_KeyPress(ByVal sender As System.Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles txtNombre.KeyPress
If e.KeyChar = "" Then e.KeyChar = "n"
If e.KeyChar = "" Then e.KeyChar = "N"
End Sub

VB.Net (Cap 2. Formularios y Controles)

Pg. 29

Desarrollo de Aplicaciones Multiplataforma

Seleccin de texto en un TextBox


La seleccin de texto en un control TextBox es un proceso que funciona de modo
transparente al programador o programadora, en el sentido en que este no necesita aadir cdigo
adicional para las operaciones de seleccin, cortar, copiar, etc., al ser tareas integradas en el
sistema operativo.
Sin embargo, podemos necesitar en un determinado momento, tener informacin acerca de
las operaciones de seleccin que est realizando el o la usuaria en nuestros controles de texto.
Para ello, el control TextBox dispone de las siguientes propiedades.
SelectionStart. Posicin del texto del control, en la que comienza la seleccin
que hemos realizado.
SelectionLength. Nmero de caracteres seleccionados en el control.
SelectedText. Cadena con el texto que hemos seleccionado en el control.
Mediante estas propiedades, no slo averiguamos la seleccin que pueda tener un control
TextBox, sino que tambin podemos utilizarlas para establecer por cdigo una seleccin;
teniendo el mismo efecto que si la hubiera efectuado el usuario con el ratn o teclado.
Para comprobar el funcionamiento de las propiedades de seleccin del TextBox, crearemos
un proyecto Windows, y en su formulario aadiremos varios controles para manipular la
seleccin de texto que hagamos en un TextBox. La figura muestra el formulario del ejemplo.

Formulario para realizar seleccin en el control TextBox

El control de este formulario, que vamos a emplear para las operaciones de seleccin es
txtOrigen. En primer lugar, y aunque no se trata de una seleccin de texto, usaremos el evento
TextChanged visto anteriormente, pero ahora de otra manera. En este caso lo usaremos para
contar la cantidad de caracteres escritos y mostrarlos en un Label. Ver Cdigo fuente.
' al cambiar el texto del control se produce este evento
Private Sub txtOrigen_TextChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles txtOrigen.TextChanged
' calculamos la longitud del texto escrito
Me.lblContador.Text = Me.txtOrigen.TextLength
End Sub

Los eventos MouseMove y KeyDown del TextBox, se producen respectivamente, cuando


movemos el ratn sobre el control, o cada vez que pulsamos una tecla para escribir texto.
Detectaremos en este caso, si existen teclas o botones especiales presionados, que nos
indiquen que se est realizando una seleccin de texto, y mostraremos en el formulario el texto
seleccionado, el nmero de caracteres y la posicin del carcter de inicio de la seleccin.
Veamos el cdigo fuente para los procedimientos manipuladores de estos eventos.

VB.Net (Cap 2. Formularios y Controles)

Pg. 30

Desarrollo de Aplicaciones Multiplataforma


Private Sub txtOrigen_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles txtOrigen.MouseMove
' comprobamos si al mover el ratn est pulsado su botn izquierdo
' en caso afirmativo es que se est seleccionando texto, por lo que obtenemos
' la informacin de seleccin con las propiedades de seleccin del TextBox
If e.Button = Windows.Forms.MouseButtons.Left Then
Me.lblTextoSelec.Text = Me.txtOrigen.SelectedText
Me.lblLongitud.Text = Me.txtOrigen.SelectionLength
Me.lblPosicion.Text = Me.txtOrigen.SelectionStart
End If
End Sub
' este evento se produce cuando se pulsa una tecla en el TextBox
Private Sub txtOrigen_KeyDown(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyEventArgs) Handles txtOrigen.KeyDown
' comprobamos las teclas pulsadas
' Si est pulsada la tecla maysculas, y adems se est pulsando la tecla
' flecha derecha, quiere decir que se est seleccionando texto;
' Mostraremos en las etiquetas la informacin de las propiedades de seleccin
' del control TextBox
If e.Shift Then
If e.KeyCode = Keys.Right Then
Me.lblTextoSelec.Text = Me.txtOrigen.SelectedText
Me.lblLongitud.Text = Me.txtOrigen.SelectionLength
Me.lblPosicion.Text = Me.txtOrigen.SelectionStart
End If
End If
End Sub

Finalmente, tras introducir un valor en los controles txtPosicion y txtLongitud, pulsaremos el


botn btnSeleccionar. Con ello conseguiremos realizar una seleccin de texto en el TextBox
txtOrigen, y pasar el texto seleccionado al control txtDestino. El efecto ser el mismo que si lo
hubiera realizado el usuario, pero en este caso sin su intervencin. Veamos en el Cdigo fuente,
el evento Click del botn btnSeleccionar.
' al pulsar este botn, seleccionar por cdigo texto del control txtOrigen y
pasarlo al control txtDestino
Private Sub btnSeleccionar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSeleccionar.Click
' elegimos desde donde comenzar la seleccin y cuantos caracteres
Me.txtOrigen.SelectionStart = Me.txtPosicion.Text
Me.txtOrigen.SelectionLength = Me.txtLongitud.Text
' ya tenemos seleccionado el texto desde la posicin SelectionStart,
' SelectionLength caracteres
' con SelectedText cogemos ese texto seleccionado
Me.txtDestino.Text = Me.txtOrigen.SelectedText
End Sub

Si lo ejecutas podrs encontrarte con algo semejante a las siguientes imgenes. De todas
formas observa que si has seleccionado un texto en cualquiera de las dos modalidades (figura de
la izquierda) y aparecen los datos correspondientes en las etiquetas, al pulsar, por ejemplo, sobre
el botn Seleccionar se mantendran. Se te ocurre como limpiarlos?

VB.Net (Cap 2. Formularios y Controles)

Pg. 31

Desarrollo de Aplicaciones Multiplataforma

CheckBox
Este control muestra una casilla de verificacin, que podemos marcar para establecer un
estado. Generalmente el estado de un CheckBox es marcado (verdadero) o desmarcado (falso),
sin embargo, podemos configurar el control para que sea detectado un tercer estado, que se
denomina indeterminado, en el cual, el control se muestra con la marca en la casilla pero en
un color de tono gris.
Las propiedades remarcables de este control son las siguientes.
Checked. Valor lgico que devuelve True cuando la casilla est marcada, y False
cuando est desmarcada.
CheckState. Valor del tipo enumerado CheckState, que indica el estado del control.
Checked, marcado; Unchecked, desmarcado; e Indeterminate, indeterminado.
ThreeState. Por defecto, un control de este tipo slo tiene dos estados, pero
asignando True a esta propiedad, conseguimos que sea un control de tres estados.
CheckAlign. Permite establecer de modo visual la ubicacin de la casilla de
verificacin dentro del rea del control.
Como detalle destacable de las propiedades Checked y CheckState, si modificamos desde
cdigo sus valores, conseguiremos alterar el estado de la casilla del control.

Controles CheckBox en ejecucin

El siguiente ejemplo, muestra un formulario con dos controles CheckBox. Un control


chkDarColor al que solo le cambiars el Nombre y el Text en las propiedades por defecto y
chkMostrarSaludo al que modificars el Nombre, Text, CheckAlign y ThreeState.
El control chkDarColor asigna un color de fondo al formulario o restablece el color original.
Esto lo conseguimos codificando el evento CheckedChanged del control. Observa que como
usuari@ si haces clic sobre este control repetidas veces, solo pasars por los 2 estados, marcado
o desmarcado.

VB.Net (Cap 2. Formularios y Controles)

Pg. 32

Desarrollo de Aplicaciones Multiplataforma

' este evento se produce cuando se hace clic en el CheckBox


' y cambia el contenido de la casilla
Private Sub chkDarColor_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles chkDarColor.CheckedChanged
If Me.chkDarColor.CheckState = CheckState.Checked Then ' si est marcado
Me.BackColor = Color.LightBlue ' le da este color al formulario
Else
Me.ResetBackColor() ' sino recupera el color original
End If
End Sub

Por su parte, el control chkMostrarSaludo, definido con tres estados, muestra, al estar
marcado, una cadena de saludo en la etiqueta lblSaludo; elimina la cadena al desmarcarlo; y
muestra los 4 primeros caracteres al entrar en el estado indeterminado. El evento
CheckStateChanged es el que debemos de utilizar para detectar el estado del CheckBox en cada
ocasin. Para mantener el valor de la cadena a mostrar, utilizamos una constante global.
Const saludo = "Hola 1DAM"
' Este evento se produce cuando cambia el estado de la casilla.
' Si usamos el CheckedChanged al marcar Indeterminado no se provoca el evento
Private Sub chkMostrarSaludo_CheckStateChanged(ByVal sender As Object, ByVal e As
System.EventArgs) Handles chkMostrarSaludo.CheckStateChanged
Select Case Me.chkMostrarSaludo.CheckState
Case CheckState.Checked
Me.lblSaludo.Text = saludo
Case CheckState.Unchecked
Me.lblSaludo.Text = ""
Case CheckState.Indeterminate
Me.lblSaludo.Text = saludo.Substring(0, 4) ' Coge los 4 primeros caracteres
End Select
End Sub

En ambos casos podramos haber usado el procedimiento orientado al evento Click.

RadioButton y GroupBox
Los controles RadioButton nos permiten definir conjuntos de opciones autoexcluyentes, de
modo que situando varios controles de este tipo en un formulario, slo podremos tener
seleccionado uno en cada ocasin.
Vamos a crear un proyecto de ejemplo con el nombre PrRadioButton, en el que situaremos
dentro de un formulario, una serie de controles RadioButton y un TextBox, de modo que
mediante los RadioButton cambiaremos el tipo de fuente y color del cuadro de texto. La Figura
muestra un diseo inicial del formulario. Por cierto, observa que el RadioButton azul tiene el
color azul ms largo que el resto. Trabaja con la propiedad AutoSize y vers el porqu.

Pruebas con el control RadioButton.

VB.Net (Cap 2. Formularios y Controles)

Pg. 33

Desarrollo de Aplicaciones Multiplataforma

Al ejecutar el proyecto, sin embargo, no podemos conseguir establecer simultneamente


un tipo de letra y color, puesto que al pulsar cualquiera de los botones de radio, se quita el que
hubiera seleccionado previamente.
Para solucionar este problema, disponemos del control GroupBox, que nos permite, como
indica su nombre, agrupar controles en su interior, tanto RadioButton como de otro tipo, ya que
se trata de un control contenedor.
Una vez dibujado un GroupBox sobre un formulario, podemos arrastrar y soltar sobre l,
controles ya existentes en el formulario, o crear nuevos controles dentro de dicho control. De
esta forma, podremos ya, en este ejemplo, seleccionar ms de un RadioButton del formulario,
como vemos en la siguiente imagen:

Seleccin de varios RadioButton en un formulario.

El evento CheckedChanged, al igual que ocurra con los controles CheckBox, ser el que
tendremos que escribir para ejecutar el cdigo en respuesta a la pulsacin sobre un control
RadioButton. El Cdigo fuente siguiente muestra los eventos correspondientes a los controles
de radio de este ejemplo. Para cambiar el tipo de fuente, instanciamos un objeto Font y lo
asignamos a la propiedad Font del TextBox; mientras que para cambiar el color, utilizamos la
estructura Color y la propiedad BackColor, tambin del TextBox.
Private Sub rbtTahoma_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtTahoma.CheckedChanged
Me.txtNombre.Font = New Font("Tahoma", 12)
End Sub
Private Sub rbtGaramond_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtGaramond.CheckedChanged
Me.txtNombre.Font = New Font("Garamond", 8)
End Sub
Private Sub rbtComic_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtComic.CheckedChanged
Me.txtNombre.Font = New Font("Comic Sans MS", 15)
End Sub
Private Sub rbtVerde_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtVerde.CheckedChanged
Me.txtNombre.BackColor = Color.Green
End Sub

VB.Net (Cap 2. Formularios y Controles)

Pg. 34

Desarrollo de Aplicaciones Multiplataforma


Private Sub rbtAzul_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtAzul.CheckedChanged
Me.txtNombre.BackColor = Color.Blue
End Sub
Private Sub rbtAmarillo_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtAmarillo.CheckedChanged
Me.txtNombre.BackColor = Color.Yellow
End Sub

ListBox
Un control ListBox contiene una lista de valores, de los cuales, el o la usuaria puede
seleccionar uno o varios simultneamente. Entre las principales propiedades de este control,
podemos resaltar las siguientes.
Items. Contiene la lista de valores que visualiza el control. Se trata de un tipo
ListBox.ObjectCollection, de manera que el contenido de la lista puede ser tanto tipos
carcter, como numricos y objetos de distintas clases. Al seleccionar esta propiedad
en la ventana de propiedades del control y pulsar el botn que contiene, podemos
introducir en una ventana elementos para el control

Introduccin de valores para un ListBox en tiempo de diseo

El control quedara por lo tanto con valores asignados en la etapa de diseo, como
muestra la siguiente figura:

ListBox en diseo con valores en su lista

Sorted. Cuando esta propiedad contiene el valor True, ordena el contenido de la lista.
Cuando contiene False, los elementos que hubiera previamente ordenados,
permanecen con dicho orden, mientras que los nuevos no sern ordenados.

VB.Net (Cap 2. Formularios y Controles)

Pg. 35

Desarrollo de Aplicaciones Multiplataforma

IntegralHeight. Los valores de la lista son mostrados al completo cuando esta


propiedad contiene True. Sin embargo, al asignar el valor False, segn el tamao del
control, puede que el ltimo valor de la lista se visualiza slo en parte. La
sigu ient e f igura muestra un ListBox con esta propiedad a False.

ListBox mostrando parte del ltimo elemento debido a la propiedad IntegralHeight.

MultiColumn. Visualiza el contenido de la lista en una o varias columnas en


funcin de si asignamos False o True respectivamente a esta propiedad.
SelectionMode. Establece el modo en el que vamos a poder seleccionar los
elementos de la lista. Si esta propiedad contiene None, no se realizar seleccin; One,
permite seleccionar los valores uno a uno; MultiSimple permite seleccionar mltiples
valores de la lista pero debemos seleccionarlos independientemente; por ltimo,
MultiExtended nos posibilita la seleccin mltiple, con la ventaja de que podemos
hacer clic en un valor, y arrastrar, seleccionando en la misma operacin varios
elementos de la lista.
SelectedItem. Devuelve el elemento de la lista actualmente seleccionado.
Selecteditems. Devuelve una coleccin ListBox.SelectedObjectCollection, que
contiene los elementos de la lista que han sido seleccionados.
SelectedIndex. Informa del elemento de la lista seleccionado, a travs del ndice de la
coleccin que contiene los elementos del ListBox.
Para mostrar algunas de las funcionalidades de este control, utilizaremos el proyecto de
ejemplo PrListBox. La siguiente figura muestra esta aplicacin en ejecucin

El ejemplo, cmo puedes comprobar, consiste en un formulario que contiene un ListBox


principal, con el nombre lstValores, que dispone de una serie de valores asignados en
tiempo de diseo.

VB.Net (Cap 2. Formularios y Controles)

Pg. 36

Desarrollo de Aplicaciones Multiplataforma

Cada vez que hacemos clic en alguno de los valores, se produce el evento
SelectedIndexChanged, que utilizamos para mostrar en este caso, el nombre del elemento o
elementos en el ttulo del formulario, como muestra el siguiente cdigo. Primero averiguaremos
cuantos hay seleccionados gracias a cualquiera de las 2 propiedades que contienen las
colecciones: SelectedIndices o SelectedItems que contienen los ndices o elementos
seleccionados respectivamente.
Si solo tenemos un elemento seleccionado podemos utilizar la propiedad SelectedItem o si
lo necesitase SelectedIndex que contienen el texto o ndice del elemento seleccionado, pero en
el caso de que haya varios, debemos recurrir a las colecciones antes comentadas.
' este evento se produce cada vez que se cambia el
' ndice seleccionado del ListBox
Private Sub lstValores_SelectedIndexChanged(ByVal sender As System.Object, ByVal
e As System.EventArgs) Handles lstValores.SelectedIndexChanged
' mostrar en el ttulo del formulario el valor o valores seleccionados
If lstValores.SelectedItems.Count = 0 Then
' No hay ninguno seleccionado
Me.Text = "No hay elementos seleccionados"
ElseIf lstValores.SelectedIndices.Count = 1 Then
' Hay solo uno seleccionado, usamos la propiedad SelectedItem
Me.Text = "Elemento seleccionado: " & Me.lstValores.SelectedItem
Else
' Hay varios, debemos recorrer los distintos elementos
Me.Text = "Elementos seleccionados "
For i As Integer = 0 To Me.lstValores.SelectedItems.Count - 1
Me.Text &= Me.lstValores.SelectedItems(i) & " "
Next
End If
End Sub

A travs de los RadioButton, cambiamos el tipo de seleccin que podemos efectuar en


el control lstValores, como puedes apreciar en el siguiente cdigo fuente.
Private Sub rbtUno_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtUno.CheckedChanged
' establecer tipo de seleccin en el ListBox a un elemento
Me.lstValores.SelectionMode = SelectionMode.One
End Sub
Private Sub rbtMultiple_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtMultiple.CheckedChanged
' establecer tipo de seleccin en el ListBox a un mltiples elementos
Me.lstValores.SelectionMode = SelectionMode.MultiSimple
End Sub
Private Sub rbtExtendida_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles rbtExtendida.CheckedChanged
' establecer tipo de seleccin en el ListBox a mltiples elementos
' de modo extendido
Me.lstValores.SelectionMode = SelectionMode.MultiExtended
End Sub

Mediante los controles chkOrdenar y chkColumnas, ordenaremos y mostraremos en


columnas respectivamente el ListBox.
Private Sub chkOrdenar_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles chkOrdenar.CheckedChanged
' segn el valor del CheckBox, ordenamos o quitamos la opcin de ordenar
' ya que si chkOrdenar.Checked est a True lstValores.Sorted tambin se pondr
' y si est a False no se ordenar
Me.lstValores.Sorted = Me.chkOrdenar.Checked
End Sub

VB.Net (Cap 2. Formularios y Controles)

Pg. 37

Desarrollo de Aplicaciones Multiplataforma


Private Sub chkColumnas_CheckedChanged(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles chkColumnas.CheckedChanged
' segn el valor del CheckBox, mostramos el ListBox en varias columnas o en una
Me.lstValores.MultiColumn = Me.chkColumnas.Checked
End Sub

El TextBox de este formulario lo usaremos para aadir nuevos elementos al ListBox


lstValores, y buscar tambin elementos existentes, pulsando los botones btnAgregar y
btnBuscar en cada caso. Observemos el miembro NoMatches del ListBox, mediante el que
averiguamos si la bsqueda tuvo xito.
Private Sub btnAgregar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAgregar.Click
' aadimos el contenido del TextBox como un elemento a la lista
Me.lstValores.Items.Add(Me.txtValor.Text)
End Sub
Private Sub btnBuscar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnBuscar.Click
Dim posElemento As Integer
If txtValor.Text = "" Then Exit Sub ' Solo busca si hay dato en txtValor
' el mtodo FindString() de la lista busca un valor
posElemento = Me.lstValores.FindString(Me.txtValor.Text)
' el campo NoMatches indica si existe o no el valor buscado
If posElemento = ListBox.NoMatches Then
MessageBox.Show("No existe el valor")
Else
' si encontramos el valor en la lista,nlo seleccionamos por cdigo
Me.lstValores.SelectedIndex = posElemento
End If
End Sub

La seleccin de los elementos de un ListBox no es competencia exclusiva del usuari@. El


programador o programadora puede tambin, si lo necesita, seleccionar valores de la lista
mediante el cdigo del programa. Al pulsar el botn btnSelecCod, utilizaremos el mtodo
SetSelected( ) del ListBox para realizar esta tarea. En este mtodo pasamos como parmetro el
ndice de la lista con el que vamos a operar, y el valor True para seleccionarlo, o False para
quitarle la seleccin.
Private Sub btnSelecCod_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnSelecCod.Click
' para seleccionar elementos de un ListBox por cdigo
' podemos utilizar el mtodo SetSelected()
Me.rbtMultiple.Checked = True
Me.lstValores.SetSelected(1, True)
Me.lstValores.SetSelected(3, True)
End Sub

El botn btnTraspasarSelec lo usaremos para tomar los elementos seleccionados de


lstValores, y pasarlos al otro ListBox del formulario. La propiedad SelectedItems del control
lstValores, devuelve una coleccin con sus elementos seleccionados. Por otra parte, podemos
eliminar los elementos de un ListBox llamando al mtodo Clear( ) de la coleccin de
valores del control, cosa que hacemos pulsando el botn btnLimpiar.
Private Sub btnTrapasarSelec_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnTrapasarSelec.Click
lstTraspaso.Items.Clear()' limpiamos la lista de los elementos que ya tenga
Dim oSeleccion As ListBox.SelectedObjectCollection
' obtenemos con SelectedItems los elementos seleccionados
oSeleccion = Me.lstValores.SelectedItems
' si existen elementos seleccionados, los traspasamos a lstTraspaso
If oSeleccion.Count > 0 Then
' podemos recorrerlo con un For como en lstValores_SelectedIndexChanged

VB.Net (Cap 2. Formularios y Controles)

Pg. 38

Desarrollo de Aplicaciones Multiplataforma


'

Veamos otra forma de hacerlo, recorriendo gracias a la interfaz IEnumerator


Dim oEnumerador As IEnumerator
oEnumerador = oSeleccion.GetEnumerator()
While oEnumerador.MoveNext()
Me.lstTraspaso.Items.Add(oEnumerador.Current)
End While
End If
End Sub

ComboBox
El ComboBox es un control basado en la combinacin (de ah su nombre) de dos controles
que ya hemos tratado: TextBox y ListBox.
Un control ComboBox dispone de una zona de edicin de texto y una lista de valores, que
podemos desplegar desde el cuadro de edicin.
El estilo de visualizacin por defecto de este control, muestra el cuadro de texto y la
lista oculta, aunque mediante la propiedad DropDownStyle podemos cambiar dicho estilo. La
siguiente figura muestra un formulario con diversos ComboBox, cada uno con diferente estilo.

Controles ComboBox de distintos estilos

La propiedad DropDownStyle tambin influye en una diferencia importante de


comportamiento entre el estilo DropDownList y los dems, dado que cuando creamos un
ComboBox con el mencionado estilo, el cuadro de texto slo podr mostrar informacin, no
permitiendo que esta sea modificada.
En el caso de que la lista desplegable sea muy grande, mediante la propiedad
MaxDropDownItems, asignaremos el nmero de elementos mximo que mostrar la lista del
control.
El resto de propiedades y mtodos son comunes con los controles TextBox y ListBox. En el
siguiente cdigo fuente se muestra el cdigo del botn btnAgregar, mediante el que llenamos de
valores los controles de este ejemplo
Private Sub btnAgregar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAgregar.Click
Me.cboColores.Items.AddRange(New String() {"AZUL", "VERDE", "AMARILLO",
"ROJO", "BLANCO", "MARRN", "GRANATE"})
Me.cboNombres.Items.AddRange(New String() {"ELENA", "JOSE", "ANA", "ALFREDO",
"LUIS", "ANGEL", "RAQUEL"})
Me.cboCiudades.Items.AddRange(New String() {"SEVILLA", "VALENCIA", "ALICANTE",
"TOLEDO", "SEGOVIA"})
End Sub

VB.Net (Cap 2. Formularios y Controles)

Pg. 39

Desarrollo de Aplicaciones Multiplataforma

PictureBox
Se dice que una imagen vale ms que mil palabras y, de hecho, muchos programas las
utilizan para transmitir informacin. Hay varias maneras de mostrar imgenes en VB.Net: la
ms comn es utilizando un control PictureBox.
Los controles PictureBox actan como un contenedor para las imgenes; se elige la imagen
que se va a mostrar estableciendo la propiedad Image. Como casi siempre podemos La
establecer esta propiedad en la ventana Propiedades o escribiendo el cdigo para decirle al
programa qu imagen se va mostrar.
Antes de agregar una imagen a un control PictureBox, generalmente se agregar el archivo
de imagen al proyecto como un recurso. Una vez que se agrega un recurso al proyecto,
podremos volver a utilizarlo cuantas veces lo deseemos. Observa el formulario de ejemplo, en el
cual hemos puesto la misma imagen en todos los controles.
As que para aadir una imagen vete a la propiedad Image (en la ventana de propiedades) y
pulsa sobre el icono de seleccin:

Nos aparecer una ventana como la que se muestra a continuacin, en la cual podemos
seleccionar la imagen solo para este recurso (en Recurso local), o an mejor en Archivo de
recursos, como puedes ver aqu:

Otra propiedad til para el control PictureBox es SizeMode, que se puede utilizar para
expandir, centrar o ampliar la imagen dentro del control PictureBox y que puede coger los
siguientes valores.

Observa el siguiente ejemplo en el que todos los controles tienen la misma imagen, pero con
distinto modo.
Nota. En todos los controles he puesto la propiedad BorderStyle a FixedSingle para que se
vea bien cmo es y qu tamao tiene el control. Si te fijas el de la derecha ni siquiera entra en el
formulario.

VB.Net (Cap 2. Formularios y Controles)

Pg. 40

Desarrollo de Aplicaciones Multiplataforma

Y por ltimo, cmo haremos si lo que deseamos es modificar una imagen de control pero
dependiendo de lo que elija el/la usuaria? O lo que es lo mismo, si queremos poner una imagen
en un control en tiempo de ejecucin. En ese caso necesitaremos conocer el nombre del fichero
que contiene la imagen (nombre con toda la ruta). E:\Fotos\Flores.jpg.
Tendremos varias formas de permitirle al o a la usuaria que lo haga, y generalmente
elegiremos el tpico Cuadro de Dilogo de Abrir, pero en este momento eso excede de nuestro
conocimiento, por lo que, tambin podramos hacer que se escribiera la ruta en una caja de
texto.

Por tanto, si dejamos que sea en la caja de texto donde introduce el nombre, con ruta, de la
imagen podramos hacer:
Private Sub btnCambiarImagen_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCambiarImagen.Click
' Carga la imagen del fichero con nombre en la caja de texto
' Ejemplo: E:\Flores\amapola.jpg
Me.picFotoZoom.Image = Image.FromFile(txtImagen.Text)
End Sub

VB.Net (Cap 2. Formularios y Controles)

Pg. 41

Desarrollo de Aplicaciones Multiplataforma

Anclaje de controles
La propiedad Anchor, existente en un gran nmero de controles, nos permite anclar
dicho control a uno o varios bordes del formulario.
Cuando un control es anclado a un borde, la distancia entre el control y dicho borde ser
siempre la misma, aunque redimensionemos el formulario.
Para establecer esta propiedad, debemos pasar a la ventana de propiedades del control, y en
Anchor, pulsar el botn que dispone, y que nos mostrar una representacin de los bordes para
anclar.

Propiedad Anchor de un control.

Las zonas de color gris oscuro representan los bordes del control que ya estn anclados a
los bordes del formulario. Debemos marcar y desmarcar respectivamente estos elementos segn
los bordes que necesitemos anclar. Por defecto, los controles se encuentran inicialmente
anclados a los bordes superior e izquierdo (Top, Left), como hemos comprobado en la anterior
figura.
La figura muestra un ejemplo en el que vemos dos controles que tienen distintos tipos de
anclaje. Button1 tiene el anclaje normal: Top-Left, mientras que Button2 tiene slo Right, por
ello, su borde derecho siempre mantendr la misma distancia con ese borde del formulario

Al cambiar el tamao del formulario los botones se quedan anclados en el borde expresado

Acople de controles
A travs de la propiedad Dock de los controles, podremos acoplar un control a uno de los
bordes de un formulario, consiguiendo que dicho control permanezca pegado a ese borde del
formulario en todo momento.
Para seleccionar el tipo de acople, haremos clic en el botn que tiene la propiedad Dock en
la ventana de propiedades, y que nos mostrar un gua de los tipos de acople disponibles.

VB.Net (Cap 2. Formularios y Controles)

Pg. 42

Desarrollo de Aplicaciones Multiplataforma

Por defecto, los controles no se encuentran acoplados al insertarse en el formulario, y slo es


posible establecer un tipo de acople en cada ocasin. La imagen de la izquierda muestra un
control Button acoplado a la izquierda del formulario y para la de la derecha hemos pulsado en
la propiedad Dock el botn central de los indicadores de acoplamiento, con lo que la propiedad
tomar el valor Fill, es decir, el control llenar toda la superficie del formulario.

El botn de la izquierda est acoplado a la izquierda y el de la derecha al centro (Fill).

Orden de tabulacin de controles


Los controles disponen de la propiedad TabIndex, que contiene un nmero que ser
utilizado para pasar el foco entre ellos al pulsar la tecla [TAB] durante la ejecucin del
programa.
Segn vamos aadiendo nuevos controles, el IDE va asignando automticamente nuevos
nmeros a esta propiedad; de forma que, cuando comencemos la ejecucin, el primer control
que tomar el foco ser el que tiene el menor nmero en su TabIndex.
Cuando deseemos cambiar este orden lo haremos modificando los valores de la propiedad
TabIndex de los controles, de modo que el orden de tabulacin sea el que mejor se adapte a
nuestras necesidades.
Podemos obtener un mapa del orden de tabulacin de los controles del formulario
seleccionando el men del IDE Ver + Orden de tabulacin; esto mostrar los controles con el
nmero de TabIndex que les hemos asignado. Como ventaja adicional, en esa situacin,
podemos hacer clic en los controles y cambiar tambin el nmero de tabulacin.

Diseador del formulario mostrando el orden de tabulacin de controles.

Si por el contrario, no queremos dar el foco a un control pulsando [TAB], debemos asignar a
la propiedad TabStop de dicho control el valor False. Por defecto, TabStop vale True,
permitiendo de esta el paso de foco entre controles mediante la tecla [TAB]

VB.Net (Cap 2. Formularios y Controles)

Pg. 43

Desarrollo de Aplicaciones Multiplataforma

Cap 3. El lenguaje
Variables, definicin y entorno
En VB.Net se pueden usar variables para almacenar valores temporalmente durante la
ejecucin de una aplicacin. Las variables tienen un nombre (la palabra que utilizaremos para
referirnos al valor que contiene la variable) y un tipo de dato (que determina la clase de datos
que la variable puede almacenar)
VB.Net distingue entre maysculas y minsculas pero dependiendo de la declaracin que le
demos a la variable o/y control siempre la escribir as, lo cual es muy til para ver si realmente
la estamos escribiendo bien. Observa que a medida que escribimos (al finalizar cada palabra)
automticamente VB la reescribe como est definida.
Ejemplo: Supongamos que hemos declarado la variable Edad y la caja de texto txtEdad y en
nuestro programa escribimos la palabra edad o txtedad VB.Net, automticamente las reescribir
como estaban al comienzo (en estos casos con las E en maysculas), por lo que si nos
equivocamos y escribimos txtfedad al no reescribir nada en maysculas veramos que algo
hemos escrito mal.
De ah la importancia de jugar con maysculas y minsculas en las declaraciones de todos
nuestros controles y/o variables.
Es por todo lo anterior que VB.Net, de forma generalizada en la comunidad de
programador@s, opta por usar las denominadas Notacin Camel (Camello) a la hora de declarar
cualquier identificador (variable, control, clase, objeto, ).

Notacin Camel
La notacin Camel consiste en escribir los identificadores con la primera letra de cada
palabra en maysculas y el resto en minscula: EndOfFile. Se llama notacin Camel porque
los identificadores recuerdan las jorobas de un camello. Existen dos variantes:

CursosInstituto, CarValidos o CamelCase: en esta variante la primera letra


tambin es mayscula.
txtNombre, nomCurso o dromedaryCase: la primera letra es minscula.

Usaremos la notacin CamelCase en identificadores para clases, as como para sus


propiedades y mtodos al estilo de los controles: Tenemos la clase Button, las propiedades
AutoSize y los mtodos SelectNextControl
Y en cambio para los controles hemos utilizado la notacin Hngara (es decir,
dromedaryCase en la que los primeros caracteres identifican el control); como por ejemplo
txtNombre, btnAceptar o frmEntradaDatos.
En el caso de las variables si son globales tenderemos a la primera forma (camel) y si son
locales o parmetros a la segunda: Ejemplo NombrePersona, Edad y nombrePersona o edad.
Function AreaTriangulo(ByVal base As Integer, ByVal altura As Integer) As Integer
' nombre de la funcin en Camel, parmetros dromedary
' variables locales como area en dromedary
Dim area As Integer
area = base * altura / 2
Return area
End Function

VB.Net (Cap 3. El lenguaje)

Pg. 45

Desarrollo de Aplicaciones Multiplataforma

El nombre de una variable puede ser tan largo como queramos, hasta un mximo de 40
caracteres. En la versin VB.Net para Espaa se pueden usar incluso la y vocales acentuadas.
El nombre de una variable siempre debe comenzar por una letra o el guin bajo (_curso) y luego
puede ir seguido de letras, nmeros o guiones.
En el caso de las constantes, se
Atencin: En el caso de las constantes, se tiende a escribirla entera en maysculas: PI,
INSTITUTO, . para distinguirlas de las variables.
La declaracin de una variable es el proceso por el cual comunicamos al compilador que
vamos a crear una nueva variable en el programa.
Para declarar una variable utilizaremos la palabra clave Dim, Static, Private o Public
(dependiendo del lugar donde declaremos la variable y el mbito que queramos darle) seguida
del identificador o nombre que daremos a dicha variable.
Public Area As Integer ' variable global y pblica
Private Nombre As String ' variable global y privada
Function AreaTriangulo(ByVal base As Integer, ByVal altura As Integer) As Integer
Dim area As Integer ' variable local, se declara en cada llamada
'...
End Function
Sub LLamadas()
Static numVeces As Integer ' local, mantiene el valor anterior
numVeces += 1
MessageBox.Show(numVeces)
End Sub

Tipos de datos primitivos


Las variables pueden ser de los siguientes tipos: (El nmero indicado en segundo lugar
indica el nmero de Bytes que ocupa en memoria.)
La Tabla siguiente muestra la relacin de tipos de datos disponibles en el lenguaje.
Tipo de dato
en VB.NET

Tipo correspondiente en
el entorno de .NET
Framework

Tamao
(bytes)

Rango de valores

Boolean

System.Boolean

True o False (Verdadero o Falso)

Byte

System.Byte

0 a 255 (sin signo)

Char

System.Char

0 a 65535 (sin signo)

Date

System.DateTime

1/ enero/1 a 31/diciembre/ 9999

Integer

System.Int32

-2.147.483.648 a 2.147.483.647

Long (entero
largo)
Short

System.Int64

System.Int16

-9.223.372.036.854.775.808
9.223.372.036.854.775.807
-32.768 a 32.767

Single (punto
flotante con
precisin simple)
Decimal

System.Single

System.Decimal

12

VB.Net (Cap 3. El lenguaje)

-3,402823E38 a 1,401298E-45 para


valores
negativos;
1,401298E-45
a
3,402823E38 para valores positivos
+/- 79.228.162.514.264.337.593.543.950.335 sin
punto decimal;
+/-7,9228162514264337593543950335
con 28 posiciones a la derecha del signo
decimal;

Pg. 46

Desarrollo de Aplicaciones Multiplataforma

Double
System.Double
(punto flotante con
precisin doble)

Object

System.Object

String (cadena
delongitud
variable)

System.String

-1,79769313486232E308 a
-4,94065645841247E-324 para valores
negativos; 4,94065645841247E-324 a
1,79769313486232E308 para valores positivos
Cualquier tipo

10 + Desde 0 a unos 2.000 millones de


(2 *
caracteres Unicode
longitud
cadena)

Si al declarar una variable no indicamos el tipo, por defecto tomar Object, que corresponde
al tipo de datos genrico en el entorno del CLR, y admite cualquier valor.
Segn lo visto, si declaramos una variable de tipo Byte e intentamos asignarle el valor 5899
se va a producir un error, ya que no se encuentra en el intervalo de valores permitidos para esa
variable. Esto puede llevar a preguntarnos: por qu no utilizar siempre Object y poder usar
cualquier valor?, o mejor para qu necesitamos asignar tipo a las variables?.
El motivo de tipificar las variables reside en que cuando realizamos una declaracin, el CLR
debe reservar espacio en la memoria para los valores que pueda tomar la variable. Si adems,
declaramos todas las variables como Object, los gastos de recursos del sistema sern mayores
que si establecemos el tipo adecuado para cada una, ya que como el CLR no sabe el valor que
puede tomar en cada ocasin la variable, debe realizar un trabajo extra de adecuacin,
consumiendo una mayor cantidad de recursos.
VS.NET dispone de una ayuda al asignar el tipo a una variable, que nos muestra la lista de
tipos disponibles para poder seleccionar uno sin tener que escribir nosotros el nombre. Al
terminar de escribir la palabra As, aparecer dicha lista, en la que pulsando las primeras letras
del tipo a buscar, se ir situando en los ms parecidos. Una vez encontrado, pulsaremos la tecla
Enter o Tab para aceptarlo.

Declaracin mltiple en lnea


En el caso de que tengamos que declarar ms de una variable del mismo tipo, podemos
declararlas todas en la misma lnea, separando cada una con una coma e indicando al final de
la lista el tipo de dato que van a tener.
Public Nombre, Apellidos, Localidad As String

Con esta tcnica de declaracin, todas las variables de la lnea tienen el mismo tipo de dato,
ya que no es posible declarar mltiples variables en la misma lnea que tengan distintos tipos de
dato.

Asignacin de valor
Para asignar un valor a una variable utilizaremos el operador de asignacin: el signo
igual ( = ), situando a su izquierda la variable a asignar, y a su derecha el valor.
En el caso de que queramos inicializar la variable en el momento de la declaracin, debemos
separar cada declaracin en una lnea, aunque coincidan en el valor de inicializacin:
Private num As Integer = 5 ' usaremos lneas independientes
Private edad As Integer = 5

Segn el tipo de dato de la variable, puede ser necesario el uso de delimitadores para
encerrar el valor que vamos a asignar.
Tipos numricos. Las variables de tipos de datos numricos no necesitan
delimitadores, se asigna directamente el nmero correspondiente. Si necesitamos
especificar decimales, utilizaremos el punto ( . ) como carcter separador para los
decimales

VB.Net (Cap 3. El lenguaje)

Pg. 47

Desarrollo de Aplicaciones Multiplataforma

Cadenas de caracteres. En este caso es preciso encerrar la cadena entre comillas


dobles ( " ).
Fechas. Al asignar una fecha a una variable de este tipo, podemos encerrar dicho
valor entre el signo de almohadilla ( # ) o comillas dobles ( " ). El formato de fecha a
utilizar depende del delimitador. Cuando usemos almohadilla la fecha tendr el
formato Mes/Da/Ao; mientras que cuando usemos comillas dobles el formato ser
Da/Mes/Ao. Las fechas pueden contener adems informacin horario que
especificaremos en el formato Hora:Minutos:Segundos FranjaHoraria. En el caso de
que no indiquemos la franja horaria (AM/PM) y si estamos utilizando el signo
almohadilla como separador, el entorno insertar automticamente los caracteres de
franja horaria correspondientes.
Tipos lgicos. Las variables de este tipo slo pueden tener el valor True (Verdadero)
o False (Falso)
Dim Instituto As String = "Cuatrovientos"
Dim Importe As Decimal = 2500.23
Dim fechaCreacion As Date = #5/20/2001# ' mes/da/ao
Dim FechaEntrada As Date = "23/01/2000" ' dia/mes/ao
Dim fechaCompleta As Date = #10/18/2001 9:30:00 AM#
Dim fechaCompletaDos As Date = "7/11/2001 14:22:00"
Dim hora As Date = #5:40:00 PM#
Dim Correcto As Boolean = True

Valor inicial
Toda variable declarada toma un valor inicial por defecto, a no ser que realicemos una
asignacin de valor en el mismo momento de la declaracin. A continuacin se muestran
algunos valores de inicio en funcin del tipo de dato que tenga la variable:
Numrico. Cero ( 0 ).
Cadena de caracteres. Cadena vaca ( "" ).
Fecha. 01/01/0001 0:00:00.
Lgico. Falso (False).
Objeto. Valor nulo (Nothing).
Por otro lado podemos, inversamente, inicializar una variable que ya tiene valor,
asignndole la palabra clave Nothing; con ello, la variable pasa a tener el valor por defecto o
inicial.
Dim Valor As String
Dim FechaActual As Date
Dim ValorLogico As Boolean
' asignar valores a variables
Valor = "mesa"
FechaActual = "10/8/2001"
ValorLogico = True
' inicializar de nuevo las variables a los valores por defecto
Valor = Nothing
FechaActual = Nothing
ValorLogico = Nothing

VB.Net (Cap 3. El lenguaje)

Pg. 48

Desarrollo de Aplicaciones Multiplataforma

mbito de las variables


El mbito de variables consiste en la capacidad de acceso que tenemos hacia una variable,
de forma que podamos obtener su valor, as como asignarlo.
Aunque hay ms posibilidades, vamos a comenzar con las que vamos a utilizar
inicialmente.
En un Formulario, clase o mdulo, una variable la declararemos en la seccin de
declaraciones, que se encuentra al comienzo de la ventana de cdigo de una de las 2 formas
siguientes: Private o Public. Si se declara Privada, esa variable ser global para todos los
procedimientos y funciones del formulario, pero local respecto a otros formularios o mdulos,
ya que no se puede acceder a ella fuera del formulario. Si se declara como Pblica, se podr
acceder a ella desde cualquier formulario o mdulo de la aplicacin.
Si la variable se ha declarado en un formulario y se utiliza en otro deberemos
especificar el nombre del formulario seguido del nombre de la variable
(Formulario.Variable).
Si la variable pblica est declarada en un Mdulo se podr usar en todo el programa
sin necesidad de especificar el mdulo en que est declarada.
Si es a nivel de clase, entonces Mejor ya lo veremos cuando nos metamos con
POO.
Ejemplo. Supongamos que tenemos un formulario frmPrincipal con las siguientes
declaraciones de variables y procedimientos:
Public Edad As Byte ' Se puede acceder a ella desde otros formularios
Private Direccin As String ' Se puede acceder a ella desde todos los
procedimientos
' o funciones de este formulario, pero no desde otros formularios
Private Sub UsoVariables()
Static nVeces As Integer ' Solo se puede acceder desde este procedimiento. Se
inicializa solo
' la primera vez que se ejecuta el subprograma
Dim num As Integer ' se inicializa cada vez que se ejecuta este subprograma
num += 1 ' siempre valdr 1
nVeces += 1 ' cada vez que se ejecute btnAceptar_Click se sumar 1
Edad = 20
Direccin = "Calle San Jorge s/n"
End Sub
Private Sub OtroSub()
' Aqu puedo acceder a Edad, Direccin

pero no a nVeces ni a num

End Sub

Si ahora estamos en otro formulario, ejemplo frmDatos no podremos usar ninguna de las
variables privadas num, nVeces o Direccin.
Private Sub DesdeOtroForm()
' Puede acceder a Edad pero debe saber que es del otro formulario
frmPrincipal.Edad = 20
frmPrincipal.Direccin = "Calle San Jorge s/n" ' ERROR. No puede acceder
End Sub

De todas formas recuerda que el VS.Net tenemos ayuda para todo, incluso en el momento en
que estamos escribiendo. Observa la siguiente imagen:

VB.Net (Cap 3. El lenguaje)

Pg. 49

Desarrollo de Aplicaciones Multiplataforma

Ayuda en tiempo de diseo

Como ya hemos indicado VB.Net inicializa las variables en el momento de la declaracin, y


por supuesto estas inicializaciones dependern del mbito de declaracin. Si una variable es
pblica (global a todo el proyecto), privada de un mdulo o formulario o esttica en un
procedimiento o funcin, se inicializar una nica vez mientras que si es privada a un
procedimiento o funcin se inicializar cada vez que se invoque dicho procedimiento o funcin.

Perodo de vida o duracin de las variables


El periodo de vida de una variable es el tiempo durante el cual la variable est activa,
ocupando el espacio de memoria que le ha asignado el CLR, y disponible para ser utilizada. El
periodo de vida de una variable depende de su mbito, de forma que podemos clasificarlos
como se muestra a continuacin.
mbito de bloque. El periodo de vida de estas variables se desarrolla desde el
momento en que son declaradas dentro del bloque y hasta que dicho bloque finaliza.
Esto lo veremos ms adelante.
mbito de procedimiento. Para estas variables, su periodo de vida est comprendido
entre el momento en que son declaradas y hasta que la ejecucin del procedimiento
termina.
mbito a nivel de mdulo y proyecto. En este caso, el periodo de vida de la
variable va desde el comienzo de la ejecucin de la aplicacin y hasta que esta
termina.

Constantes
Existen dos tipos de constantes:

Constantes intrnsecas o definidas por el sistema proporcionadas por aplicaciones y


controles. Las constantes de VS.Net generalmente nos aparecern en el momento de
intentar acceder a ellas.

Las constantes definidas por el usuario o usuaria y que se declaran mediante la


instruccin Const.

VB.Net (Cap 3. El lenguaje)

Pg. 50

Desarrollo de Aplicaciones Multiplataforma

La sintaxis para declarar una constante es la siguiente: (Atencin, cuando ponemos [] en la


sintaxis quiere decir que esas partes son optativas, no que se escriban entre [] en el caso de optar
por ellas, y la | que se puede elegir entre las dos opciones).
[Public|Private] Const NOMBRE_CONSTANTE[As tipo] = expresin
El argumento NOMBRE_CONSTANTE debe ser un nombre vlido (recuerda que las
constantes las declararemos en maysculas) y expresin est compuesta por constantes y
operadores de cadena o numricos; sin embargo, no se pueden usar llamadas a funciones en
expresin. Generalmente el tipo no se escribe, pues viene implcito con el valor.
Const PI = 3.1416
Public Const MAX = 100
Const FECHA_SALIDA = #1/1/2002#
Const CLAVE = "DAI"

Se puede colocar ms de una declaracin de constante en una nica lnea si se separa con
comas:
Public Const PI = 3.14, MAXPLANETAS = 9, DISTANCIA_PLANETA = 1.5E+19

A menudo, la expresin del lado derecho del signo igual ( = ) es un nmero o cadena literal,
pero tambin puede ser una expresin que d como resultado un nmero o una cadena. Se puede
incluso definir constantes en trminos de constantes previamente definidas:
Const PI2 = PI * 2

Alcance de las constantes definidas por el usuario


Una instruccin Const tiene igual alcance que una declaracin de variable y se le aplican las
mismas reglas. Si no se especifica mbito, es local al lugar donde se define, y para definirla
como pblica solo se podr hacer en un mdulo.
Public Const PI = 3.1416 ' Obligatoriamente en mdulo
Const MAX = 1000 ' Solo se podr usar en el mdulo, formulario, procedimiento o
funcin en que se define

Operadores
Aritmticos: +, - ,*, / (divisin real), \ (divisin entera), Mod (resto), ^ (potencia) y
los operadores abreviados +=, -=, ^=. Estos ltimos los veremos un poquito ms
adelante, con la instruccin de asignacin.
Alfanumricos: & y +. Ambos indican lo mismo, concatenacin de cadenas.
Relacionales: =, <>, <, >, <=, >=, Like
Lgicos: Not (ser lo contrario del operando. True->False y viceversa), And (sera
cierto si lo son los dos operandos), Or (cierto si lo es 1 de los operandos), Xor (cierto
si es uno y solo uno de los operandos), AndAlso (semejante a And pero si el 1 es
False ya no sigue evaluando) y OrElse (semejante a Or pero si el primero es True ya
no sigue evaluando).
Ejemplos:
Dim Num1, Num2 As Integer, Cad As String, Positivo As Boolean
Num1 = Num2 * 3 ' Operador aritmtico, Num1 valdr el triple que Num2
If Num1 Mod 2 = 0 Then
' Estamos preguntando si el Resto de Num entre 2 es 0, es decir, si Num es par
Positivo = Num1 > 0 ' La variable Positivo guardar True si Num es > 0 y
False en otro caso
If Cad = "Hola" Or Cad = "Adios" Then ' Pregunta si Cad vale uno de esos dos
valores

VB.Net (Cap 3. El lenguaje)

Pg. 51

Desarrollo de Aplicaciones Multiplataforma

Cuando en una expresin aritmtica intervienen operandos de diferentes tipos, el resultado se


expresa, generalmente, en la precisin del operando con mayor precisin. El orden, de menor a
mayor, segn la precisin, es Byte, Integer, Long,
Los operandos relaciones, tambin conocidos como operadores de comparacin, comparan
dos expresiones dando un resultado True, False.
Por defecto, el comportamiento de estos operadores para datos alfanumricos es la llamada
comparacin binaria es decir, las letras maysculas se consideran distintas de las minsculas.
Dim Instituto As String
Instituto = txtInstituto.Text ' Supongamos que tiene la cadena Cuatrovientos
If Instituto = "CUATROVIENTOS" Then
MessageBox.Show("Es nuestro instituto")
Else
MessageBox.Show("Otro instituto")
' Mostrara este mensaje, pues se
consideran distintos caracteres
End If

Para considerarlas iguales tenemos varias posibilidades.


Podemos pasar los datos a maysculas (o minsculas), mediante el mtodo ToUpper o
ToLower que tienen todos los String.
If Instituto.ToUpper = "CUATROVIENTOS" Then
MessageBox.Show("Es nuestro instituto") ' Ahora si los consdiera iguales
Else
MessageBox.Show("Otro instituto")
End If

O bien usar la funcin StrComp que veremos ms adelante.


If StrComp(Instituto, "CUATROVIENTOS", CompareMethod.Text) = 0 Then

Diferencia entre And y AndAlso as como entre Or y OrElse


En el caso de los operadores iniciales And y Or, siempre se evala la condicin entre los 2
elementos de la expresin, mientras que en los compuestos AndAlso y OrElse se comienza
evaluando la primera parte de la expresin y solo si esta es True en el caso de AndAlso o False
en el caso de OrElse se evala la segunda parte.
Hay ocasiones en que esta diferencia puede influir en que un programa se rompa o no.
Supongamos que tenemos definida la siguiente variable:
Dim num As String

Vamos a incluir un cdigo que se deba ejecutar solo si el valor de la variable es numrico y
positivo. En ese caso pondramos algo semejante a:
If IsNumeric(num) And num > 0 Then ' Se rompe en el caso de que num no sea nmero
' Instrucciones del Then
Else
' Instrucciones del Else
End If
If IsNumeric(num) AndAlso num > 0 Then

Si la variable contiene un nmero en los dos casos funcionara igual, si es positivo hara lo
que se encuentre en el Then y si es negativo o 0 las instrucciones del Else.
Pero qu ocurre si la variable nunca ha recibido valor (estara con la cadena vaca ) o un
valor que no se pueda convertir a numrico (ejemplo hola)? En ese caso en el primer ejemplo,
y dado que debe hacerse ambas preguntas, al comparar (string) con 0 (numrico) se
romper. Sin embargo, en el segundo caso, al ver que no es numrico (primera parte False) ni
siquiera intenta hacer la segunda pregunta.

VB.Net (Cap 3. El lenguaje)

Pg. 52

Desarrollo de Aplicaciones Multiplataforma

Igualmente ocurre con los Or. Si en el siguiente ejemplo ponemos Or y la resp no es


numrica se rompe, pero con OrElse ni siquiera intentar hacer la pregunta resp<0?
Dim resp As String
Do
resp = InputBox("Introduce un nmero positivo")
Loop While Not IsNumeric(resp) OrElse resp < 0

Prioridad de operadores
Dentro de una lnea de cdigo que contenga varias operaciones, estas se resolvern en un
orden predeterminado conocido como prioridad de operadores. Dicha prioridad se aplica tanto
entre los operadores de un mismo grupo como entre los distintos grupos de operadores.
Los operadores aritmticos se ajustan a la prioridad indicada en la siguiente tabla,
considerando que la prioridad va de mayor a menor, es decir, la potencia se ejecuta antes que
la suma..
Prioridad de operadores aritmticos
Potenciacin ( ^ )
Negacin ( - )
Multiplicacin y divisin real ( * , /)
Divisin entera ( \ )
Resto de divisin ( Mod )
Suma y resta ( + , - )

El operador de mayor prioridad es el de potenciacin, los de menor son la suma y resta. En


el caso de operadores con idntica prioridad como multiplicacin y divisin, se resolvern en
el orden de aparicin, es decir, de izquierda a derecha. Ejemplo:
Dim res As Integer
res = 5 + 3 ^ 2 * 4 - 2

' resultado toma el valor 39

Los operadores de comparacin tienen todos la misma prioridad, resolvindose en el orden


de aparicin dentro de la expresin.
Los lgicos se ajustan a la prioridad indicada en la tabla:
Prioridad de operadores lgicos
Negacin (Not)
Conjuncin (And, AndAlso)
Disyuncin (Or, OrElse, Xor)
Dim valido As Boolean
valido = 10 < 70 And Not 30 = 20 ' el resultado es True

Y por ltimo, cuando una expresin contenga operadores de distintos grupos, estos se
resolvern en el siguiente orden.
Prioridad entre operadores de distintos grupos
Aritmticos
Concatenacin
Comparacin
Lgicos
Dim Resultado As Boolean
Resultado = 30 + 5 * 5 > 100 And 52 > 10
' devuelve: False

Uso de parntesis para alterar la prioridad de operadores


Podemos alterar el orden natural de prioridades entre operadores utilizando los parntesis,
encerrando entre ellos los elementos de una expresin que queramos sean resueltos en

VB.Net (Cap 3. El lenguaje)

Pg. 53

Desarrollo de Aplicaciones Multiplataforma

primer lugar. De esta forma, se resolvern en primer lugar las operaciones que se encuentren en
los parntesis ms interiores, finalizando por las de los parntesis exteriores. Es importante tener
en cuenta, que dentro de los parntesis se seguir manteniendo la prioridad explicada
anteriormente.
El cdigo siguiente en condiciones normales, devolvera False como resultado. Sin embargo,
gracias al uso de parntesis, cambiamos la prioridad predeterminada, obteniendo finalmente
True.
Dim Resultado As Boolean
Resultado = ((30 + 5) * 5 > 100) And (52 > 200 / (2 + 5)) ' devuelve: True

Comentarios
Como ya hemos visto en todos los ejemplos anteriores en VB.Net cada lnea de comentario
comienza con un apstrofo ('). Ejemplo:
' Esto es un comentario

Es muy cmodo utilizar los iconos Bloque con comentarios y Bloque sin comentarios
para, si hemos seleccionado un conjunto de instrucciones, poner o quitar el a todo ese
conjunto de instrucciones, convirtindolas /retirndolas por tanto en comentarios.
Ejemplo: Si tenemos seleccionado el texto que aparece en la figura y pulsamos el botn
Bloque con comentarios automticamente se escribir como aparece a la derecha.

Instrucciones en VB.Net
En principio en VB.Net cada instruccin se escribe en una y solo una lnea.
Si deseamos escribir dos instrucciones en una misma lnea deberemos separarlas por el
carcter :
Ejemplo.
pal = "hola" :

n = 2

Por lo mismo, si deseamos cortar una instruccin para que ocupe ms de una lnea debemos
aadir el carcter _.
Ejemplo. Deseamos asignar una concatenacin de cadenas en una caja de texto, y queremos
romper la lnea.
txtDireccin.Text = txtCalle.Text & " " & txtNum.Text & " " & _
txtPiso.Text & " " & txtLetra.Text

VB.Net (Cap 3. El lenguaje)

Pg. 54

Desarrollo de Aplicaciones Multiplataforma

Asignacin (=) y operadores abreviados +=, *=, -=. /=, &=


La asignacin en VB.Net es el operador =. Se utiliza para asignar un valor a una variable o a
una propiedad de un control.
Ejemplos:
num = 3 ' Asigna a num el valor 3
txtEdad.Text = 30 ' Se muestra en la caja de texto txtEdad el valor 30
Negrita = False ' Negrita (booleana) toma el valor False
lblTotal.Caption = Precio * Cantidad ' En lblTotal aparece el valor del producto

Incluso podemos hacer cosas como esta:


nVeces = nVeces + 1

Con esto, estamos indicndoles al VB que: calcula lo que actualmente vale la variable
nVeces , smale 1 y el resultado de esa suma, lo guarda de nuevo en la variable nVeces..
Por tanto, suponiendo que nVeces valiese 10, despus de esta asignacin, su valor ser 11,
(es decir 10 que vala antes ms 1 que le sumamos).
Esto ltimo se llama incrementar una variable, y el vb.NET tiene su propio operador para
estos casos, es decir cuando lo que asignamos a una variable es lo que ya haba antes ms el
resultado de una expresin:
nVeces += 1

Aunque tambin se pueden usar: *=, /=, -=, etctera, dependiendo de la operacin que
queramos hacer con el valor que ya tuviera la variable.
Por tanto i = i * 2, es lo mismo que i *= 2

Instruccin Condicional simple y mltiple: If


Esta instruccin permite ejecutar condicionalmente una o varias instrucciones, dependiendo
de si el resultado de evaluar una condicin es o no cierto.
La sintaxis de esta estructura puede aplicarse de diferentes formas en funcin del tipo de
decisin a resolver.
Si queremos que la instruccin ocupe una sola lnea utilizaremos la siguiente sintaxis:
If condicin Then [instrucciones] [Else instrucciones_else]
Ejemplos:
If txtNombre.Text = "" Then Exit Sub ' Este uso es muy tpico y cmodo
If n>2 Then n = n + 1 : text1.text = n Else text1.text = Menor que 2

Si deseamos escribir en ms de una lnea (lo habitual) debemos indicar el final del If con su
correspondiente End If. Observa adems que en VB el If tiene tres posibilidades, solo la parte
del Then, con Then y Else o con la opcin ElseIf, siempre que se escriba junto. Si lo separamos
estamos entrando en un segundo If que por tanto necesitar su propio End If.
If condicin Then
instrucciones
End If

If condicin Then
instrucciones
Else
instrucciones_else
End If

If condicin Then
instrucciones
ElseIf condicin-n Then
instrucciones_elseif
[Else
[instrucciones_else]
End If

La condicin es generalmente una expresin booleana, pero puede ser cualquier expresin
que pueda ser evaluada a un valor numrico, ya que un valor 0 es considerado como False y un
valor <> 0 como True. Si la condicin es verdadera se ejecutan las sentencias que estn a

VB.Net (Cap 3. El lenguaje)

Pg. 55

Desarrollo de Aplicaciones Multiplataforma

continuacin de Then y si la condicin es falsa las que estn a continuacin del Else si esta
clusula ha sido especificada o nada en caso contrario.
Ejemplos:
' If sin Else
If Not IsNumeric(txtNum.Text) Then
MessageBox.Show("Dato errneo")
txtNum.SetFocus()
Exit Sub
End If
' If con ElseIf y con Else
If txtNum.Text > 0 Then
MessageBox.Show("Positivo")
ElseIf txtNum.Text < 0 Then
MessageBox.Show("Negativo")
Else
MessageBox.Show("Vale 0")
End If
' If con Else
If txtNum.Text Mod 2 = 0 Then
MessageBox.Show("Par")
Else
MessageBox.Show("Impar")
End If

Condicional mltiple: Select Case


Esta instruccin permite ejecutar una de varias acciones en funcin del valor de una
expresin. Es una alternativa al If cuando lo que se necesita es comparar la misma expresin
con diferentes valores.
Su sintaxis es:
Select Case expresin_prueba
Case lista_expresin-1
instrucciones-1
[Case lista_expresin-n
[instrucciones-n]] ...
[Case Else
[instrucciones_else]]
End Select
La sintaxis de la instruccin Select Case consta de las siguientes partes:
expresin_prueba: Cualquier expresin numrica o de cadena.
lista_expresin-n: Lista delimitada por comas de una o ms de las formas siguientes:
expresin, expresin To expresin, Is expresin operador_de_comparacin. La
palabra clave To especifica un intervalo de valore. Se usa la palabra clave Is con
operadores de comparacin, para especificar un intervalo de valores. Si no se escribe,
la palabra clave Is se insertar automticamente.
instrucciones-n: Una o ms instrucciones a ejecutar si expresin_prueba coincide con
cualquier parte de lista_expresin-n.
instrucciones_else: Opcional. Una o ms instrucciones que se ejecuten si
expresin_prueba no coincide con ninguna de las otras clusulas Case.
Si la expresin_prueba coincide con cualquier lista_expresin asociada con una clusula
Case, las instrucciones que siguen a esa clusula Case se ejecutan hasta la siguiente clusula
Case o, para la ltima clusula, hasta la instruccin End Select. El control pasa despus a la
instruccin que sigue a End Select. Si expresin_prueba coincide con una expresin de

VB.Net (Cap 3. El lenguaje)

Pg. 56

Desarrollo de Aplicaciones Multiplataforma

lista_expresin en ms de una clusula Case, slo se ejecutan las instrucciones que siguen a la
primera coincidencia.
Aunque no es necesario, es buena idea tener una instruccin Case Else en el bloque Select
Case para controlar valores imprevistos de expresin_prueba.
Se pueden utilizar expresiones mltiples o intervalos en cada clusula Case. Por ejemplo, la
lnea siguiente es vlida:
Case 1 To 4, 7 To 9, 11, 13, Is > MaxNumber
' Ser cierto para los valores entre 1 y 4, de 7 a 9, el 11, el 13 y los mayores
que MaxNumber

Tambin se pueden especificar intervalos y expresiones mltiples para cadenas de caracteres.


En el siguiente ejemplo, Case coincide con las cadenas que son exactamente , cadenas que
estn entre A y Z en orden alfabtico y el valor actual de la caja de texto:
Case "", "A" To "Z", txtDato.Text

Las instrucciones Select Case se pueden anidar. Cada instruccin Select Case debe tener su
correspondiente instruccin End Select.
Ejemplo:
Dim Nmero As Byte
Nmero = txtNum.Text
' Supongamos que en la caja de texto tenemos el nmero 6
Select Case Nmero
' Evala Nmero.
Case 1 To 5
' Nmero entre 1 y 5, inclusive.
lblSalida.Caption = "Entre 1 y 5"
Case 6, 7, 8
' Nmero entre 6 y 8. 'Esta ser la clusula Case cuyo valor
es True.
lblSalida.Caption = "Entre 6 y 8"
Case 9 To 10
' Nmero es 9 10.
lblSalida.Caption = "Mayor que 8"
Case Else
' Otros valores.
lblSalida.Caption = "Otro valor"
End Select

Recordemos que en VB.Net podemos poner ms de una instruccin siempre que aadamos
los : por lo que esta instruccin puede ponerse. A la vez observa que si se permite que un
valor se cumpla en dos clusulas Case se ejecutar solo para la primera. En este caso si Nmero
vale 10 la etiqueta se quedar con el valor Entre 9 y 10 y no Mayor o igual a 10
Select Case Nmero
' Evala Nmero.
Case 1 To 5 : lblSalida.Caption = "Entre 1 y 5"
Case 6, 7, 8 : lblSalida.Caption = "Entre 6 y 8"
Case 9 To 10 : lblSalida.Caption = "Entre 9 y 10"
Case Is >= 10 : lblSalida.Caption = "Mayor o igual a 10"
Case Else : lblSalida.Caption = "Negativo o 0"
End Select

Atencin Qu ocurre en el ejemplo anterior si tenemos Nmero declarada como Decimal


y toma el valor 7.6? Y qu escribir si es 9.4?
En el primer caso (7.6) sacar un mensaje absurdo Negativo o 0 ya que ese valor no est
entre los supuestos. A primera vista podra pensarse que entrara en la clusula de 6,7,8, pero
realmente esta pregunta por esos 3 valores y solo por ellos. En cambio 9.4 si es un nmero que
se encuentra entre 9 y 10 (9 To 10) por lo que sacara el mensaje Entre 9 y 10.

VB.Net (Cap 3. El lenguaje)

Pg. 57

Desarrollo de Aplicaciones Multiplataforma

Usando la Select Case para determinar los botones chequeados


Cuando queremos saber entre varios RadioButton, cual de ellos est seleccionado
deberamos hacer algo semejante a:
If rbtAndando.Checked Then
lblSeleccionado.Text = " rbtAndando" ' Si se ha seleccionado le pone su
nombre
ElseIf rbtEnBici.Checked Then
lblSeleccionado.Text = " rbtEnBici"
ElseIf rbtEnBus.Checked Then
lblSeleccionado.Text = " rbtEnBus"
ElseIf rbtEnVehiculoPropio.Checked Then
lblSeleccionado.Text = " rbtEnVehiculoPropio"
Else ' No ha sido ninguno de los anteriores, es decir, no hay ninguno chequeado
lblSeleccionado.Text = "Ninguno"
End If

Pero podramos usar la instruccin Select Case de forma especial. Si ponemos la expresin a
evaluar como True y en las propiedades Checked de los controles como posibles valores, los if
anteriores se pueden reemplazar por:
Select Case True
Case rbtAndando.Checked : lblSeleccionado.Text = " rbtAndando" ' Si se ha
seleccionado le pone su nombre
Case rbtEnBici.Checked : lblSeleccionado.Text = " rbtEnBici"
Case rbtEnBus.Checked : lblSeleccionado.Text = " rbtEnBus"
Case rbtEnVehiculoPropio.Checked : lblSeleccionado.Text = "
rbtEnVehiculoPropio"
Case Else : lblSeleccionado.Text = "Ninguno" ' No hay ninguno seleccionado
End Select

Bucles While..Wend y Do..Loop


En VB.Net tenemos dos tipos distintos de bucles para simular los tpicos Mientras y Repetir.
Por una parte est el While...Wend con la siguiente sintaxis:
While condicin
instrucciones
Wend
Este bucle repite la ejecucin de un conjunto de instrucciones mientras la condicin dada sea
cierta. La condicin se verifica antes de ejecutarse las instrucciones, por lo que puede que estas
no se ejecuten nunca (si desde el comienzo es falsa).
While num <= 10 ' Comprueba si num<=10. Entra al bucle en el caso de que lo sea
num = num + 1 ' Modifica el valor de la variable sobre la que se pregunta en la
' condicin
End While

Los bucles While...Wend se pueden anidar a cualquier nivel. Cada Wend coincide con el
While ms reciente.
Tambin tenemos los bucles Do..Loop con los 4 posibles formatos, que son ms completos
que el anterior (tienen la posibilidad de una salida alternativa con el Exit Do). En este caso las
instrucciones se repiten mientras la condicin sea cierta (While) o hasta que lo sea (Until). A
su vez, en ambos casos, tenemos 2 posibles formatos:
Do [{While | Until} condicin]
[instrucciones]
[Exit Do]
[instrucciones]
Loop

VB.Net (Cap 3. El lenguaje)

Do
[instrucciones]
[Exit Do]
[instrucciones]
Loop [{While | Until} condicin]

Pg. 58

Desarrollo de Aplicaciones Multiplataforma

Es decir, la condicin se puede poner arriba o abajo y en cualquiera de las formas: While o
Until.
Se puede utilizar cualquier nmero de instrucciones Exit Do ubicadas en cualquier lugar
dentro de una estructura de control DoLoop, para proporcionar una salida alternativa. La
instruccin Exit Do se utiliza frecuentemente en la evaluacin de alguna condicin, por ejemplo,
IfThen. En este caso, la instruccin Exit Do transfiere el control a la instruccin que sigue
inmediatamente a la instruccin Loop.
Cuando se utiliza con instrucciones anidadas DoLoop, la instruccin Exit Do transfiere
control al bucle que est anidado un nivel por encima del bucle donde ocurre.
Ejemplo:
Estos dos bucles son equivalentes (lo importante es donde se evala la condicin, el estilo
until o while depende ms del gusto personal):
Do
If n < 0 Then Exit Do ' Provoca otra posible salida del bucle
n = n + 1
Loop Until n > 10

Do
If n < 0 Then Exit Do ' Provoca otra posible salida del bucle
n = n + 1
Loop While n <= 10

Bucle For
Permite ejecutar un conjunto de instrucciones un nmero concreto de veces.
For contador = principio To fin [Step incremento]
[instrucciones]
[Exit For]
[instrucciones]
Next [contador]
El bucle finaliza cuando la condicin es > que el valor final (siempre que el incremento sea
positivo) o si es < que el valor final para incrementos negativos. Si no se especifica ningn
incremento, por defecto toma el valor.
En la parte del Next escribir o no el nombre del contador es simplemente para dar mayor
legibilidad a la instruccin, pero no le aporta nada.
Una vez que se inicia el bucle y se han ejecutado todas sus instrucciones, incremento se
suma a contador volviendo a evaluar si la variable contador ya es > que fin (o < para
incrementos negativos). Dependiendo de la respuesta las instrucciones se vuelven a ejecutar de
nuevo o se sale del bucle y la ejecucin contina con la instruccin siguiente a Next. Veamos
algunos ejemplos:
suma = 0 ' inicializamos el acumulador a 0
For i = 1 To 10 Step 2 ' cont toma valores 1,3,5...hasta 11 (11>10->se sale)
suma += i ' guarda en suma 1+3+5+7+9. Con el valor 11 se ha salido,
Next

Recuerda que suma += i es lo mismo que suma = suma + i


En este ejemplo se saldr del bucle cuando i valga 11 (ir tomando valores impares, 1, 3 ).
Veamos otro par e ejemplos.
' En este caso el incremento es 1, por lo que no entra al bucle
' ya que al inicializar i a 21 ya es superior a 10

VB.Net (Cap 3. El lenguaje)

Pg. 59

Desarrollo de Aplicaciones Multiplataforma


For i = 21 To 10
suma += i ' suma se queda como est
Next
' En cambio en el siguiente entrar para valores 21, 20, ... y 10. Al tomar el
valor 9
' se sale del bucle
For i = 21 To 10 Step -1
suma += i ' suma = 21+20+...+10
Next

Declaracin de variables a nivel de bloque


En las ltimas versiones de VB.Net, podemos declarar una variable en cualquier lugar, pero
hay que tener en cuenta que eso tiene sus consecuencias, ya que si declaramos una variable
dentro de un bucle, esta variable solo podr ser accedida en el propio bucle.
Ejemplo: Si escribimos el siguiente
Dim suma, i As Integer
For i = 1 To 10
suma += i
Next
MessageBox.Show("Suma vale " & suma & ControlChars.Back & "i vale " & i)

Si ejecutamos este trozo de programa nos encontraremos con la siguiente ventana:

En cambio en el siguiente ejemplo dar un error de compilacin, ya que la i del MessageBox


no la reconoce, pues solo tiene mbito en el For (que es donde la hemos declarado).
Dim suma As Integer
For i As Integer = 1 To 10 ' se declara en el mismo For
suma += i
Next
MessageBox.Show("Suma vale " & suma & ControlChars.CrLf & "i vale " &
"Resultado", MessageBoxButtons.OK, MessageBoxIcon.Information)

i,

Esta forma de declaracin puede ser muy prctica, siempre que la variable solo la usemos
para el bucle, y si es as y tenemos 2 For seguidos deberamos declararla ambas veces.
For i As Integer = 1 To 10 ' se declara para este For
'instrucciones a ejecutar 10 veces
Next
'En este espacio entre For no se reconoce ninguna variable i
For i As Integer = txtNum.Text To 15 ' Es una nueva i
'instrucciones a ejecutar varias veces, depender el valor que tenga txtNum
Next

Si sabemos que una variable solo la necesitamos en ese espacio es muy cmo declararla
dentro de la instruccin y sobretodo porque as optimizamos recursos.
Atencin: A partir de las ltimas versiones de Visual Basic.Net si usamos una variable no
declarada en un For, es lo mismo que si se declara en l, es decir, los bucles anteriores equivalen
a:

VB.Net (Cap 3. El lenguaje)

Pg. 60

Desarrollo de Aplicaciones Multiplataforma


For i = 1 To 10 ' Si no est declarada se declara AUTOMTICAMENTE para este For
'instrucciones a ejecutar 10 veces
Next
'En este espacio entre For no se reconoce ninguna variable i
For i = txtNum.Text To 15 ' Es una nueva i
'instrucciones a ejecutar varias veces, depender el valor que tenga txtNum
Next

Manejo de excepciones: Bloque Try..Catch


Las excepciones en VB.Net las podemos controlar usando las instrucciones Try / Catch /
Finally. Estas instrucciones realmente son bloques de instrucciones, al estilo de If / Else.
Cuando queramos controlar una parte del cdigo que puede producir un error lo incluimos
dentro del bloque Try, si se produce un error, ste lo podemos detectar en el bloque Catch, por
ltimo, independientemente de que se produzca o no una excepcin, podemos ejecutar el cdigo
que incluyamos en el bloque Finally, para indicar el final del bloque de control de excepciones
lo haremos con End Try.
Cuando creamos una estructura de control de excepciones no estamos obligados a usar los
tres bloques. Es ms, en numerosas ocasiones solo usaremos los dos primeros: Try que es
siempre obligatorio, ya que es el que le indica al compilador que tenemos intencin de controlar
los errores que se produzcan, y Catch para dar solucin al control del error.
Veamos ahora con ms detalle cada uno de estos bloques y que es lo que podemos hacer en
cada uno de ellos.

Bloque Try
En este bloque incluiremos el cdigo en el que queremos comprobar los errores.
El cdigo a usar ser un cdigo normal, es decir, no tenemos que hacer nada en especial, ya
que en el momento que se produzca el error se usar (si hay) el cdigo del bloque Catch.

Bloque Catch
Si se produce una excepcin, sta la capturamos en un bloque Catch.
En el bloque Catch podemos indicar que tipo de excepcin queremos capturar, para ello
usaremos una variable de tipo Exception, la cual pude ser del tipo de error especfico que
queremos controlar o de un tipo genrico.
Por ejemplo, si sabemos que nuestro cdigo puede producir un error al trabajar con ficheros,
podemos usar un cdigo como este:
Try
' cdigo para trabajar con ficheros, etc.
Catch ex As System.IO.IOException
' el cdigo a ejecutar cuando se produzca ese error
End Try

Si nuestra intencin es capturar todos los errores que se produzcan, es decir, no queremos
hacer un filtro con errores especficos, podemos usar la clase Exception como tipo de excepcin
a capturar. La clase Exception es la ms genrica de todas las clases para manejo de
excepciones, por tanto capturar todas las excepciones que se produzcan.
Try
' cdigo que queremos controlar
Catch ex As Exception ' ex es el nombre de la variable. Se puede cambiar

VB.Net (Cap 3. El lenguaje)

Pg. 61

Desarrollo de Aplicaciones Multiplataforma

' el cdigo a ejecutar cuando se produzca cualquier error


End Try

Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se
detenga la aplicacin cuando se produzca un error, podemos hacerlo de esta forma:
Try
' cdigo que queremos controlar
Catch
' el cdigo a ejecutar cuando se produzca cualquier error
End Try

Varias capturas de errores en un mismo bloque Try/Catch


En un mismo Try podemos capturar diferentes tipos de errores, para ello podemos incluir
varios bloques Catch, cada uno de ellos con un tipo de excepcin diferente.
Es importante tener en cuenta que cuando se produce un error y usamos varios bloques
Catch, Visual Basic buscar la captura que mejor se adapte al error que se ha producido, pero
siempre lo har examinando los diferentes bloques Catch que hayamos indicado empezando por
el indicado despus del bloque Try, por tanto deberamos poner las ms genricas al final, de
forma que siempre nos aseguremos de que las capturas de errores ms especficas se intercepten
antes que las genricas.
Veamos un ejemplo de su uso:
Dim fichero As System.IO.StreamReader
Dim ruta As String = My.Application.Info.DirectoryPath & "\Ejemplo"
Dim numeros As New List(Of Integer)
Try
fichero = New StreamReader(ruta & "\ficheroEjemplo.txt")
Do Until fichero.EndOfStream
Dim lin As Integer = fichero.ReadLine '
numeros.Add(lin) ' sera equivalente a lineas.Add(fichero.ReadLine)
Loop
fichero.Close()
Catch ex As IO.FileNotFoundException ' Esta excepcin se produce si no existe
el fichero
MessageBox.Show(ex.Message, "Error FileNotFound")
Exit Sub
Catch ex As IO.IOException ' Esta excepcin se produce si se producen otros
errores de fichero
MessageBox.Show(ex.Message, "Error IO")
Exit Sub
Catch ex As Exception ' En este caso estamos ante otro tipo de errores, por
ejemplo, se ha encontrado una lnea no numrica
MessageBox.Show(ex.Message, "Error general")
Exit Sub
End Try

Bloque Finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca
o no una excepcin. De esta forma nos aseguramos de que siempre se ejecutar un cdigo, por
ejemplo para liberar recursos, se haya producido un error o no.
Nota: Hay que tener en cuenta de que incluso si usamos Exit Try para salir del bloque de
control de errores, se ejecutar el cdigo indicado en el bloque Finally.

VB.Net (Cap 3. El lenguaje)

Pg. 62

Desarrollo de Aplicaciones Multiplataforma

Lanzar una excepcin por cdigo


Para lanzar (o crear) excepciones tendremos que usar la instruccin Throw seguida de un
objeto derivado del tipo Exception.
Normalmente se hace de la siguiente forma:
Throw New Exception("Esto es un error personalizado")

Con este cdigo estamos indicndole al Visual Basic .NET que queremos "lanzar" (Throw)
una nueva excepcin (New Exception) y que el mensaje que se mostrar, ser el que le
indiquemos dentro de los parntesis.
Cuando nosotros lanzamos (o creamos) una excepcin, el error lo interceptar un bloque Try
que est activo, si no hay ningn bloque Try activo, ser el CLR (runtime de .NET Framework)
el que se encargar de interceptar esa excepcin, pero deteniendo la ejecucin del programa...
Private _fechaNacimiento As Date
''' <summary>
''' Permite modificar la fecha de nacimiento
''' </summary>
''' <value>Debe ser un valor no superior a la fecha actual. Si no lo es lanza una
excepcin</value>
''' <returns>Devuelve la fecha de nacimiento. Si no se ha introducido, lanza una
excepcin</returns>
''' <remarks></remarks>
Property FechaNacimiento As Date
Get ' Si _fechaNacimiento est "sin valor" lanza una excepcin
If _fechaNacimiento = #12:00:00 AM# Then Throw New Exception("Esta persona no
conoce su fecha de nacimiento")
Return _fechaNacimiento
End Get
Set(ByVal value As Date) ' Controla que sea inferior o igual a la fecha actual
If value > DateTime.Today Then Throw New Exception("La fecha de nacimiento
no puede ser superior a la actual")
_fechaNacimiento = value
End Set
End Property

Nota: Para recoger luego la excepcin deberemos utilizar la instruccin Try/Catch


explicada anteriormente, sabiendo que en mtodo Message de la variable ex tendremos el texto
generado en New Exception.
Supongamos que tenemos defina una Persona en la forma:
Dim per As New Persona

Y en alguna parte hacemos la siguiente instruccin:


per.FechaNacimiento = txtFechaNac.Text

Esta instruccin en s misma, y si no hago un control previo de fecha podra ocasionar 2


tipos de errores:
Try
p.FechaNacimiento = txtFechaNacimiento.text
Catch ex As Exception
MessageBox.Show(ex.Message) ' En este caso sacara el mensaje de la clase
o podra sacar "La conversin de cadena __ en el tipo Date no es vlida
End Try

VB.Net (Cap 3. El lenguaje)

Pg. 63

Desarrollo de Aplicaciones Multiplataforma

Atencin: Nunca deberamos usar un Try si tenemos otra forma ms sencilla y concreta de
resolver el control de la excepcin. En el ejemplo anterior controlar que en la caja de texto haya
un dato lgico (es decir, una fecha) se debera hacer en la forma:
If Not IsDate(txtFechaNacimiento.Text) Then
MessageBox.Show("No hay una fecha vlida", "Atencin")
txtFechaNacimiento.Clear()
txtFechaNacimiento.Focus()
Exit Sub
End If

VB.Net (Cap 3. El lenguaje)

Pg. 64

Desarrollo de Aplicaciones Multiplataforma

Cap 4. Funciones estndar y mtodos de interes


Funciones del lenguaje
Cada lenguaje dispone de un grupo de funciones de apoyo, para ayudar al programador o
programadora en su trabajo cotidiano. Las versiones anteriores de Visual Basic contenan un
gran nmero de funciones para realizar operaciones aritmticas, manipular cadenas, fechas,
etc.
VB.NET tambin tiene funciones para las operaciones antes comentadas. No obstante,
debido a la orientacin a objetos sobre la que est construida la plataforma .NET, la gran
potencia a la hora de resolver cualquier situacin la encontraremos en el gran nmero de clases
proporcionadas por el entorno para resolver las ms variadas situaciones, lo que veremos en el
prximo tema dedicado a OOP.
En este apartado y organizadas por categoras, vemos una pequea muestra de las
funciones disponibles en VB.NET.

Requerir datos con InputBox


La funcin InputBox visualiza una caja de dilogo semejante a la de la figura siguiente, con
un mensaje que indica al usuario o usuaria el tipo de informacin que debe introducir.
Sintaxis:

InputBox (mensaje [,ttulo] [, por omisin][,posx][,posy])


Por ejemplo, la instruccin:
Dim nombre As String
nombre = InputBox("Introduce el nombre de usuario" & ControlChars.CrLf & "Debe
ser uno existente", "Atencin")

Visualiza la caja de dilogo siguiente:

La primera cadena de caracteres del mensaje contiene el mensaje que indica al usuario o
usuaria el tipo de informacin que debe introducir; en el ejemplo Introduce el nombre de
usuario. Si el mensaje contiene varias lneas, debemos introducir explcitamente al final de cada
una de ellas un retorno de carro y avance de lnea, lo cual podemos hacerlo mediante la
constante CrLf de la clase ControlChars.
La funcin InputBox siempre devuelve un dato de tipo String.
El resto de los parmetros son opcionales. Si queremos omitir un argumento que precede a
otro especificado, deberemos poner las correspondientes comas delimitadoras.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 65

Desarrollo de Aplicaciones Multiplataforma

La cadena de caracteres ttulo ser visualizada en la barra de ttulo del dilogo; si se omite
como en el ejemplo anterior, se pone como ttulo el nombre de la aplicacin (en el ejemplo
Atencin).
La cadena de caracteres por_omisin especifica el texto que aparecer en la caja de texto; si
se omite, la caja de texto aparece vaca. (En el siguiente ejemplo la caja de texto aparecer por
defecto con la palabra Cuatrovientos)
nombre = InputBox("Nombre del instituto", "Introduce el dato", "Cuatrovientos")

Los argumentos posx y posy son las coordenadas x e y medidas desde la izquierda y parte
superior de la pantalla respectivamente, expresadas en twips (1 twip = 1/1440 pulgadas). Si se
omiten, la caja de dilogo se visualiza centrada horizontalmente y a 1/3 de la parte superior de la
pantalla.
Si al ejecutar el InputBox, el usuario o usuaria pulsa el botn de Aceptar, la funcin
InputBox devuelve el valor (string) que se encuentra en la caja de texto del InputBox. En el
ejemplo de la figura nombre recibira maria.
Por el contrario, si se pulsa el botn de Cancelar e independientemente del valor que
tengamos en la caja de texto, la funcin InputBox devuelve una cadena vaca.
Por tanto, si deseamos saber si el usuario/a ha pulsado Aceptar o Cancelar basta que
preguntemos por la variable recogida (en nuestro caso nombre) y ver si su valor es o no.
Como puedes suponer, no podemos distinguir si el usuario/a ha pulsado la tecla Cancelar o
Aceptar con la caja de texto vaca.
Ejemplo:
nombre = InputBox("Introduce el nombre de usuario" & ControlChars.CrLf & "Debe
ser uno existente", "Atencin")
If nombre = "" Then Exit Sub ' Si se ha pulsado Cancelar no se desea continuar

Visualizar datos mediante la clase MessageBox


La clase MessageBox muestra un cuadro de mensaje que puede contener texto, botones
y smbolos que informan e instruyen al usuari@.
Gracias a su mtodo Show 21 veces sobrecargado el cuadro puede mostrar la ventana desde
un mensaje y el botn de Aceptar para cerrar la ventana (como se puede apreciar en la primera
imagen), a los que se le puede aadir un ttulo, otros botones, un icono, indicar cul es el botn
predeterminado para que se considere si pulsamos la tecla <Intro>, opciones de cmo debe estar
el texto en la ventana (observa que en la3 figura est a la derecha), e incluso si se desea aadir
un botn de Ayuda.

Veamos el cdigo que permite mostrar estas ventanas:


MessageBox.Show("Adios")
MessageBox.Show("Grabar los cambios?","Cerrar programa",
MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 66

Desarrollo de Aplicaciones Multiplataforma


MessageBox.Show("Grabar los cambios?", "Cerrar programa",
MessageBoxButtons.OKCancel, MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2, MessageBoxOptions.RightAlign, True)

Al igual que en el la ventana InputBox, si deseamos que el mensaje conste de varias lneas
deberemos indicarlo con la constante CrLf, Cr, Lf o NewLine de la clase ControlChars
MessageBox.Show("Cerrar programa" & ControlChars.CrLf & "Grabar datos?",
"Atencin!!!", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question)

Como podemos comprobar, hay ventanas que solo sirven para dar informacin (mostrando el
botn Aceptar para cerrarla una vez leda), pero hay otras veces, como en el ejemplo de arriba,
en las que se presentan varios botones para realizar una accin diferente dependiendo del botn
pulsado por la o el usuario.
En ese caso, necesitaremos una variable del tipo DialogResult que es el devuelto por el
mtodo Show, que recoja la respuesta como vemos en el siguiente ejemplo:
Dim resp As DialogResult
resp = MessageBox.Show("Deseas continuar?", "Atencin", MessageBoxButtons.YesNo,
MessageBoxIcon.Question)
If resp = Windows.Forms.DialogResult.No Then Exit Sub ' Ha respondido que no
desea continuar

Hay ocasiones en las que no necesitamos guardarlo en una variable, sino simplemente
preguntar por la respuesta, en ese caso podemos hacerlo directamente en la forma:
If MessageBox.Show("Deseas continuar?", "Atencin", MessageBoxButtons.YesNo,
MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then Exit Sub ' Ha
respondido que no desea continuar

Cuidado! Si hay varias posibilidades NO podramos hacer:


If MessageBox.Show("Continuar?", "Atencin", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question) = Windows.Forms.DialogResult.Yes Then
' instrucciones del S
End If
If MessageBox.Show("Continuar?", "Atencin", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question) = Windows.Forms.DialogResult.No Then
' Instrucciones del No
End If
If MessageBox.Show("Continuar?", "Atencin", MessageBoxButtons.YesNoCancel,
MessageBoxIcon.Question) = Windows.Forms.DialogResult.Cancel Then
' Instrucciones del Cancelar
End If

Pues esto ocasionara que se mostraran 3 ventanas seguidas, pues cada vez que escribimos
MessageBox.Show se muestra una diferente.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 67

Desarrollo de Aplicaciones Multiplataforma

Funciones de conversiones de tipos


CByte, CDate,
Cada funcin convierte una expresin a un tipo de datos especfico. En todos los casos la
sintaxis de la funcin es: NombreFuncin (expresin). El argumento obligatorio expresin es
cualquier expresin de cadena o expresin numrica.
El nombre de la funcin determina el tipo devuelto, como se muestra a continuacin:
Funcin

Tipo
devuelto

Intervalo del argumento expresin

CBool

Boolean

Cualquier expresin de cadena o numrica vlida.

CByte

Byte

0 a 255 (sin signo); las partes fraccionarias se redondean

CChar

Char

Cualquier expresin Char o String vlida; slo se convierte el primer


carcter de String; el valor puede estar comprendido entre 0 y 65535 (sin
signo).

CDate

Date

Cualquier expresin vlida de fecha y hora.

CDbl

Double

-1,79769313486232E308 a
-4,94065645841247E-324 para valores negativos; 4,94065645841247E-324
a 1,79769313486232E308 para valores positivos.

CDec

Decimal

+/-79.228.162.514.264.337.593.543.950.335 para nmeros basados en cero,


es decir, nmeros sin decimales. Para nmeros con 28 decimales, el
intervalo es +/-7,9228162514264337593543950335. La menor posicin
para un nmero que no sea cero es 0,0000000000000000000000000001.

CInt

Integer

de -2.147.483.648 a 2.147.483.647; las partes fraccionarias se redondean.

CLng

Long

de -9.223.372.036.854.775.808 a 9.223.372.036.854.775.807; las partes


fraccionarias se redondean

CObj

Object

Cualquier expresin vlida

CSByte

SByte

de -128 a 127; las partes fraccionarias se redondean.

CShort

Short

de -32.768 a 32.767; las partes fraccionarias se redondean.

CSng

Single

-3,402823E38 a -1,401298E-45 para valores negativos; 1,401298E-45 a


3,402823E38 para valores positivos.

CStr

String

Los valores devueltos para CStr dependen del argumento expression. Mira
en la ayuda Valores devueltos para la funcin CStr..

CUInt

UInteger

de 0 a 4.294.967.295 (sin signo); las partes fraccionarias se redondean.

CULng

ULong

de 0 a 18.446.744.073.709.551.615 (sin signo); las partes fraccionarias se


redondean

CUShort

UShort

de 0 a 65.535 (sin signo); las partes fraccionarias se redondean.

Nota. Si la expresin del argumento expresin que se pasa a la funcin est fuera del
intervalo del tipo de dato al que se va a convertir o no es numrico, se produce una excepcin

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 68

Desarrollo de Aplicaciones Multiplataforma

(OverflowException en el primer caso y ArgumentException en el segundo) que si no se


controla, provocar un error de ejecucin.
Ejemplo. Si en la siguiente instruccin la caja de texto contiene el valor 3, num recoge este
valor, pero si tenemos un valor negativo o superior a 255 dar un error.
Dim num As Byte = CByte(txtNum.Text) ' Error si en la caja de texto no hay un
dato numrico o no est entre 0 y 255

Cuando la parte fraccionaria es exactamente 0,5, CByte, CInt y CLng siempre redondean al
nmero par ms cercano. Por ejemplo, 0,5 redondea a 0, y 1,5 redondea a 2.
Atencin Aunque en muchas no necesitemos hacer conversiones porque VB.Net lo hace de
forma automtica, hay otras en que l mismo nos lo exigir.
Dim num As Byte = txtNum.Text ' Si en la caja de texto hay un valor entre 0 y 255
hace intrnsecamente la conversin.

En cambio la siguiente expresin dara error de compilacin:


Dim numAbs As Decimal = Math.Abs(txtNum.Text) ' Error de compilacin, la funcin
Abs necesita recibir un dato estrictamente numrico

La solucin por tanto debera ser:


Dim numAbs As Decimal = Math.Abs(CDec(txtNum.Text)) ' Obligatoriamente debemos
usar la funcin de conversin

Clase Convert
Si queremos hacerlo con POO, podemos usar la clase Convert, pero teniendo en cuenta que
esta clase trabaja con los tipos de la plataforma, de tal forma, que si queremos hablar, por
ejemplo del tipo Integer de VB debemos hacer referencia a System.Int32 de la plataforma.
Los mtodos son del tipo ToBoolean, ToInt32, ...
Dim num As Integer =

Convert.ToInt32(txtNumero.Text)

Int y Fix
Las funciones Int y Fix sirven para truncar un nmero, es decir, quitan la parte fraccionaria
del nmero pasado como parmetro y devuelven el valor entero resultante.
La diferencia entre las funciones Int y Fix es que si el nmero es negativo, Int devuelve el
primer entero negativo menor o igual que el nmero, mientras que Fix devuelve el primer entero
negativo mayor o igual que el nmero. Observa los siguientes ejemplos:
Dim numInt As Decimal = Int(txtNum.Text) ' Si txtNumText vale -7,2 recoge -8,
con 7,2 o 7,8 valdr 7
Dim numFix As Decimal = Fix(txtNum.Text) ' Con -7,2 recoge -7, con 7,2 o 7,8
valdr 7
Dim numCInt As Integer = CInt(txtNum.Text) ' Con -7,2 o 7,2 coge -7, con -7,8
guarda -8 y 8 si el valor es 7,8

Funciones y contantes matemticas. Clase Math


Estas funciones son mtodos (funciones) de la clase Math (ejemplo Math.Pi ) por lo que
para usarlas debemos escribir el nombre de la clase o incluir el espacio de nombres antes en el
que est incluida la clase Math y que es System.Math (Imports System.Math).

Constantes Pi y E
Representan a las constantes y e respectivamente. Es decir, son equivalentes a los valores
3.14926535897931 y 2.7182818284590451.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 69

Desarrollo de Aplicaciones Multiplataforma

Son muy sencillas de utilizar, basta con poner el nombre de la constante indicando que es de
la clase Math en la forma:
lblArea.Text = Math.Pi * txtRadio.Text ^ 2 ' Hay que especificar que PI es
miembro de Math

Si no queremos incluir continuamente el nombre de la clase podemos importarlo antes de la


declaracin de la clase, como puedes apreciar en el siguiente ejemplo:
Imports System.Math
Public Class frmFuncionesMatematicas
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
lblArea.Text = Pi * txtRadio.Text ^ 2 ' Con Imports no necesitamos indicar
Math
End Sub
End Class

Floor y Ceiling
Devuelve el nmero entero ms grande menor o igual que el nmero especificado y
Devuelve el nmero entero ms pequeo mayor o igual que el nmero especificado.
Para verlo, supongamos el siguiente ejemplo:
Dim numF As Integer = Math.Floor(CDec(txtNum.Text))
Dim numC As Integer = Math.Ceiling(CDec(txtNum.Text))

Los posibles valores de numF y numC dependiendo del valor de txtNum seran:
txtNum.Text

numF

numC

1,2

-1,2

-2

-1

1,8

-1,8

-2

-1

Sqrt
Devuelve la raz cuadrada del valor pasado como parmetro. Veamos un ejemplo del uso de
esta funcin
Private Sub btnRaiz_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRaiz.Click
lblRaiz.Text = Math.Sqrt(txtNum.Text)
End Sub

Atencin Qu ocurre si en la caja de texto hay un valor no numrico? Y qu si el valor


es negativo?
Ambos controles los haremos en el siguiente ejemplo, pero antes debes saber en el caso de
que el valor que pasamos sea negativo, la funcin Sqrt devuelve un valor no numrico especial
denominado Nan que en pantalla aparece como NeuN. La funcin IsNumeric est explicada en
el siguiente apartado.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 70

Desarrollo de Aplicaciones Multiplataforma

Si queremos mostrar un mensaje especial, diferente de NeuN (que es una palabra muy
extraa para cualquier usuari@ deberemos controlar primero que el resultado sea vlido, lo cual
lo podemos hacer gracias al mtodo IsNaN del tipo Double. Observa el mensaje del siguiente
ejemplo.

El cdigo asociado a este caso podra ser:


Private Sub btnRaiz_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRaiz.Click
If Not IsNumeric(txtNum.Text) Then
MessageBox.Show("El valor debe ser numrico", "Atencin")
txtNum.Clear()
Exit Sub
End If
Dim r As Double = Math.Sqrt(txtNum.Text)
If Double.IsNaN(r) Then
lblResultado.Text = "Error, no puede ser negativo"
Else
lblResultado.Text = r
End If
End Sub

Lgicamente en este caso concreto tenemos otra solucin an ms sencilla, que es preguntar
si el valor de la caja de texto es negativo:
If txtNum.Text < 0 Then
lblResultado.Text = "Error, no puede ser negativo"
Else
lblResultado.Text = Math.Sqrt(txtNum.Text)
End If

Abs
Devuelve el valor absoluto de un nmero.
Veamos un ejemplo:
Dim num As Decimal = -7.8

' con . para decimales porque estamos en cdigo

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 71

Desarrollo de Aplicaciones Multiplataforma


Dim numAbs As Decimal = Math.Abs(num)
num valiese 7,8

' numAbs recoge el valor 7,8, igual que si

Atencin El parmetro de la funcin deber ser obligatoriamente de tipo numrico, y de no


serlo, habr que hacer una conversin previa, para evitar un error de compilacin.
Observa el siguiente ejemplo:
Dim numAbs As Decimal = Math.Abs(txtNum.Text) ' Error de compilacin, la funcin
Abs necesita recibir un dato estrictamente numrico

La solucin por tanto debera ser:


Dim numAbs As Decimal = Math.Abs(CDec(txtNum.Text)) ' Obligatoriamente debemos
usar la funcin de conversin

Logaritmos: Log, Log10


Para calcular el logaritmo de un nmero tenemos estos dos mtodos, el primero
sobrecargado con 1 2 parmetros.
Log(Double) : Devuelve el logaritmo natural o neperiano (en base e) del nmero
especificado como parmetro siempre que dicho nmero sea positivo. Si es 0 devuelve
NegativeInfinity y si es negativo Nan.
Dim numLog As Decimal = Math.Log(txtNum.Text) ' Devuelve el logaritmo neperiano
del numero que se encuentre en txtNum.Text

Si quisiramos controlar los posibles errores, podramos hacerlo en la forma:


Dim n As Double = Math.Log(txtNum.Text)
If Double.IsNegativeInfinity(n) Or Double.IsNaN(n) Then ' Si el resultado es - o
errneo
MessageBox.Show("El logaritmo neperiano de " & txtNum.Text & " es errneo;
sale " & n, "Error en logaritmo")
Else
MessageBox.Show(n, "Logaritmo neperiano")
End If

Atencin Si la variable en la que deseamos guardar el valor es de un tipo inferior a Double,


esta no puede recoger el valor de - por lo que da un error de ejecucin.
Dim n As Decimal = Math.Log(0) ' Error de ejecucin!!!!

Log(Double, Double) : Devuelve el logaritmo del primer parmetro en la base del segundo.
Dim numLogBase As Decimal = Math.Log(txtNum.Text, txtBase.Text) ' Devuelve el
logaritmo en base txtBase.Text del nmero que est en txtNum

Log10(Double) Devuelve el logaritmo en base 10 del nmero especificado.


Dim numLog10 As Decimal = Math.Log(txtNum.Text) ' Devuelve el logaritmo en base
10 del numero que se encuentre en txtNum.Text

Exp
Devuelve e elevado a la potencia especificada. Esta funcin es la inversa a Log. Si el nmero
pasado como parmetro es igual a NaN o PositiveInfinity, devuelve ese valor, mientras que si es
igual a NegativeInfinity, devuelve 0.
Dim num As Double = Math.Exp(txtNum.Text) ' Devuelve etxtNum.Text

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 72

Desarrollo de Aplicaciones Multiplataforma

Funciones de comprobacin de tipos de datos


En ciertas situaciones necesitamos comprobar si determinada variable o expresin
contienen un valor numrico, fecha, etc, ... El lenguaje nos proporciona para ello, algunas
funciones con las que podremos comprobar el tipo de dato, para evitar posibles errores.
IsNumeric( ). Esta funcin devuelve un valor lgico indicando si la expresin que
pasamos como parmetro contiene un nmero o una cadena que pueda ser convertida
a nmero.
IsDate( ). Esta funcin devuelve un valor lgico indicando si la expresin que
pasamos como parmetro contiene una fecha o una cadena que pueda ser convertida a
fecha. Una fecha se considera vlida en varios formatos, desde el tpico con notacin
dd/mm/aaaa, hasta si tenemos el nombre del mes. Ejemplo 5 de Marzo de 2000 es una
fecha vlida.
Ejemplo: Supongamos que queremos controlar si el valor que se encuentra en una caja de
texto es de tipo fecha o no, y en el caso de no serlo, no continuar con el subprograma ya que el
dato se considera errneo. En ese caso escribiramos algo semejante a:
If Not IsDate(txtFecha.Text) Then ' Si no se puede considerar fecha el valor de
la caja de texto
MessageBox.Show("Debes introducir una fecha", "Error de entrada",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtFecha.Clear() ' limpia la caja de texto
txtFecha.Focus() ' Le da de nuevo el foco
Exit Sub
End If

Fechas
Para declarar una variable fecha tenemos varias posibilidades. En nuestro caso lo haremos
con alguna de las siguientes formas (es decir usando o no constructor y en este ltimo caso con
valor inicial por defecto o pasndole un valor existente).
Generalmente lo vamos a hacer:
Private fecha As Date ' Inicialmente vale #12:00:00 AM#, que es el valor por
defecto
Private ComienzoSigloXXI As New Date(2000, 1, 1, 0, 0, 1) ' Comienza en la hora
0:0:1 del da 1/1/2000
Private fechaAct As Date = Today ' Se guarda solo la fecha actual, h:m:s se
quedan a 0
Private fechaHoraAct As Date = Now ' En este caso recibe la fecha actual y hora
del sistema

Funciones de fechas: Mdulo DateAndTime y mtodos de datos


de tipo fecha
El mdulo DateAndTime contiene los procedimientos y propiedades que se utilizan en
operaciones de fecha y hora. Veamos algunas de las ms interesantes.
Nota. Varias operaciones las podemos resolver mediante funciones de este mdulo o gracias
a otras propiedades o mtodos de las variables de tipo fecha. As que definiremos aqu las que
sean exclusivas de esta forma. Por ejemplo existe la funcin Month que tambin es una
propiedad de las variables de tipo fecha. Sin embargo MonthName no existe en los mtodos de
las variables, as que deberemos recurrir a esta forma.
Dim fecha As Date = "1/12/2001"

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 73

Desarrollo de Aplicaciones Multiplataforma


lblMes.Text = DateAndTime.Month(fecha) ' Como DateAndTime es mdulo, se puede
poner directamente Month(fecha). Obtenemos el 12, n del mes de la fecha
lblMes.Text = fecha.Month ' Obtenemos lo mismo que en el caso anterior, el 12
lblNomMes.Text = DateAndTime.MonthName(12) ' Muestra el nombre del mes en el
idioma en que est configurado el ordenador en el que se ejecuta el proyecto. En
el caso de ser el espaol pondra Diciembre. Esta funcin solo existe aqu.

Te marco en negrita las que ms vamos a utilizar, por ser ms tiles o porque no se
encuentran como miembros de los datos de tipo fecha.

Propiedades
Nombre
Now

Descripcin
Devuelve un valor de Date que contiene la fecha y la hora actuales segn el sistema.

TimeOfDay Devuelve o establece un valor de Date que contiene la hora actual del da segn el sistema.
Today

Devuelve o establece un valor de Date que contiene la fecha actual segn el sistema.

Mtodos
Nombre

Descripcin

DateAdd

Devuelve un valor de Date que contiene un valor de fecha y hora al que se ha sumado
un intervalo de tiempo especificado.

DateDiff

Devuelve un valor Long que especifica el nmero de intervalos de tiempo entre dos
valores de Date.

DatePart

Devuelve un valor Integer que contiene el componente especificado de un valor de


Date dado.

Day

Devuelve un valor de tipo Integer del 1 al 31 que representa el da del mes.

Hour

Devuelve un valor de tipo Integer del 0 al 23 que representa la hora del da.

Minute

Devuelve un valor de tipo Integer del 0 al 59 que representa el minuto de la hora.

Month

Devuelve un valor de tipo Integer del 1 al 12 que representa el mes del ao.

MonthName

Devuelve un valor de tipo String que contiene el nombre del mes especificado.

Second

Devuelve un valor de tipo Integer del 0 al 59 que representa el segundo del minuto.

DateSerial

Devuelve un valor de Date que representa un ao, mes y da especificados, con la


informacin de hora establecida en medianoche (00:00:00). Ejemplo:
Dim primerDiaSigloXX1 As Date = DateSerial(2000, 1, 1). En este caso
parece ms lgico declarar una variable Date con el constructor (ver punto Fechas)

TimeSerial

Devuelve un valor de Date que representa una hora, un minuto y un segundo


especificados, con la informacin de fecha establecida con respecto al 1 de enero del
ao 1.

TimeValue

Devuelve un valor de Date que contiene la informacin de hora representada por una
cadena, con la informacin de fecha establecida en el 1 de enero del ao 1.

Weekday

Devuelve un valor de tipo Integer que contiene un nmero que representa el da de la


semana.

Devuelve un valor de tipo String que contiene el nombre del da de la semana


especificado. Cuidado! Debemos tener en cuenta que mientras que el mtodo
DayOfWeek devuelve valores entre 0 y 6 (que son las constantes que van desde
WeekdayName Monday -0-a Sunday -6-) estenecesita como primer parmetro el da de la semana,
valor que interpreta de 1 a 7.
Observa la siguiente instruccin:
lblDiaSemanaActual.Text = DateAndTime.WeekdayName(Today.DayOfWeek + 1, False,
FirstDayOfWeek.Sunday)

Year

Devuelve un valor de tipo Integer del 1 al 9999 que representa el ao.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 74

Desarrollo de Aplicaciones Multiplataforma


Me.Text = "Fecha actual " & DateAndTime.Today ' Muestra la fecha actual del
sistema, puede escribirse directamente Today
lblMes.Text = Today.Month ' Escribe en la etiqueta el n del mes de la fecha
actual
lblNomMes.Text = MonthName(Today.Month) ' Muestra el nombre del mes actual
Dim diasVividos As Integer = DateDiff(DateInterval.Day, fechaNac,
DateAndTime.Today) ' Resta y devuelve los das (poque as le hemos indicado
mediante el intervalo DateInterval.Day) que hay de la fecha de nacimiento a la
actual (Today). Primero ponemos la mayor y luego la menor.
Dim horasVividas As Integer = DateDiff(DateInterval.Hour, fechaNac,
DateAndTime.Today) ' As obtenemos las horas entre dos fechas

Mtodos ms utilizados de datos de tipo fecha


Nombre

Descripcin

AddDays

Devuelve un nuevo objeto DateTime que suma el nmero especificado de das al valor
de esta instancia.

AddHours

Devuelve un nuevo objeto DateTime que suma el nmero especificado de horas al


valor de esta instancia.

AddMilliseconds

Devuelve un nuevo objeto DateTime que suma el nmero especificado de milisegundos


al valor de esta instancia.

AddMinutes

Devuelve un nuevo objeto DateTime que suma el nmero especificado de minutos al


valor de esta instancia.

AddMonths

Devuelve un nuevo objeto DateTime que suma el nmero especificado de meses al


valor de esta instancia.

AddSeconds

Devuelve un nuevo objeto DateTime que suma el nmero especificado de segundos al


valor de esta instancia.

AddTicks

Devuelve un nuevo objeto DateTime que suma el nmero especificado de pasos al


valor de esta instancia.

AddYears

Devuelve un nuevo objeto DateTime que suma el nmero especificado de aos al valor
de esta instancia.

DaysInMonth

Devuelve el nmero de das del mes y ao especificados.

IsLeapYear

Devuelve una indicacin en la que se precisa si el ao especificado es bisiesto.

Subtract

Resta la fecha y hora especificadas de esta instancia. Devuelve un objeto TimeSpan

Dim fecha As Date = txtFecha.Text


Dim fechaNueva As Date = fecha.AddYears(txtAos.Text) ' fechaNueva es la misma
que fecha pero con los txtAos.Text aadidos (o quitados en el caso de ser
negativo)
Dim fechaComienzoSiglo As New Date(2000, 1, 1) ' Le asigna el valor 1/1/2000
Dim tiempoSiglo As TimeSpan = Today.Subtract(fechaComienzoSiglo) ' Resta al da
actual la fecha del 1/1/2000. tiempoSiglo contiene el n de das, horas,
MessageBox.Show(tiempoSiglo.TotalDays) ' Indica los das que han pasado desde el
primer da del siglo

Para ver estas funciones y/o mtodos observa el siguiente ejemplo. Supongamos que
tenemos un formulario en el que tras comprobar que hay una fecha y un nmero en las dos cajas
de texto de arriba, muestra la fecha resultante de sumar a la fecha inicial los aos indicados. En
el caso del da de la semana y del mes se indicar en nmero y nombre.

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 75

Desarrollo de Aplicaciones Multiplataforma

El cdigo resultante sera:


Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
If Not IsDate(txtFecha.Text) Then ' Si no se puede considerar fecha el valor de
la caja de texto
MessageBox.Show("Debes introducir una fecha", "Error de entrada",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtFecha.Clear() ' limpia la caja de texto
txtFecha.Focus() ' Le da de nuevo el foco
Exit Sub
End If
If Not IsNumeric(txtAos.Text) Then
MessageBox.Show("Debes introducir un nmero", "Error de entrada",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
txtAos.Clear()
txtAos.Focus()
Exit Sub
End If
Dim fechaNueva As Date = CDate(txtFecha.Text).AddYears(txtAos.Text) ' Aunque
no usemos la funcin CDate aqu tambin funciona
lblDia.Text = fechaNueva.Day ' Para el da usamos el mtodo de las expresiones
de tipo Date.
' Podra ser tambien lblDia.Text = CDate(txtFecha.Text).Day
lblDiaSemana.Text = fechaNueva.DayOfWeek & " / " &
DateAndTime.WeekdayName(fechaNueva.DayOfWeek + 1,True, ) ' Da de la semana en
nmero y en nombre
lblMes.Text = fechaNueva.Month & " / " & DateAndTime.MonthName(fechaNueva.Month)
lblAo.Text = fechaNueva.Year
End Sub

Nota. Podemos generar una variable de fecha introduciendo hora, minutos y segundos como
mostramos a continuacin y ver tambin la diferencia de dos fechas en la forma:
Dim fNac As Date = New System.Date(1980, 8, 10, 6, 0, 0) ' Ao, Mes, Dia, Hora,
Minutos y Seg
lblHoraNac.Text = fNac.Hour ' Escribe el nombre del mes y la hora
Dim vivido As TimeSpan = Now.Subtract(fNac)
Dim minViv As Integer = vivido.TotalMinutes ' Now.Subtract(fNac).TotalMinutes

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 76

Desarrollo de Aplicaciones Multiplataforma

Mtodos de la clase String y de variables de tipo cadena


La clase String proporciona miembros para comparar objetos String, devolver el ndice de
un carcter o una cadena en un objeto String, copiar el valor de un objeto String, dividir una
cadena o combinar cadenas, modificar el valor de una cadena, aplicar formato a los nmeros, las
fechas y horas o los valores de enumeracin en una cadena y normalizar una cadena.
Utilizaremos los mtodos Compare, CompareOrdinal, CompareTo, Equals, EndsWith
y StartsWith para realizar comparaciones.
Los mtodos IndexOf, IndexOfAny, LastIndexOf y LastIndexOfAny para obtener el
ndice de una subcadena o un carcter Unicode en una cadena.
Para crear una o varias cadenas nuevas a partir de las partes de una cadena original,
tenemos los mtodos Substring y Split, y para crear una nueva cadena a partir de una o
varias subcadenas, utilizaremos los mtodos Concat y Join.
Para modificar toda una cadena o parte de ella, se utilizan los mtodos Insert, Replace,
Remove, PadLeft, PadRight, Trim, TrimEnd y TrimStart.
Para cambiar los caracteres Unicode de una cadena de maysculas a minsculas y
viceversa, usaremos los mtodos ToLower, ToLowerInvariant, ToUpper y
ToUpperInvariant.
Para obtener el nmero caracteres de una cadena se utiliza la propiedad Length y para
obtener acceso a los diferentes caracteres de una cadena la propiedad Chars.
Veamos algunas de ellas con determinados ejemplos:

String.Compare
Sirve para comparar dos cadenas, devolviendo un valor -1,0 o 1 dependiendo de que la
primera sea alfanumricamente menor, igual o mayor que la segunda. La usaremos cuando
deseamos considerar que maysculas y minsculas se consideren iguales.
Ejemplo:
If String.Compare("qu", "Qu", True) = 0 Then
MessageBox.Show("Son iguales") 'En este caso son iguales, pero con False como
ltimo parmetro habra considerado que son distintas
Else
MessageBox.Show("Son distintas")
End If

Tambin podemos ver cul de dos cadenas es mayor que la otra.


If String.Compare(cad1,cad2, True) > 0 Then 'Mira si la 1 es > que la 2.
Ejemplo si cad1=Adios y cad2 = Baln el resultado es -1 as que no entrar en
el If, pero si cad1 = Agur y cad2 = adios entrar en el If porque agur es
mayor que adios independientemente de cmo est escrito (por el True final)

Nota. Si necesitamos comparar 2 cadenas y queremos que considere maysculas y


minsculas de la forma en que est por defecto en el programa (generalmente se consideran
diferentes), no necesitamos utilizar ningn mtodo especial, vale con compararlas con los
operadores de comparacin =, >, >=, <, <= o <>
If cad1 = cad2 Then ' Compara si son iguales, considera May <> min.
If cad1 > cad2 Then ' Compara si la primera es > que la segunda, considera May <> min. Ejemplo
Salinas es mayor que Baln pero menor que Adios
' Las anteriores instrucciones son equivalentes: a
If String.Compare(cad1, cad2) = 0 Then 'O tambin : If String.Compare(cad1, cad2, False)

If String.Compare(cad1, cad2) > 0 Then

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 77

Desarrollo de Aplicaciones Multiplataforma

Veamos como en el caso anterior los mtodos que ms vamos a utilizar en el caso de las
variables de tipo String. Si necesitas otros puedes acceder a la ayuda de VStudio.
Nombre

Descripcin

Contains

Devuelve un valor que indica si el objeto String especificado aparece dentro de esta
cadena.

EndsWith

Determina si el final de esta instancia de cadena coincide con la cadena especificada.

IndexOf

Indica el ndice de la primera aparicin de la cadena especificada en la instancia en


cuestin.La bsqueda comienza en una posicin de carcter especificada, si no se
especifica lo hace desde el comienzo.

Insert

Inserta una instancia especificada de String en una posicin de ndice especificada de la


instancia.

Indica la posicin de ndice de la ltima aparicin de una cadena especificada en la


LastIndexOf instancia en cuestin.La bsqueda comienza en una posicin de carcter especificada y
examina un nmero especificado de posiciones de caracteres, si as se indican.
Remove

Elimina todos o un nmero de caracteres especificados de la cadena, a partir de una


posicin especificada y hasta la ltima posicin.

Replace

Devuelve una nueva cadena en la que todas las apariciones de una cadena especificada en
la instancia actual se reemplazan por otra cadena especificada.

Split

Devuelve una matriz de cadenas que contiene las subcadenas de esta instancia que estn
delimitadas por elementos de la matriz de caracteres Unicode especificada. Se puede
especificar mediante un parmetro el nmero mximo de subcadenas que se van a
devolver.

StartsWith

Determina si el principio de esta instancia de cadena coincide con la cadena especificada.

Substring

Recupera una subcadena de la instancia.La subcadena comienza en una posicin de


carcter especificada pudiendo indicar tambin una longitud.

ToLower

Devuelve una copia de esta cadena convertida en minsculas.

ToUpper

Devuelve una copia de esta cadena convertida en maysculas.

Trim

Quita todos los caracteres de espacio en blanco del principio y el final del String actual.

Y las propiedades:
Nombre
Descripcin
Chars
Obtiene el carcter situado en una posicin de carcter especificada en el objeto String actual.
Length

Obtiene el nmero de caracteres del objeto String ctual.

Veamos unos ejemplos que nos ayuden a entenderlas.

Longitud y caracteres de una cadena


If cad1.Length = cad2.Length Then ' Length: cantidad de caracteres de la cadena
MessageBox.Show("Ambas cadenas son igual de largas")
End If
If cad1.Chars(0) = cad2.Chars(0) Then ' Con Chars(indice) podemos acceder al
carcter que est en esa posicin
MessageBox.Show("El primer carcter es el mismo")
Else
MessageBox.Show("El primer carcter es diferente")
End If

Ver si una cadena est includa en otra: Contains, IndexOf,


StartsWith y EndWith
Dim cad As String = txtCadIni.Text

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 78

Desarrollo de Aplicaciones Multiplataforma


If cad.Contains(txtSubCad.Text) Then ' Si lo escrito en txtSubCad se encuentra en
cad
lblSubEnCad.Text = "S"
Else
lblSubEnCad.Text = "No"
End If
If cad.ToUpper.IndexOf(txtSubCad.Text.ToUpper) = -1 Then ' Devuelve -1 si no est
o un n indicando la posicin en que se encuentra (0 para la primera posicin).
Considera las dos en maysculas, as que no importar como estn escritas
lblPosSubEnCad.Text = "NO est"
Else
lblPosSubEnCad.Text = cad.IndexOf(txtSubCad.Text) ' Muestra la posicin se
encuentra
End If
If cad.StartsWith(txtSubCad.Text) Then
MessageBox.Show(cad & " SI comienza con " & txtSubCad.Text)
Else
MessageBox.Show(cad & " NO comienza con " & txtSubCad.Text)
End If

Manipular cadenas: SubString, Remove, Replace, Insert,


Trim, ToUpper y ToLower
Dim cad As String = "Hola que tal ests"
Dim subCad As String = cad.Substring(1, 2) ' subcad toma el valor "ol"
subCad = cad.Substring(5) ' subcad se queda con "que tal ests"
subCad = cad.Remove(2, 5) ' subCad se queda con "Hoqu tal ests?. Borra a partir
del 3 5 caracteres
subCad = cad.Remove(2) ' subCad se queda con "Ho. Borra a partir del 3 hasta el
final
subCad = cad.Replace("l", "RR") ' subCad se queda con "HoRRa, qu taRR ests?"
Dim superCad As String = cad.Insert(4, " alumn@ de 1 DAM") ' supercad valdr
"Hola alumn@ de 1DAM, qu tal ests?"
Dim
Dim sinBlancosMay As String = "
Sin los de izq ni dcha
".ToUpper.Trim ' se
queda con "SIN LOS DE IZA NI DCHA" por ToUpper y Trim
If "hola" = "Hola" Then ' Ser False, no se consideran iguales
If "hola".ToUpper = "Hola".ToUpper Then ' Ser True, en maysculas ambas son
iguales

Creacin de nmeros aleatorios


Para lograr que un programa genere una serie de nmeros aleatorios (valores que siempre
sern de no negativos) disponemos de la clase Random. Declarando un objeto de esta clase, y
gracias a sus mtodos Next, podremos obtener los nmeros aleatorios bajo las condiciones que
le especifiquemos.
Para ello definiremos los mtodos que ms vamos a utilizar de esta clase, y que son:
Nombre
Next

Descripcin
Devuelve un nmero aleatorio entero no negativo.

Next(Int32)

Devuelve un nmero aleatorio no negativo menor que el valor mximo especificado.

Next(Int32, Int32) Devuelve un nmero aleatorio que se encuentra en el intervalo especificado.


NextBytes

Rellena con nmeros aleatorios los elementos de una matriz de bytes especificada.

NextDouble

Devuelve un nmero aleatorio entre 0,0 y 1,0.

Como ves, tenemos el mtodo Next sobrecargado, para pedir que nos genere un n aleatorio
sin ms, menor que un valor dado o dentro de un rango definido.
Ejemplo:

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 79

Desarrollo de Aplicaciones Multiplataforma


Dim rnd As New Random()' Solo debemos declarar una variable Random para todo el
programa
Dim numAlea As Integer
numAlea = rnd.Next ' numAlea coger cualquier valor
numAlea = rnd.Next(10) ' numAlea guardar un valor entre 0 y 9
numAlea = rnd.Next(50, 101) ' el n aleatorio se encontrar entre 50 y 100

Si deseamos generar un nmero double entre 0 y 1 usaramos NextDouble en la forma:


Dim numAleaDob As Double
numAleaDob = rnd.NextDouble
decimales)

' numAleaDob coger cualquier valor entre 0 y 1 (con

Si lo que deseamos es obtener un conjunto de nmeros en un array usaramos NextBytes en


la forma:
Dim numsAlea(25) As Byte ' Array para contener 25 nmeros de tipo Byte
rnd.NextBytes(numsAlea) ' El array numsAlea se llena con 25 enteros aleatorios
(con valores entre 0 y 255 por ser de tipo Byte)

VB.Net (Cap 4 Funciones estndar y mtodos de inters)

Pg. 80

Desarrollo de Aplicaciones Multiplataforma

Cap 5. Procedimientos y funciones: Sub y


Function
Qu son los procedimientos?
Todo el cdigo ejecutable de una aplicacin VB se ubica en rutinas de cdigo o
procedimientos. Un procedimiento es un elemento del lenguaje compuesto por un conjunto de
instrucciones, a las que se denomina cuerpo del procedimiento. Su comienzo y fin lo
establecemos mediante las palabras reservadas Sub . End Sub o Function End Function,
asocindole un nombre o identificador, que nos servir para reconocerlo entre el resto de
procedimientos creados en el programa. Podemos enviarle tambin informacin adicional en
forma de parmetros, con lo que el resultado de la ejecucin de un procedimiento variar segn
los valores que pasemos en cada llamada.
En VB disponemos de los siguientes tipos de procedimientos:
Sub. Procedimiento que realiza un conjunto de operaciones pero no devuelve valor al
punto de llamada. A estos les llamaremos con el nombre genrico de procedimiento.
Los controladores de eventos son procedimientos Sub que se ejecutan en respuesta a
un evento.
Function. Procedimiento (le llamaremos funcin) que realiza un conjunto de
operaciones, y devuelve un valor denominado valor de retorno al punto de cdigo que
realiz la llamada.
Property. Procedimiento que se utiliza para labores de acceso y asignacin de
valores a las propiedades de un objeto. Sern tratados con ms profundidad en el tema
dedicado a la programacin orientada a objetos.
De hecho, en la base de una aplicacin en VB estn sus procedimientos conducidos por
eventos. Un procedimiento orientado a evento es un procedimiento que es invocado cuando un
objeto reconoce que ha ocurrido un determinado evento sobre l.
Ejemplo:
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As Handles
btnAceptar.Click
' Instrucciones a ejecutar cuando el o la usuaria hace Clic sobre el botn
btnAceptar"
End Sub

En general, un procedimiento es invocado cuando se hace una llamada explcita al mismo.


Cuando un procedimiento llama a otro procedimiento, se transfiere el control al segundo
procedimiento. Al finalizar la ejecucin del cdigo del segundo, ste devuelve el control al
procedimiento que lo invoc.
Debido a esta funcionalidad, los procedimientos resultan tiles para realizar tareas repetidas
o compartidas. En lugar de escribir el mismo cdigo ms de una vez, podemos escribir un
procedimiento e invocarlo (llamarlo) desde varios puntos de nuestra aplicacin o desde otras
aplicaciones.
Podemos invocar cualquier tipo de procedimientos, pudiendo hacer esto tambin con los
procedimientos orientados a eventos.
Ejemplo: Desde el procedimiento frmBanco_Load deseamos ejecutar las instrucciones que se
realizarn cuando la usuaria o usuario haga clic sobre el botn Aceptar. Para ello haramos una
llamada explcita del mismo, en la forma:

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 81

Desarrollo de Aplicaciones Multiplataforma


Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
btnAceptar_Click(btnAceptar, e) ' Qu escribir en el parmetro de llamada:
btnAceptar o sender, ... lo veremos ms adelante
End Sub

Un procedimiento estndar puede escribirse como procedimiento Sub o como funcin


Function. Un procedimiento conducido por un evento siempre es un procedimiento Sub.

mbito de los procedimientos


Utilizaremos un modificador de acceso para definir el mbito o accesibilidad de los
procedimientos que escribimos (es decir, el permiso para que otro cdigo invoque al
procedimiento). Si no especificamos un modificador de acceso, se considera Public de forma
predeterminada.
La siguiente tabla muestra las opciones de accesibilidad para declarar un procedimiento:
mbito

Descripcin

Public

Ninguna restriccin de acceso

Private

Solo accesible desde el mdulo o clase que contiene la declaracin

Protected, Friend y
Protected Friend

Estos los veremos ms adelante, cuando estemos hablando de OOP

Funciones (Function)
Una funcin es un procedimiento que cuando se ejecuta devuelve un resultado.

Sintaxis en la definicin de una funcin


[mbito] Function Nombre_Funcin [(Lista de parmetros)] [As tipoDato]
instrucciones a ejecutar cuando se invoque la funcin pudiendo incluir una o
varias instruccin Return expresin
End Function
Vamos a definir y llamar a un par de funciones, que recojan diferentes conceptos de los que
deseamos explicar.
Por una parte tendremos la funcin Area que devuelve el rea del crculo cuyo radio se
corresponde con el valor pasado como parmetro. Si el radio es negativo devuelve un -1 para
que el o la usuaria de la funcin sepa que es errneo.
' Es privada para el lugar donde se define
Private Function Area(ByVal radio As Decimal) As Decimal
If radio <= 0 Then Return 0 ' Si el radio es negativo o 0, devuelve este valor
para error
Return Math.PI * radio ^ 2 ' Este ser el valor devuelto siempre que el radio
sea positivo
End Function

Y una segunda, que dados dos nmeros devuelva el cociente de la divisin entera como
resultado de una funcin y el resto mediante un parmetro de salida.

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 82

Desarrollo de Aplicaciones Multiplataforma


Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal
' Es visible desde cualquier lugar del proyecto ya que la hemos definido como
Public
Dim cociente As Decimal
cociente = dividendo \ divisor ' Calcula el cociente de la divisin
resto = dividendo Mod divisor ' El parmetro resto sale con ese valor, el
resto de la divisin entera
Return cociente ' Devuelve como resultado de la funcin
End Function

Si desde el formulario frmDatos queremos usar estas funciones pondramos hacerlo en la


forma:
Private Sub btnAceptar_Click(ByVal ) Handles btnAceptar.Click
Dim coc As Integer, res As Integer
coc = DivisionEntera(3, 5, res)
MessageBox.Show("El cociente de dividir 3 entre 5 es " & coc & " y el resto "
& res)
Dim areaCir As Decimal = Area(txtRadio.Text)
MessageBox.Show("El area del crculo cuyo radio es " & txtRadio.Text & " es "
& areaCir)
End Sub

mbito: Como ya hemos dicho, define el lugar desde el que se puede acceder a la
funcin y para empezar vemos el mbito Private (solo desde el formulario, mdulo o
clase que lo define) y Public para que pueda acceder a l desde cualquier lugar de la
aplicacin.
Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal
Private Function Area(ByVal radio As Decimal) As Decimal

Function...End Function. Palabras clave que indican el comienzo y final de la


funcin respectivamente. Cuando hagamos una llamada a la funcin, el compilador
ejecutar el cdigo comprendido entre estas dos palabras clave.
Private Function Area(ByVal radio As Decimal) As Decimal
End Function

Nombre_Funcin: Es el nombre de la funcin que es por tanto quin la define.


Private Function Area(ByVal radio As Decimal) As Decimal

TipoDato. Tipo de dato del valor devuelto como resultado de la ejecucin de la


funcin.
Private Function Area(ByVal radio As Decimal) As Decimal

Lista de parmetros: Lista de variables separadas por comas, y encerradas entre


parntesis, que representan la informacin que recibe la funcin desde el cdigo
llamador Cuando se llama a una funcin, VB asigna el valor de cada argumento en la
llamada al parmetro que ocupa su misma posicin en la lista de parmetros de la
funcin. Los parmetros pueden ser por valor o por referencia. Para que un parmetro
sea considerado por valor necesita la palabra reservada ByVal y ByRef cuando
deseemos que sea por referencia. Este punto lo tratamos con ms detalle un poco ms
adelante.
Private Function Area(ByVal radio As Decimal) As Decimal
Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 83

Desarrollo de Aplicaciones Multiplataforma

Return expresin: Esta palabra clave permite salir de la ejecucin de la funcin


devolviendo al mismo tiempo un valor al cdigo que hizo la llamada. Podemos
utilizarla dentro de una funcin, en tantos lugares como necesitemos.
Private Function Area(ByVal radio As Decimal) As Decimal
Devuelve 2 valores diferentes dependiendo del valor del radio
If radio <= 0 Then Return 0
Return Math.PI * radio ^ 2
End Function

Llamada a una funcin


Para realizar una llamada o ejecutar un procedimiento Function debemos escribir su nombre
en un punto del programa; en este aspecto ambos tipos de procedimiento son iguales.
[variable =] Nombre_Funcin [(lista de argumentos)]
Lista de argumentos: Son una lista de constantes, variables o expresiones separadas
por comas. El nmero de argumentos deber ser igual al nmero de parmetros de la
funcin. Los tipos de los argumentos deben coincidir con los tipos de sus
correspondientes parmetros. Una llamada a una funcin puede formar parte de una
expresin.
coc = DivisionEntera(3, 5, res)
lblArea.Text = DivisionEntera(txtDdno.Text, txtDvor.Text, res)
lblResto.Text = res
Dim areaCir As Decimal = Area(txtRadio.Text)

Siguiendo con nuestros ejemplos, podemos hacer las siguientes llamadas:


coc = DivisionEntera(3, 5, res)
Dim areaCir As Decimal = Area(txtRadio.Text)
MessageBox.Show ("Area del circulo de radio 2 " & Area(2))
lblArea.Text = Area(txtRadio.Text)

Como puedes apreciar en los ejemplos, siempre haremos algo con el resultado de la funcin,
o bien asignaremos a una variable, al texto de un control, mostrarlo en un MessageBox o lo que
necesitemos en el momento.

Procedimientos (Sub)
Sintaxis que define un procedimiento Sub
[Ambito] Sub Nombre_Procedimiento [(Lista de parmetros)]
Instrucciones del Sub pudiendo incluir una o varias instruccin Exit Sub
End Sub
La explicacin es anloga a la dada para las funciones.
Veamos un ejemplo:
Public Sub MostrarHora(ByVal seg As Integer)
Dim hora As Date
hora = DateAndTime.TimeOfDay.AddSeconds(seg)
MessageBox.Show("Dentro de " & seg & " segundos sern las " & hora)
End Sub

Si te fijas, en el caso de los procedimientos orientados a eventos estamos ante un


Subprograma, que adems tiene la caracterstica especial de ser orientada a evento gracias a la
parte Handles.
Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
MostrarHora(5) ' llamada al procedimiento conel valor de 5 para los seg

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 84

Desarrollo de Aplicaciones Multiplataforma


End Sub

Llamada a un procedimiento Sub


Como en el caso de las funciones, pero con la salvedad de que no podemos asignar el
procedimiento a ninguna variable, ni sacarlo en un MessageBox, ya que un procedimiento no
devuelve ningn valor.
Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
MostrarHora(5) ' llamada al procedimiento conel valor de 5 para los seg
End Sub

Cmo declarar argumentos en los procedimientos


Un procedimiento que realiza tareas repetidas o compartidas utiliza distinta informacin en
cada llamada. Esta informacin puede estar formada por variables, constantes y expresiones que
se pasan al procedimiento por el procedimiento que origina la llamada. Cada valor que se pasa a
un procedimiento se denomina argumento.
Cuando definimos un procedimiento en VB.Net, describimos los datos y los tipos de datos
para los que el procedimiento est diseado para aceptar desde un procedimiento de llamada.
Los elementos definidos en el procedimiento se denominan parmetros.
Cuando invocamos el procedimiento, sustituimos un valor actual de cada parmetro. Los
valores que asignamos en lugar de los parmetros se denominan argumentos.

Declarar argumentos
Declaramos cada argumento de un procedimiento del mismo modo en que declaramos una
variable, especificando el nombre del argumento y el tipo de datos. Observa que incluso los
procedimientos orientados a eventos tienen dos argumentos que son definidos por valor.
Private Function Area(ByVal radio As Decimal) As Decimal
Public Function DivisionEntera(ByVal dividendo As Integer, ByVal divisor As
Integer, ByRef resto As Integer) As Decimal
Public Sub MostrarHora(ByVal seg As Integer)
Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load

Atencin: No es necesario que los nombres de argumentos utilizados cuando se invoca un


procedimiento coincidan con los nombres de parmetros utilizados para la definicin del
mismo.
MessageBox.Show("El rea de " & miRadio & " es " & Area(miRadio)) ' En la llamada la
variable es miRadio y en la declaracin radio. Al realizar la llamada (al invocar
a la funcin Area) la variable radio coge el valor que lleve la variable miRadio
y trabaja con ese valor.

Paso por valor (ByVal)


Cuando pasamos un parmetro por valor a un procedimiento, la variable que contiene el
parmetro puede ser modificada dentro del procedimiento, sin que estos cambios afecten al
valor original en el cdigo llamador. Debemos situar en este caso en el procedimiento, la
palabra clave ByVal antes del nombre del parmetro.
Veamos un ejemplo: Supongamos que tenemos la siguiente funcin:
Private Function Triple(ByVal num As Decimal) As Integer

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 85

Memoria

numero
5

Llamada
Triple(numero)

num
5
15

Declaracin de la funcin
Triple(ByVal num )

Desarrollo de Aplicaciones Multiplataforma


num = num * 3
Return num
End Function

Si hacemos las mismas llamadas nos encontraremos con algunos cambios tal vez no
previstos:
Dim numero As Integer = 5
Dim tri As Integer = Triple(numero)
MessageBox.Show("El triple del nmero " & numero & " es " & tri &
ControlChars.CrLf & "Y el triple de 3 es " & Triple(3)) ' En este caso la
variable numero cambia el valor, el 3 al ser un valor constante lgicamente no
puede cambiar

En este caso habramos mostrado una ventana como la que vemos a continuacin:

Lo que ocurre en el fuente anterior a nivel de gestin interna en memoria de los parmetros
es lo siguiente: cuando se realiza la llamada al procedimiento y se pasa el parmetro, el entorno
detecta que se trata de un parmetro pasado por referencia, y tanto la variable del cdigo
llamador como la del procedimiento llamado utilizan la misma direccin de memoria o
referencia hacia los datos, por lo que los cambios realizados en un procedimiento afectarn
tambin al otro. La siguiente figura muestra una representacin grfica de este proceso.

Memoria
num / numero
5
15

Llamada
Triple(numero)

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Declaracin de la funcin
Triple(ByRef num )

Pg. 87

Desarrollo de Aplicaciones Multiplataforma

Resumen del paso ByVal y ByRef


Cuando definimos un procedimiento, definimos el modo en el que otros procedimientos
pueden pasar argumentos al procedimiento. Podemos escoger pasarle argumentos por referencia
(ByRef) o por valor (ByVal).
Mecanismo
de paso

Explicacin

Implicaciones

Ventaja

Por valor:
ByVal

El procedimiento
invocado recibe una
copia de los datos
cuando es invocado

Si el procedimiento invocado
modifica la copia, el valor
original de la variable
permanece intacto. Cuando la
ejecucin retorna al
procedimiento de llamada, la
variable contiene el mismo valor
que tena antes de que el valor se
pasara.

Protege la variable de
ser cambiada por el
procedimiento
invocado.

Por
referencia:
ByRef

El procedimiento
invocado recibe una
referencia a los
datos originales (la
direccin de los
datos en memoria)
cuando es invocado.

El procedimiento invocado
puede modificar la variable
directamente. Cuando la
ejecucin retorna al
procedimiento de llamada, la
variable contiene el valor
modificado.

El procedimiento
invocado puede
utilizar el argumento
para devolver un
nuevo valor al cdigo
de llamada.

Paso de parmetros por posicin y por nombre. Parmetros


opcionales
Por otra parte tenemos un par de conceptos que nombraremos, pero en los que no vamos a
profundizar, ya que seguramente no vamos a utilizar.
Cuando al llamar a un procedimiento con parmetros, pasamos estos en el mismo orden
en el que estn especificados en la declaracin del procedimiento, se dice que se ha realizado
un paso de parmetros por posicin.
Existe adems, otro modo de paso de parmetros en el cul no estamos obligados a situarlos
en el mismo orden que indica la declaracin, es el llamado paso de parmetros por nombre. En
este tipo de paso, debemos situar en la llamada al procedimiento el nombre del parmetro,
seguido de los signos de dos puntos e igual (:= ) y finalmente el valor a pasar.
Un parmetro opcional es aquel que no es necesario especificar al hacer la llamada a un
procedimiento.
Para indicar en la declaracin de un procedimiento que un parmetro es opcional, debemos
utilizar la palabra clave Optional.
Si quieres puedes profundizar ms en estos conceptos iendo a la ayuda del propio VS.Net.

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 88

Desarrollo de Aplicaciones Multiplataforma

Sobrecarga de procedimientos: Overloads


Veamos lo que nos dice la documentacin de VS .NET sobre la sobrecarga de propiedades y
mtodos (o lo que es lo mismo, sobre la sobrecarga de procedimientos):
La sobrecarga consiste en crear ms de un procedimiento, constructor de
instancias o propiedad en una clase con el mismo nombre y distintos tipos de
argumento.
La sobrecarga es especialmente til cuando un modelo de objeto exige el uso de
nombres idnticos para procedimientos que operan en diferentes tipos de datos.

Es decir, que si necesitamos un procedimiento que utilice distinto nmero de parmetros o


parmetros de distintos tipos, podemos usar la sobrecarga de procedimientos.
Para definir un procedimiento como sobrecargado, debemos comenzar su declaracin con la
palabra clave Overloads. Podemos utilizar procedimientos tanto Sub como Function cuando
realizamos sobrecarga., siendo posible que una de las implementaciones no tenga lista de
parmetros. El siguiente cdigo fuente muestra un ejemplo de sobrecarga.
Public Overloads Sub Datos()
' cdigo del procedimiento
End Sub
Public Overloads Sub Datos(listaParametros)
' cdigo del procedimiento con parmetros
End Sub
Public Overloads Function Datos(listaParametros) As tipoRetorno
' cdigo de la funcin con parmetros
End Function

En el ejemplo anterior, cuando llamemos al procedimiento Datos( ), el entorno de .NET


Framework, en funcin de si pasamos o no parmetros al procedimiento, y de cmo sean
estos parmetros, ejecutar la versin adecuada del procedimiento.
Ya que el protocolo o firma del procedimiento es el elemento que emplea el CLR para
diferenciar cada una de sus versiones o implementaciones, las listas de parmetros de cada
versin deben ser diferentes al menos en uno de los siguientes aspectos:
Nmero de parmetros.
Orden de los parmetros
Tipo de dato de los parmetros.
Por consiguiente, no es posible crear dos procedimientos sobrecargados que slo se
diferencien en los nombres de los parmetros, por los modificadores de mbito (Public,
Private, etc.), o por el tipo de dato de retorno en el caso de un procedimiento Function.
Una vez vistas las normas y restricciones aplicables a los procedimientos sobrecargados,
veamos un ejemplo en el que aplicamos esta tcnica.
Supongamos que queremos definir una funcin Area, que calcule el rea de un crculo
sabiendo que depende del radio. Puede ocurrir que al llamarle a esta funcin, ella ya conozca el
Radio (lo tenga en una variable _Radio), o por el contrario debamos pasrselo como parmetro.
Tendramos las dos funciones siguientes:
' Primera version: Area sin parmetros
Public Overloads Function Area() As Double
Return Math.PI * _Radio ^ 2 '_Radio es una variable global que ya conoce
End Function

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 89

Desarrollo de Aplicaciones Multiplataforma


' Segunda version: Area con un parmetro
Public Overloads Function Area(ByVal radio As Double) 'Permite introducir el
radio siempre que no tuviese anteriormente
If _Radio <> 0 Then Throw New Exception("Ya tena radio") ' Si ya tena valor
en el _Radio no
_Radio = radio
Return Math.PI * _Radio ^ 2
End Function

En este cdigo hemos creado dos versiones sobrecargadas de la funcin Area.


Atencin: Cuando un procedimiento o funcin sobrecargada vaya a hacer las mismas
instrucciones que otra de sus versiones, en lugar de volver a escribir todo el cdigo (aunque en
este ejemplo solo sea una lnea) haremos una llamada al simple.
Public Overloads
If _Radio <> 0
en el _Radio no
_Radio = radio
parmetros
Return Area()'
End Function

Function Area(ByVal radio As Double)


Then Throw New Exception("Ya tena radio") ' Si ya tena valor
' Como ya _Radio tiene el valor, podemos llamar a la funcin sin
Ejecuta las instrucciones de la funcin sin parmetros

A la hora de invocar o llamar a la funcin, comprobaremos que si no se indica ningn


parmetro, el VB usar la primera declaracin mientras que si recibe un nmero llamar a la
segunda.
Nota: Cuando se usan procedimientos sobrecargados, es el propio compilador de Visual
Basic .NET el que decide cual es el procedimiento que mejor se adecua a los parmetros que se
han indicado al llamar a ese procedimiento.
Observa como al ir escribiendo nos indica y ayuda a elegir entre la deseada, incluso
dependiendo de cmo estemos escribiendo.

VB.Net (Cap 5. Procedimientos y funciones: Sub y Function)

Pg. 90

Desarrollo de Aplicaciones Multiplataforma

Cap 6. Programacin orientada a objetos (OOP)


Fundamentos de la Programacin Orientada a Objetos (OOP)
La organizacin de una aplicacin en Programacin Orientada a Objetos, tambin
denominada OOP (Object Oriented Programming) se realiza mediante estructuras de cdigo
denominadas Clases.
Una clase contiene un conjunto de procedimientos (y funciones) e informacin que ejecutan
una serie de procesos destinados a resolver un grupo de tareas con un denominador comn.
Una aplicacin orientada a objetos tendr tantas clases como aspectos del programa sea
necesario resolver.
Un procedimiento o funcin que est situado dentro de una clase, no podr llamar ni ser
llamado por otro procedimiento situado en una estructura distinta, si no es bajo una serie de
reglas. Lo mismo suceder con los datos que contenga la estructura, permanecern aislados del
exterior, y slo sern accesibles siguiendo ciertas normas.

Objeto
Un objeto es una agrupacin de cdigo, compuesta de propiedades y mtodos, que pueden
ser manipulados como una entidad independiente. Las propiedades definen los datos o
informacin del objeto, permitiendo consultar o modificar su estado; mientras que los mtodos
son las rutinas que definen su comportamiento.
Un objeto es una pieza que se ocupa de desempear un trabajo concreto dentro de una
estructura organizativa de nivel superior, formada por mltiples objetos, cada uno de los cuales
ejerce la tarea particular para la que ha sido diseado.

Clase
Una clase no es otra cosa que el conjunto de especificaciones o normas que definen cmo
va a ser creado un objeto de un tipo determinado; algo parecido a un manual de instrucciones
conteniendo las indicaciones para crear el objeto.
Los trminos objeto y clase son utilizados en OOP con gran profusin y en contextos muy
similares, por lo que para intentar aclarar en lo posible ambos conceptos, diremos que una clase
constituye la representacin abstracta de algo, mientras que un objeto constituye la
representacin concreta de lo que una clase define. Ejemplo, cuando decimos la palabra Coche
nos hacemos una imagen mental de lo que ese concepto significa y las acciones que puede
realizar, pero el objeto real es cuando hablamos de un coche concreto (ejemplo miCoche).
De la misma forma, conocemos la clase TextBox, Label, y los objetos txtNombre,
txtDireccin, lblResultados, .
Es decir, una clase que describe los objetos que de ella se pueden crear, tiene propiedades
que describen sus atributos, mtodos que definen sus acciones y eventos que definen sus
respuestas y que por tanto se pasarn a todas las instancias de esa clase.
Nota. Recuerda que, en realidad desde el comienzo, en todos nuestros proyectos tenemos
como mnimo definida una clase, la del formulario.
Es decir, cada vez que creamos (con el diseador) un nuevo formulario estamos creando una
clase cuyo nombre es el elegido para el formulario (si no lo cambiamos por defecto habra sido
Form1). El objeto ser luego el formulario que aparece en pantalla cuando ejecutemos el
programa y que tiene un comportamiento definido en la clase.

VB.Net (Cap 6. OOP)

Pg. 91

Desarrollo de Aplicaciones Multiplataforma


Public Class frmBanco
' Tenemos la clase frmBanco (la clase del formulario) con los procedimientos y/o
funciones que definamos y que el formulario real ejecutar en su momento.
Private Sub frmBanco_Load(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
' Cdigo a ejecutar cuando se carga el formulario
End Sub
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
' Cdigo que se ejecuta al hacer clic sobre el botn
End Sub
End Class

Instancias de una clase


El proceso por el cul se obtiene un objeto a partir de las especificaciones de una clase
se conoce como instanciacin de objetos. Es decir, la creacin de un nuevo objeto que
pertenezca a la clase, como cuando se crea un nuevo coche en la fbrica de coches. Cada vez
que se instancia un nuevo objeto, este comienza con unas propiedades por defecto (con un color
pintado, de un tamao, marca, con unas velocidades, con una respuesta concreta al arrancar el
coche,
Ejemplo: una clase que representa una CuentaBancaria podra tener propiedades como
NumCuenta, Titular, Saldo y FechaEdicion mtodos como Ingresar, Retirar y Antiguedad as
como eventos del tipo CambioSaldo. Una vez creada la instancia de un objeto de
CuentaBancaria, podramos tener acceso a sus propiedades, mtodos y eventos de igual manera
que si se tratara de un objeto TextBox.

Creando la clase
Para crear una nueva clase en VB.Net podrs hacerlo desde el men Proyecto -> Crear clase
o en el Explorador de Soluciones eligiendo el proyecto con el botn secundario del ratn para ir
a Agregar ->Clase como puedes apreciar en las siguientes figuras:

VB.Net (Cap 6. OOP)

Pg. 92

Desarrollo de Aplicaciones Multiplataforma

Si al crearla le ponemos el nombre CuentaBancaria, y observamos el Explorador de


Soluciones nos encontraremos con un nuevo fichero de extensin vb pero sin diseo de
formulario:

Y con el siguiente cdigo:


Public Class CuentaBancaria
End Class

Es decir, ya tenemos creada una nueva clase, an sin ninguna propiedad y con una serie de
mtodos aparentemente ocultos que tiene toda clase en VS.Net solo por el hecho de ser creada.
En realidad estos mtodos vienen definidos en la super clase Object de la cual hereda toda clase,
pero estos conceptos los dejaremos para ms adelante.
Estos mtodos iniciales los puedes apreciar en cuanto declares una variable de esta clase (un
objeto de esta clase), como se muestra en la siguiente figura:

Miembros de la clase
Los elementos de una clase que contienen sus datos y definen su comportamiento, es decir,
las propiedades y mtodos, reciben adems el nombre de miembros de la clase, trmino que
tambin venimos utilizando en repetidas ocasiones.

Propiedades
Una propiedad en la clase se define, por norma general (aunque haya casos en los que no sea
as), mediante dos elementos: una variable propiedad y un procedimiento que define a la
propiedad.
La variable de propiedad, tal y como su nombre indica, es una variable con mbito privado
a nivel de la clase, que se encarga de guardar el valor de la propiedad. Por su parte el
procedimiento de propiedad o Property, es el encargado de actuar de puente entre el cdigo
cliente y la variable de propiedad, realizando las operaciones de acceso y asignacin de valores
a dicha variable.
Por lo tanto, para crear una propiedad en nuestra clase, generalmente primero declararemos
una variable Private, y en segundo lugar un procedimiento de tipo Property, que consta de dos
bloques: Get, para devolver el valor de la variable de propiedad; y Set, para asignrselo.
Cuando declaramos un procedimiento Property, debemos, al igual que en una funcin,
tipificarlo (definirle el tipo al que pertenece), ya que una de sus labores consiste en la
devolucin de un valor.
Para devolver el valor, en el bloque Get utilizaremos la palabra clave Return, seguida del
valor de retorno.

VB.Net (Cap 6. OOP)

Pg. 93

Desarrollo de Aplicaciones Multiplataforma

En cuanto a la asignacin de valor, el bloque Set utiliza un parmetro con el nombre Value,
que contiene el valor para asignar a la propiedad.
Si seguimos con nuestra clase CuentaBancaria, recordaremos que tenamos las propiedades
NumCuenta, Titular y Saldo.
Observacin. En la declaracin de las clases seguimos con la notacin Camel, en la
siguiente forma: Para nombrar a la clase, propiedades, mtodos (y eventos si los hubiera)
comenzando con la primera letra en maysculas (ejemplo: clase CuentaBancaria, propiedad
NumCuenta), para las variables privadas o parmetros (value, cantidad) comenzando en
minsculas y en el caso de las variables propiedad (las que contienen el valor de la propiedad)
con el mismo nombre que la propiedad precedido del guin bajo: _Titular.
Public Class CuentaBancaria ' Nombre de la clase (empieza en May)
Private _Titular As String ' variable privada que va a contener el nombre de la
persona titular de la cuenta. Se llama igual que la propiedad pero con el _
Public Property Titular As String ' Definicin de la propiedad. El nombre en May
Get ' Se ejecuta cuando desde "el programa" se pregunta por el/la Titular
Return _Titular
' Devuelve el valor que tiene en la variable
End Get
Set(ByVal value As String) ' Se ejecuta cuando desde "el programa" se intenta
modificar al/a Titular con el valor que viene en la variable value. Este nombre
comienza en min
_Titular = value
' Modificaremos el valor de la variable para que recoja
el nuevo valor que viene en la variable value
End Set
End Property
End Class

Observacin: Te has dado cuenta que la variable de la propiedad y la propiedad son del
mismo tipo String? Esto es lgico y obligatorio, ya que si la variable contiene el valor de la
propiedad deber ser de ese tipo. No podramos decir que Titular es String y que _Titular es
Decimal.
De la misma forma empezaramos a declarar las propiedades NumCuenta y Saldo, pero antes
debemos hacernos la siguiente consideracin. As como el nombre de la persona titular de la
cuenta puede cambiar en cualquier momento, se puede cambiar el nmero de cuenta o la fecha
de edicin una vez creada? De la misma forma, podemos ir a la caja de ahorros o banco y
decirles que modifique nuestro Saldo sin hacer la operacin de Ingresar o Retirar dinero? Es
evidente que no. As pues en este ejemplo nos encontramos con 2 propiedades que necesitamos
definir como especiales, es decir, que se pueden leer (podemos preguntar por el Saldo o por el
NumCuenta) pero no modificar. Nos encontramos con las llamadas Propiedades de Solo
Lectura, que en el caso de VB.Net se declaran ReadOnly.
Cmo las definiramos en este caso?
Public Class CuentaBancaria
' Variables privadas. Contienen el valor de las propiedades de nombre semejante
Private _Titular As String
Private _Saldo As Decimal
Private _NumCuenta As Decimal
Private _FechaEdicion As Date
Public Property Titular As String
Escritura
' Definicin anterior
End Property

VB.Net (Cap 6. OOP)

' Definicin de la propiedad de Lectura y

Pg. 94

Desarrollo de Aplicaciones Multiplataforma


Public ReadOnly Property Saldo As Decimal ' Propiedad de Solo Lectura
Get ' El o la usuaria de la clase, puede preguntar por el Saldo
Return _Saldo
End Get
' Como no hay procedimiento Set, no podr modificar el saldo desde la
propiedad, necesitar de los mtodos Ingresar o Retirar
End Property
' Y as las otras dos, NumCuentay FechaEdicion las dos ReadOnly
End Class

Nota: De la misma forma que podemos definir una propiedad de slo lectura, tambin
podemos crear una propiedad de Slo Escritura (WriteOnly) es decir, una propiedad que slo
aceptar que se asignen nuevos valores, pero que no permitan obtener el valor que tienen... La
verdad es que este tipo de propiedades no son muy habituales, pero podemos hacerlo.
Veamos cmo tendramos que declarar una propiedad de slo escritura. Para ello vamos a
suponer (lo cual no es muy lgico) que tuvisemos una
' Supongamos que tuvisemos una propiedad Interes que se pueda modificar desde el
exterior ("por programa" o desde otra clase) pero que no se pueda leer (Es decir,
el programa o la otra clase no puedever el contenido de Interes)
Private _Interes As Decimal
Public WriteOnly Property Interes As Decimal ' Propiedad de solo escritura.
Set(ByVal value As Decimal) ' Solo tiene la parte del Set
_Interes = value
End Set
End Property

Mtodos
Adems de las propiedades vistas, habamos dicho que en una cuenta podamos Ingresar y
Retirar dinero y preguntar la Antigedad de la cuenta. Esto significa que tenemos que definir un
mtodo para cada accin.
Los mtodos estn definidos mediante subprogramas o funciones, que a su vez pueden tener
o no parmetros. Hemos elegido estos mtodos para tener una representacin de ambos casos.
Pensemos en la forma de definirlos. En los casos de Ingresar y Retirar, deberemos indicar la
cantidad con la que deseamos realizar la operacin, sabiendo que el Saldo sufrir una
modificacin.
As pues estos dos mtodos tendran una declaracin del tipo:
Public Sub Ingresar(ByVal cantidad As Decimal) ' Declaramos el mtodo Ingresar.
Necesita recibir como dato la cantidad de dinero a ingresar
_Saldo = _Saldo + cantidad ' Modificamos el valor de la variable que contiene
el Saldo. Esta instruccin es equivalente a _Saldo += cantidad
' Generalmente pondremos la propiedad en lugar de la variable, pero eso ser
cuando la propiedad no sea ReadOnly y se controle el dato que recibe
End Sub

Pero ojo!, en el caso de Retirar dinero deberemos tener en cuenta que no podemos retirar
una cantidad superior al saldo existente. Es por eso que definiremos este mtodo en la forma:
Public Sub Retirar(ByVal cantidad As Decimal)
If cantidad <= _Saldo Then _Saldo = _Saldo - cantidad ' Solo modificamos el
valor del Saldo si hay suficiente
End Sub

Atencin: En este caso si la cantidad solicitada es superior al saldo no estamos haciendo


nada con el Saldo (lgico, pues no tenemos suficiente) pero tampoco hacemos nada para que el
o la usuaria del mtodo se entere de lo que est ocurriendo. Esto no es muy lgico, ya que lo
normal es que haya alguna forma de avisarle. Dependiendo del caso y del gusto de quien

VB.Net (Cap 6. OOP)

Pg. 95

Desarrollo de Aplicaciones Multiplataforma

programa se har alguna forma, pero en general podemos decir que nunca ser mediante un
MessageBox!!!!
Lo normal en este caso sera provocar una excepcin, pero esto lo veremos ms adelante. Otra
posibilidad sera que en lugar de un Sub fuese una funcin y devolviese la cantidad retirada, en
la forma:
Public Function Retirar(ByVal cantidad As Decimal) As Decimal ' Devuelve la
cantidad realmente retirada
If cantidad <= _Saldo Then
_Saldo = _Saldo - cantidad ' Solo modificamos el valor del Saldo si hay
suficiente
Return cantidad ' Hemos retirado esta cantidad del saldo
End If
Return 0 ' No se ha retirado nada, ya que no ha entrado en el If
End Function

Propiedad o mtodo? Propiedades que no tienen variable asociada.


Y por ltimo tendramos el caso de la Antigedad de la cuenta, es decir, la cantidad de das
que han transcurrido desde que se cre la cuenta.
Para eso definiremos Antigedad, que en cualquier momento deber calcular los das que
han pasado desde la fecha de edicin de la cuenta hasta el da actual.
Cmo consideramos este concepto? Es una accin que puede realizar el objeto, y por tanto
lo definiramos como un mtodo, o es una caracterstica de la cuenta que no puede modificarse
desde el exterior pero que le define, lo cual nos determinara una propiedad de solo lectura?.
Hay ocasiones como esta en que no est nada claro y que en realidad cualquiera de los
conceptos es vlido. El decidirnos por uno u otro en muchas ocasiones depende de la persona
que est programando, sin ninguna norma que lo aclare.
Si lo consideramos un mtodo lo definiramos en la forma:
Public Function Antiguedad() As Integer
Dim dias As Integer = DateDiff(DateInterval.Day, _FechaEdicion,
DateAndTime.Today) ' Dias que han pasado entre ambas fechas
Return dias
'Tambin podra hacerse directamente:
'Return DateDiff(DateInterval.Day, _FechaEdicion, DateAndTime.Today)
End Function

Si lo consideramos propiedad de solo lectura, quedara:


Public ReadOnly Property Antiguedad() As Integer
Get
Dim dias As Integer = DateDiff(DateInterval.Day, _FechaEdicion,
DateAndTime.Today) ' Dias que han pasado entre ambas fechas
Return dias
End Get
End Property

Observacin: Este es un ejemplo de propiedad que no lleva una variable privada


asociada ya que en realidad se calcula a partir de otros datos.

VB.Net (Cap 6. OOP)

Pg. 96

Desarrollo de Aplicaciones Multiplataforma

Definiendo y creando objetos a partir de la clase


Como hemos visto, mediante la declaracin de la clase hemos definido las caractersticas de
una cuenta bancaria. Pero an no tenemos ninguna. Cmo lo conseguimos? Pues declarando y
posteriormente creando variables de esa clase.
Nota: En realidad, declarar una variable de una clase es declarar una referencia a un objeto.
Ejemplo:
Dim miCuenta As CuentaBancaria ' Declaramos una variable de la clase
CuentaBancaria, que en su momento har referencia a un objeto de dicha clase. As
declarada en realidad an no existe, no hace referencia a ninguno.

Para que una variable de este tipo realmente referencie a un objeto real tenemos dos
posibilidades:
Crendolo mediante el operador New.
miCuenta = New CuentaBancaria ' Crea un nuevo objeto de esta clase, con los
valores iniciales en sus propiedades.

Crear un objeto significa reservar un nuevo espacio en memoria para sus atributos.
Haciendo referencia a otro objeto ya existente.
Dim otraCuenta As CuentaBancaria
otraCuenta = miCuenta

Cuidado! A diferencia de las variables de tipos normales, al realizar una asignacin de


una variable a otra, en realidad lo que estamos diciendo es que ambas hacen referencia al mismo
objeto. Es decir, ambas variables estn dirigindose al mismo espacio de memoria, por lo que
ambas tienen los mismos valores en todas sus propiedades.

miCuenta

otraCuenta

_FechaInicio: 10/12/2011
_Saldo: 3500
_Titular: 1DAM
_NumCuenta: 30350058215421254589
Ingresar
Retirar
Antiguedad

Observa las siguientes instrucciones:


Dim miCuenta As New CuentaBancaria
miCuenta.Titular = "1DAM" ' Como titutar de esta cuenta tenemos a "1DAM"
Dim otraCuenta As CuentaBancaria = miCuenta ' Ambas hacen referencia a la misma
cuenta
otraCuenta.Titular = "Mara"
MessageBox.Show(miCuenta.Titular) ' Qu mostrara este MessageBox en pantalla?

La respuesta a la pregunta es Mara, ya que ambas variables hacen referencia al mismo


objeto, por tanto si se modifica el valor de una propiedad ambas sufren esa modificacin. Se
dice que la asignacin en variables de este tipo es por referencia, se pasa la referencia al objeto.
Es diferente para variables de tipos estndar en los que la asignacin se denomina por valor,
ya que lo que se asigna es el valor quedando las variables independientes:
Dim miTitular As String = "1DAM"
Dim otroTitular As String = miTitular ' Solo le asigna el valor
otroTitular = "Mara"
MessageBox.Show(miTitular) ' Que mostrara en este caso?

VB.Net (Cap 6. OOP)

Pg. 97

Desarrollo de Aplicaciones Multiplataforma

En este caso escribira 1DAM ya que miTitular se ha quedado con el valor que tena.
Una vez creado un objeto, podremos utilizar sus propiedades y/o mtodos, como vemos en la
siguiente imagen.

Atencin. Aunque las propiedades y/o mtodos los saque solo por tener declarada la
variable, si hacemos referencia a una propiedad sin haber creado (New) o referenciado a un
objeto mediante una asignacin como en el caso anterior, la instruccin dara error de
ejecucin., como puedes ver en la siguiente imagen. Observa que miCuenta sala subrayada en
verde.

En realidad, si acercas el ratn al cdigo te encontraras con el siguiente mensaje:

Tambin podemos definir y crear un objeto en una sola instruccin en la forma:


Dim miCuenta As New CuentaBancaria ' Declara y crea una variable de la clase
CuentaBancaria

Uso de las propiedades y/o mtodos


Vamos a ver mediante un programa como podemos trabajar con la clase.
Si queremos cambiar el valor de una propiedad lo haremos con la tpica asignacin, como
puedes ver en el siguiente ejemplo:
Private miCuenta As CuentaBancaria ' Declara un objeto global de la clase
CuentaBancaria
Private Sub btnNuevaCuenta_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnNuevaCuenta.Click
miCuenta = New CuentaBancaria ' Crea una nueva cuenta
miCuenta.Titular = txtTitular.Text ' Le da a la propiedad Titular este valor
End Sub

Si queremos conocer su valor, tambin podemos hacerlo en la forma tradicional. Ejemplo:

VB.Net (Cap 6. OOP)

Pg. 98

Desarrollo de Aplicaciones Multiplataforma


Private Sub btnMostrarSaldo_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnMostrarSaldo.Click
MessageBox.Show("El saldo es " & miCuenta.Saldo, "Atencin")
End Sub

En cambio si quisiramos modificar el Saldo nos dara un error de compilacin, como


puedes apreciar en la figura, ya que lo hemos definido como de solo lectura, y por tanto no se
puede modificar:

Recordemos que el Saldo solo se poda modificar gracias a los mtodos Ingresar o Retirar.
Veamos su uso:
Private Sub btnIngresar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnIngresar.Click
If Not IsNumeric(txtCantidad.Text) Then Exit Sub
MessageBox.Show("Saldo actual " & miCuenta.Saldo, "Atencin")
miCuenta.Ingresar(txtCantidad.Text) ' Invoca al mtodo Ingresar del objeto
MessageBox.Show("El nuevo saldo es " & miCuenta.Saldo, "Atencin")
End Sub

Con los 2 MessageBox mostrando el Saldo de esa cuenta, conseguiramos ver el que tena
antes de ingresar esa cantidad y el que le queda tras hacerlo.
Recuerda que no habramos podido hacer la siguiente instruccin por ser una propiedad de
solo lectura, es decir, no se permite modificar desde el exterior de la clase.
miCuenta.Saldo = miCuenta.Saldo + txtCantidad.Text
propiedad ReadOnly

' Error de compilacin,

Mtodos constructores
El primer mtodo que es ejecutado al instanciar un objeto de la clase se denomina
constructor. Este tipo de mtodo resulta til para tareas de configuracin iniciales sobre el
objeto.
No es necesario escribir un mtodo constructor en la clase, ya que en el caso de que no
exista, el compilador se encarga de crearlo implcitamente. Es decir, tras construirse el objeto,
qu valor tienen sus propiedades por defecto? Pues como estamos en el lenguaje VB y este
inicializa las variables con unos valores concretos, esta ser la lgica que se mantendr.
Si continuamos con el ejemplo que llevamos de nuestra CuentaBancaria, qu ocurre con las
propiedades antes de asignarle ningn valor?
Dim otraCuenta As New CuentaBancaria
MessageBox.Show("Titular :" & miCuenta.Titular & ControlChars.CrLf & "Saldo " &
miCuenta.Saldo) ' Qu valores mostrara este MessageBox?

Pues, como no hemos definido ningn constructor y Titular es String, devolvera el valor
y en el caso del Saldo que es numrico el valor 0.
Hay otras ocasiones en las que queremos que al construirse el objeto comience con otros
valores diferentes. En ese caso necesitaremos escribir nuestros propio constructor o
constructores, mediante un mtodo especial llamado New().
Siguiendo con nuestro ejemplo cundo coge valor la propiedades FechaEdicion y
NumCuenta? Pues este sera el sitio lgico. Fjate especialmente en el caso de la fecha de
edicin, porque la solucin para el NumCuenta an es un poco complicado
Lo que est claro es que este sera el lugar ms lgico, en el momento en que se crea.

VB.Net (Cap 6. OOP)

Pg. 99

Desarrollo de Aplicaciones Multiplataforma


Private Shared ultimaCuenta As String = "29890000000000000000" ' Para calcular
la nueva cuenta. Variable compartida. Esto lo veremos ms adelante
Public Sub New()
_NumCuenta = ultimaCuenta + 1 ' Sera un n superior a la ltima cuenta creada
_FechaEdicion = Today ' coge la fecha del sistema
End Sub

As, cuando en otra parte del programa ejecutemos una instruccin del tipo:
miCuenta = New CuentaBancaria

o bien
Private miCuenta As New CuentaBancaria

Se ejecutar este constructor dndole el valor que le corresponde a las propiedades


NumCuenta y a FechaEdicin.
Al igual que ocurre en un mtodo normal, New( ) admite parmetros; esto nos sirve
para asignar valores de inicio al objeto en el momento de su instanciacin. La denominacin
para este tipo de mtodos es constructor parametrizado. El siguiente cdigo fuente nos muestra
una variacin del fuente anterior, utilizando un par de constructores de este tipo.
Public Sub New(ByVal numCuenta As String) ' Le pasamos el n de cuenta para que
coja ese valor, la fecha de edicin ser la del sistema
_NumCuenta = numCuenta
_FechaEdicion = Today
End Sub
Public Sub New(ByVal numCuenta As String, ByVal fecEdicion As Date) ' Le pasamos
tanto el nmero de cuenta como un valor para la fecha de edicin
_NumCuenta = numCuenta
_FechaEdicion = fecEdicion
End Sub

Para conseguir que al crear un objeto utilice estos constructores deberamos hacer:
Dim oCuenta As CuentaBancaria
oCuenta = New CuentaBancaria() ' Utiliza el constructor sin parmetros, se crear
una nueva cuenta con el n que le corresponde y la fecha del sistema
oCuenta = New CuentaBancaria(txtTitular.Text) ' Utiliza el constructor con 1
parmetro, el n de cuenta ser el pasado en el parmetro
oCuenta = New CuentaBancaria(txtTitular.Text, txtCantidad.Text) ' Utiliza el 3,
creando la cuenta con estos valores para NumCuenta y FechaEdicion

Nota Si no queremos hacer nada en especial en el constructor, se puede no escribir nada,


que el propio VB genera automticamente el constructor vaco. Pero en el caso de que
escribamos un constructor con parmetros y queremos mantener el constructor vaco debemos
escribirlo explcitamente, incluso aunque no necesitemos escribir cdigo para l.
Public Sub New()
End Sub

Observacin. Como vers en el siguiente apartado, para sobrecargar un procedimiento o


funcin escribimos la palabra Overloads. Esto es as, excepto cuando lo que estamos
sobrecargando es constructor.

VB.Net (Cap 6. OOP)

Pg. 100

Desarrollo de Aplicaciones Multiplataforma

Sobrecarga de mtodos o polimorfismo, en una misma clase


La sobrecarga de mtodos, tal y como ya vimos en el tema anterior sobre procedimientos y
funciones en el apartado Sobrecarga de procedimientos, es una tcnica que consiste en crear
varios mtodos con idntico nombre dentro de la misma clase, distinguindose entre s por su
lista de parmetros.
Para declarar un mtodo como sobrecargado, debemos utilizar la palabra clave Overloads
despus del modificador de mbito. Podemos sobrecargar mtodos de tipo Sub y Function.
Supongamos que tenemos una clase Articulo que necesita manejar en diferentes formas, la
informacin referente a Pagar dependiendo de la cantidad comprada y sabiendo que hay
ocasiones en que se hace descuento sobre el precio habitual. Por tal motivo, vamos a crear tres
mtodos con el nombre Pagar( ), que variarn en su firma, o protocolo de llamada, y realizarn
diferentes tareas, pero todas ellas relacionadas con el precio a pagar.
Usaremos el concepto de Regin, para ver cmo podemos expandirla o contraerla y as tener
visible o no toda la regin. (Hay ocasiones en que es prctico contraerla). Y por supuesto,
cuando definamos una regin, lo haremos con conceptos lgicos. En el ejemplo hemos
diferenciado las Propiedades de los Mtodos.

Public Class Articulo


#Region "Propiedades" ' Generamos regiones para poder expandirla o contraerla y
ver todas las propiedades o solo
Private _Pvp As Decimal
Private _Nombre As String
Private _Stock As Integer
Public Property Pvp As Decimal
Get
Return _Pvp
End Get
Set(ByVal value As Decimal)
If value < 0 Then Throw New Exception("El Pvp no puede tener un valor <0")
_Pvp = value
End Set
End Property
Public Property Nombre As String
Get
Return _Nombre
End Get
Set(ByVal value As String)
If value <> "" Then _Nombre = value
End Set
End Property
Public Property Stock As Integer
Get
Return _Stock
End Get
Set(ByVal value As Integer)
If value < 0 Then Throw New Exception("El Stock no puede tener un valor <0")
_Stock = value
End Set
End Property
#End Region

VB.Net (Cap 6. OOP)

Pg. 101

Desarrollo de Aplicaciones Multiplataforma


#Region "Mtodos"
Public Overloads Function Pagar(ByVal cantidad As Integer, ByVal descuento As
Integer) As Decimal
' Podemos trabajar con el nombre de las propiedades Stock o de las variables
_Stock, pero suele ser ms aconsejable de la propiedad, porque as hace los
controles oportunos (los que tengamos en el Set o Get correspondiente)
If cantidad > Stock Then Throw New Exception("No hay suficiente stock")
Stock = Stock - cantidad
Dim precio As Decimal
precio = Pvp - Pvp * descuento / 100
Return precio * cantidad
End Function
Public Overloads Function Pagar(ByVal cantidad As Integer) As Decimal
Return Pagar(cantidad, 0) ' Llamamos al anterior con descuento 0 para que
tambin haga los controles oportunos
End Function
Public Overloads Function Pagar() As Decimal ' En este caso se considera 1 unidad
del artculo
Return Pagar(1) ' Llamamos a una de las formas anteriores. Puede ser Pagar(1,0)
End Function
#End Region
End Class

Vemos pues, cmo a travs de la sobrecarga conseguimos tambin polimorfismo (ver


siguiente apartado) para una clase, ya que el mismo nombre de mtodo, en funcin de los
parmetros pasados, actuar de diferente forma.
A pesar de haber indicado que la palabra clave Overloads nos permite sobrecargar los
mtodos con nombres iguales en la clase, realmente no sera necesario su uso, ya que el
compilador detecta la diferencia entre dichos mtodos a travs de su lista de parmetros. Sin
embargo se recomienda el uso de esta palabra clave por motivos de legibilidad del cdigo, de
forma que nos ayude a reconocer ms rpidamente los mtodos sobrecargados.
Cuando realmente necesitaremos emplear Overloads ser al sobrecargar un mtodo en una
clase derivada, aspecto este que se explicar en el captulo referente a la herencia.

Caractersticas bsicas de un sistema orientado a objeto


Para que un lenguaje o sistema sea considerado orientado a objeto, debe cumplir las
caractersticas de los siguientes apartados.

Abstraccin
La abstraccin es aquella caracterstica que nos permite identificar un objeto a travs de sus
aspectos conceptuales.
Las propiedades de los objetos de una misma clase, pueden hacerlos tan distintos que sea
difcil reconocer que pertenecen a una clase idntica. No obstante, nosotros reconocemos a qu
clase pertenecen, identificando adems, si se trata de la misma clase para ambos. Ello es posible
gracias a la abstraccin.
Tomemos como ejemplo dos objetos coche, uno deportivo y otro familiar; su aspecto
exterior es muy diferente, sin embargo, cuando pensamos en cualquiera de ellos, sabemos que
ambos pertenecen a la clase Coche, porque realizamos una abstraccin o identificacin mental
de los elementos comunes que ambos tienen (ruedas, volante, motor, puertas, etc.).
Del mismo modo que hacemos al identificar objetos reales, la abstraccin nos ayuda a la
hora de desarrollar una aplicacin, permitindonos identificar los objetos que van a formar parte

VB.Net (Cap 6. OOP)

Pg. 102

Desarrollo de Aplicaciones Multiplataforma

de nuestro programa, sin necesidad de disponer an de su implementacin; nos basta con


reconocer los aspectos conceptuales que cada objeto debe resolver.
Por ejemplo, cuando abordamos el desarrollo de un programa de gestin orientado a objetos,
realizamos una abstraccin de los objetos que necesitaramos para resolver los procesos del
programa: un objeto Empleado, para gestionar al personal de la empresa; un objeto Factura,
para gestionar las ventas realizadas de productos; un objeto Usuario, para verificar las personas
que utilizan la aplicacin, etc.

Encapsulacin
La encapsulacin establece la separacin entre el interfaz del objeto y su implementacin,
aportndonos dos ventajas fundamentales.
Por una parte proporciona seguridad al cdigo de la clase, evitando accesos y
modificaciones no deseadas; una clase bien encapsulada no debe permitir la modificacin
directa de una variable, ni ejecutar mtodos que sean de uso interno para la clase.
Por otro lado la encapsulacin simplifica la utilizacin de los objetos, ya que un programador
que use un objeto, si este est bien diseado y su cdigo correctamente escrito, no necesitar
conocer los detalles de su implementacin, se limitar a utilizarlo.
Tomando un ejemplo real, cuando nosotros utilizamos un objeto Coche, al presionar el
acelerador, no necesitamos conocer la mecnica interna que hace moverse al coche, sabemos
que el mtodo Acelerar del coche es lo que tenemos que utilizar para desplazarnos, y
simplemente lo usamos.
Pasando a un ejemplo en programacin, si estamos creando un programa de gestin y nos
proporcionan un objeto Cliente que tiene el mtodo Alta, y sirve para aadir nuevos clientes a
la base de datos, no precisamos conocer el cdigo que contiene dicho mtodo, simplemente lo
ejecutamos y damos de alta a los clientes en nuestra aplicacin.

Polimorfismo
El polimorfismo determina que el mismo nombre de mtodo, realizar diferentes acciones
segn el objeto sobre el que sea aplicado. Al igual que suceda en la encapsulacin, el
programador que haga uso del objeto, no necesita conocer los detalles de implementacin de los
mtodos, se limita a utilizarlos.
Pasando a un ejemplo real, tomamos dos objetos: Pelota y VasoCristal; si ejecutamos sobre
ambos el mtodo Tirar, el resultado en ambos casos ser muy diferente; mientras que el objeto
Pelota rebotar al llegar al suelo, el objeto VasoCristal se romper.
En un ejemplo aplicado a la programacin, supongamos que disponemos de los objetos
Ventana y Fichero; si ejecutamos sobre ambos el mtodo Abrir, el resultado en Ventana ser la
visualizacin de una ventana en el monitor del usuario; mientras que en el objeto Fichero, se
tomar un fichero en el equipo del usuario y se dejar listo para realizar sobre l operaciones de
lectura o escritura.

Herencia
Se trata de la caracterstica ms importante de la OOP, y establece que partiendo de una
clase a la que denominamos clase base, padre o superclase, creamos una nueva clase
denominada clase derivada, hija, o subclase. En esta clase derivada dispondremos de todo el
cdigo de la clase base, ms el nuevo cdigo propio de la clase hija, que escribamos para
extender sus funcionalidades.
A su vez podemos tomar una clase derivada, creando una nueva subclase a partir de ella, y
as sucesivamente, componiendo lo que se denomina una jerarqua de clases, que explicaremos
seguidamente.

VB.Net (Cap 6. OOP)

Pg. 103

Desarrollo de Aplicaciones Multiplataforma

Existen dos tipos de herencia: simple y mltiple. La herencia simple es aquella en la que
creamos una clase derivada a partir de una sola clase base, mientras que la herencia mltiple nos
permite crear una clase derivada a partir de varias clases base. El entorno de .NET Framework
slo permite utilizar herencia simple.
Como ejemplo real de herencia, podemos usar la clase Coche como clase base; en ella
reconocemos una serie de propiedades como Motor, Ruedas, Volante, etc., y unos mtodos
como Arrancar, Acelerar, Frenar, etc. Como clase derivada creamos CocheDeportivo, en la
cual, adems de todas las caractersticas mencionadas para la clase Coche, encontramos
propiedades y comportamiento especficos como ABS, Turbo, etc.
Un ejemplo basado en programacin consistira en disponer de la una clase Empleado. Esta
clase se ocupara de las operaciones de alta de emplead@s, pago de nminas, etc.; pero en
un momento dado, surge la necesidad de realizar pagos a emplead@s que no trabajan en la
central de la empresa, ya que se trata de comerciales que pasan la mayor parte del tiempo
desplazndose. Para realizar dichos pagos usaremos Internet, necesitando el nmero de tarjeta
de crdito y la direccin email del empleado o empleada. Resolveremos esta situacin creando
la clase derivada CiberEmpleado, que hereda de la clase Empleado, en la que slo tendramos
que aadir las nuevas propiedades y mtodos para las transacciones electrnicas, puesto que las
operaciones tradicionales ya las tendramos disponibles por el mero hecho de haber heredado de
Empleado.

Jerarquas de clases
Como decamos en un apartado anterior, uno de los fines de la OOP consiste en la
clasificacin del cdigo; para ello se emplean jerarquas o rboles de clases, en los que a base de
niveles, se muestra un conjunto de clases conectadas por una relacin de herencia. Observemos
el esquema de la siguiente figura, en el que se muestra un ejemplo de la jerarqua de clases de
medios de transporte.

Jerarqua de clases de medios de transporte.

En esta representacin de ejemplo, como nivel superior de la jerarqua o clase base estara
Medios de transporte, de la que se derivaran las clases Barco, Tren, Automvil, y a su vez, de
estas ltimas, partiran nuevas clases hijas.

VB.Net (Cap 6. OOP)

Pg. 104

Desarrollo de Aplicaciones Multiplataforma

Atencin: En el caso de VB.Net tenemos ya una jerarqua predefinida, por la cual


cualquier clase que declaremos hereda de una clase primaria llamada Object que tiene los
mtodos ya visto en numerosas ocasiones Equals, GetHashCode, GetType, ReferenceEquals y
ToString que en su momento podremos sobrecargar o sobreescribir, pero esto son conceptos an
no explicados.

Relaciones entre objetos


Los objetos existentes en una aplicacin se comunican entre s mediante una serie de
relaciones que describimos a continuacin.

Herencia
Como acabamos de describir en el apartado sobre caractersticas de la OOP, cuando a partir
de una clase existente, creamos una nueva clase derivada, esta nueva clase dispone de todas las
propiedades y mtodos de la clase base, ms el cdigo propio que implemente. Para reconocer si
existe esta relacin entre dos objetos, debemos realizar un anlisis sintctico sobre la misma
usando la partcula es un.
Tomando como ejemplo los objetos Empleado, CiberEmpleado y Factura, podemos decir
que s hay una relacin de herencia entre Empleado y CiberEmpleado, ya que al analizar la
frase Un objeto CiberEmpleado es un Empleado, el resultado es verdadero. No ocurre lo
mismo entre los objetos CiberEmpleado y Factura, ya que el anlisis de la frase Un objeto
CiberEmpleado es una Factura, devuelve falso.

Pertenencia
Los objetos pueden estar formados a su vez por otros objetos. Un objeto Factura puede estar
compuesto por objetos CabeceraFactura, LineaFactura, etc. Se dice en este caso que hay una
relacin de pertenencia, puesto que existe un conjunto de objetos que pertenecen a otro objeto o
se unen para formar otro objeto. A este tipo de relacin se le denomina tambin Contenedora.
Para reconocer si existe esta relacin entre dos objetos, debemos realizar un anlisis
sintctico sobre la misma usando la partcula tiene un. As, por ejemplo, la frase Un objeto
Factura tiene un objeto LineaFactura devolvera verdadero.

Utilizacin
Hay situaciones en que un objeto utiliza a otro para realizar una determinada tarea, sin
que ello suponga la existencia de una relacin de pertenencia entre dichos objetos.
Por ejemplo, un objeto Ventana puede utilizar un objeto Empleado para mostrar al usuario
las propiedades del empleado, sin necesidad de que el objeto Empleado sea propiedad del objeto
Ventana.
Ntese la importante diferencia entre esta relacin y la anterior, ya que aqu, el objeto
Ventana a travs de cdigo, crear, o le ser pasado como parmetro, un objeto Empleado, para
poder mostrarlo en el rea de la ventana.
Para reconocer si existe esta relacin entre dos objetos, debemos realizar un anlisis
sintctico sobre la misma empleando la partcula usa un. As, por ejemplo, la frase Un objeto
Ventana usa un objeto Empleado devolvera verdadero.

Reutilizacin
Un objeto bien diseado, puede ser reutilizado en otra aplicacin de modo directo o creando
una clase derivada a partir de l. Este es uno de los objetivos perseguidos por la OOP,
aprovechar en lo posible el cdigo ya escrito, ahorrando un considerable tiempo en el desarrollo
de programas.
VB.Net (Cap 6. OOP)

Pg. 105

Desarrollo de Aplicaciones Multiplataforma

Cap 7. Arrays y Colecciones


Arrays o Matrices
Tambin conocido con las denominaciones de matriz, tabla y vector, un array es aquel
elemento del lenguaje que nos permite agrupar un conjunto de valores del mismo tipo, y
acceder a ellos a travs de una misma variable o identificador, especificando la posicin o
ndice en donde se encuentra el dato a recuperar.
Todos los elementos de un array tienen el mismo tipo de datos. Se puede declarar un array de
cualquiera de los tipos de datos fundamentales, incluyendo los tipos definidos por el usuario

Declaracin
En VB.Net la declaracin de un array la haremos usando un par de parntesis en el nombre
de la variable o del tipo, en el siguiente ejemplo declaramos un array de tipo String llamado
nombres:
Estas dos formas son equivalentes.
Dim nombres() As String
Dim nombres As String()

Tambin podemos indicar el nmero de elementos que contendr el array:


Dim nombres(10) As String

Nota. El nmero de elementos solo podemos definirlo en el nombre, si esa cantidad de


elementos lo indicamos en el tipo, recibiremos el error "los lmites de la matriz no pueden
aparecer en los especificadores del tipo".

Al declarar un array indicando el nmero de elementos, como es el caso anterior, lo que


estamos definiendo es un array de 11 elementos: desde 0 hasta 10, ya que en VB.Net, al igual
que en el resto de lenguajes de .NET, todos los arrays tienen como ndice inferior el valor 0.
Para que quede claro que el lmite inferior debe ser 0, en VB.Net podemos usar la
instruccin 0 To para indicar el valor mximo del ndice superior, ya que, tal como podemos
comprobar si vemos 0 To 10, quedar claro que nuestra intencin es declarar un array con 11
elementos, o al menos nuestro cdigo resultar ms legible:
Private nombres(0 To 10) As String

Nota: En los apartados posteriores vers que un array tambin se puede definir de la clase
Array y crear una instancia como se ve en la siguiente instruccin:
Private nombres As Array= Array.CreateInstance(GetType(String), 11) ' Lo declara y
luego lo instancia con CreateInstance. No se puede poner New Array porque la
clase Array no lo permite

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 107

Desarrollo de Aplicaciones Multiplataforma

Asignar y recuperar el valor a/de un elemento del array


Para acceder a los elementos de un array se escribir el nombre del array y entre parntesis el
ndice, o nmero que indica la posicin del elemento en el array. Ejemplo nmeros(0) indica
que es el primer elemento del array nmeros.
Una vez accedido a un elemento del array, lo usaremos como si de otra variable simple se
tratase.
numeros(0) = 3 ' Asigna un 3 al primer elemento del array numeros
Dim num As Integer = numeros(2) ' Asigna a una variable el valor que hay en la 3
posicin del array
numeros(1) = numeros(1) * 3 '
numeros(1) += 10 ' Suma 10 al valor del 2 elemento del array
For i As Integer = 0 To TOTNUMS 1 ' Suponiendo que TOTNUMS es una constante
numeros(i) = 10 ' Indica mediante una variable entera la posicin en el array
Next

Averiguar los elementos de un array


Para saber el nmero de elementos de un array tenemos la propiedad
devuelve la cantidad de elementos del array.

Length,

que nos

Por tanto, si queremos usar esta propiedad para acceder a todos los elementos, debemos tener
en cuenta que el ndice inferior es el 0, por lo que si usamos un bucle para recorrerlo, debemos
hacerlo desde la posicin 0 a 1 menos de la longitud, en la forma:
For i As Integer = 0 To numeros.Length - 1 ' As recorre todos los elementos
lstNum.Items.Add(numeros(i))
Next

Igualmente podemos uar el mtodo GetUpperBound(dimensin)


For i As Integer = 0 To numeros.GetUpperBound(0) 'Devuelve el ltimo elemento del
array. El 0 es para indicar la dimensin

La razn de que indiquemos un 0 como argumento del mtodo GetUpperBound la


explicaremos ms adelante, pero si ya sabes que es un array de varias dimensiones, decir que el
0 indica que es la dimensin 0, que es la nica dimensin de los arrays que estamos viendo por
el momento.
Cuidado!. Hay ocasiones en que el array puede ser Nothing, en cuyo caso no podremos
usar ninguna de sus propiedades o mtodos, como en el siguiente ejemplo:
Dim num() As Integer ' El array no tiene dimensin, vale Nothing
For i As Integer = 0 To num.Length - 1 ' Se rompe porque numeros no existe

Si se puede dar esa posibilidad antes deberamos hacer algo semejante a:


If numeros Is Nothing Then Exit Sub ' Salir del subprograma porque no existe
If numeros IsNot Nothing Then ' Si no es Nothing
For i As Integer = 0 To num.Length 1 ' Aunque no tenga elementos ya no se
rompe

Inicializar el array al declararlo


En VB.Net podemos inicializar un array al declararlo. Para ello debemos poner los valores a
asignar dentro de un par de llaves, tal como vemos en el siguiente ejemplo:
Public Paises() As String = {"GUATEMALA", "IRLANDA", "PORTUGAL", "ANGOLA"} ' El
array comienza con 4 elementos (0..3) con esos valores

Con el cdigo anterior estamos creando un array de tipo String con 4 valores cuyos ndices
van de 0 a 3.

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 108

Desarrollo de Aplicaciones Multiplataforma

En este caso, cuando iniciamos el array al declararlo, no podemos indicar el nmero de


elementos que tendr ese array, ya que ese valor lo averiguar el compilador cuando haga la
asignacin. Tampoco es vlido indicar el nmero de elementos que queremos que tenga y solo
asignarle unos cuantos menos (o ms), ya que se producir un error en tiempo de compilacin.
Si el array es bidimensional (o con ms dimensiones), tambin podemos inicializarlos al
declararlo, pero en este caso debemos usar doble juego de llaves:
Dim Cursos(,) As String = {{"1DAM", "2DAM"}, {"1ASIR", "2ASIR"}}

En este cdigo tendramos un array bidimensional con los siguientes valores:


Cursos(0, 0) = "1DAM", Cursos(0, 1) = "2DAM", Cursos(1, 0) = "1ASIR" y
Cursos(1, 1) = "2ASIR"

Como podemos ver en la declaracin anterior, si definimos arrays con ms de una


dimensin, debemos indicarlas usando una coma para separar cada dimensin. En los valores a
asignar, usaremos las llaves encerradas en otras llaves, segn el nmero de dimensiones.
Tambin podemos inicializar el array a valores por defecto. En este caso pondremos las
llaves vacas.
Atencin. Observa que es diferente declarar un array con las {} a sin ellas
Dim numeros() As Integer ' El array no tiene dimensin, vale Nothing
Dim numeros() As Integer = {} ' El array tiene longitud 0

Para ver las diferencias, crea un formulario con un botn y una lista (lstNum) y copia el
siguiente cdigo:
Dim num0(9) As Integer ' Array de 10 elementos, con valor 0 en cada uno
Dim numNothing() As Integer ' El array no tiene dimensin, vale Nothing
Dim numVacio() As Integer = {} ' El array existe aunque vaco. Tiene longitud 0
MessageBox.Show("num0")
lstNum.Items.Clear()
For i As Integer = 0 To num0.Length - 1 ' Escribe 9 ceros
lstNum.Items.Add(num0(i))
Next
MessageBox.Show("numVacio")
lstNum.Items.Clear()
For i As Integer = 0 To numVacio.Length - 1 ' No escribe nada, porque
numVacio.Length vale 0
lstNum.Items.Add(numVacio(i))
Next
MessageBox.Show("numNothing")
lstNum.Items.Clear()
For i As Integer = 0 To numNothing.Length - 1 ' Se rompe, porque numNothing no
existe, es Nothing y no se puede aplicar ningn mtodo o propiedad
lstNum.Items.Add(numNothing(i))
Next

Nota: Igualmente podemos dar valores a un array definindolo de la clase Array en la


forma: Dim palabras As Array = {"hola", "adios", "vale", "si"}' Crea el array y
define el tipo ms acorde con los valores pasados

Cambiar el tamao: ReDim


Para cambiar el tamao de un array, usaremos la instruccin ReDim.
Esta instruccin solo la podemos usar para cambiar el tamao de un array previamente
declarado, no para declararlo la primera vez.
Dim Nombres(10) As String ' Comienza con un tamao de 11 elementos (de 0 a 10)

ReDim Nombres(20) ' A partir de este momento tendr 21 elementos

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 109

Desarrollo de Aplicaciones Multiplataforma

Cambiar el tamao conservando sus valores


Podemos cambiar el tamao de un array y mantener los valores que tuviera anteriormente,
gracias a la partcula Preserve de la instruccin Redim.
Public Paises() As String = {"GUATEMALA", "IRLANDA"} ' El array comienza con 2
elementos (0 y 1) con esos valores
Private Sub frmPersonas_Load(ByVal sender As ) Handles MyBase.Load
' Modificamos el tamao de los arrays con Redim. Esta instruccin SIEMPRE debe
estar en un procedimiento (funcin, property, ...)
' Redim Preserve: De los datos anteriores mantiene los que tuviese
ReDim Preserve Paises(3) ' Ahora tendr 4 elementos (de 0 a 3).
Paises(2) = "PORTUGAL"
Paises(3) = "ANGOLA"
End Sub

As podremos redefinir un array en funcin de lo que vaya ocurriendo en tiempo de


ejecucin, como puedes apreciar en el siguiente ejemplo:
Private Ciudades() As String ' En este caso no le hemos indicado el tamao. Si se
intenta usar sin redimensionar dara error (el array an est a Nothing)
Private Sub btnRedim_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnRedim.Click
Dim TotCiudades As Integer = txtNumCiu.Text
ReDim Ciudades(TotCiudades - 1) ' Se redimensiona dependiendo del valor de la
caja de texto. Se reinicia a blanco todo el array perdiendo los datos que
tuviese
End Sub

Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de cualquier nmero de
dimensiones, en los arrays de ms de una dimensin solamente podemos cambiar el tamao de
la ltima dimensin.
Nota: En el apartado de la clase Array vers que tambin podemos redefinir el tamao del
array mediante el mtodo Resize.

Eliminar su contenido
Una vez que hemos declarado un array y le hemos asignado valores, es posible que nos
interese eliminarlos de nuevo.Para lograrlo, podemos hacerlo de dos formas:
Como con cualquier objeto, podemos asignar un valor Nothing al array.
Usar la instruccin Erase que elimina totalmente el array de la memoria.
Si seguimos con el ejemplo del prrafo anterior, las dos instrucciones siguientes son
equivalentes.
numVacio = Nothing ' Antes tena longitud 0, pero exista. Ahora se queda a
Nothing, no existe.
Erase num0 ' Antes tena 10 elementos, ahora se queda a Nothing

Cuidado!. No se puede usar Redim para eliminar el array, ni poniendo un 0 entre


parntesis (ya que se quedara con un elemento, el 0esimo), ni dejando el parntesis vaco,
porque no lo admite la instruccin, como se puede observar en la siguiente figura:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 110

Desarrollo de Aplicaciones Multiplataforma

Nota: Como en los casos anteriores, tenemos el mtodo


adems nos permitir dejar el array sin elementos pero creado.

Resize de la

clase Array que

Inicializar los valores de sus elementos


Bastara con redimensionarlo a la misma u otra longitud, pero sin la clusula Preserve.
Ejemplo:
ReDim numeros(9)

' El array se redimensiona con 10 elementos a 0

Nota: Tambin podemos usar el mtodo Clear de la clase array:


Array.Clear(numeros, 0, numeros.Length) ' Limpia el array completo, desde la
posicin 0 tantos elementos como tiene

Copiar un array en otro


En VB.Net los arrays son tipos por referencia, y como tal, los tipos por referencia realmente
lo que contienen es una referencia a los datos reales no los datos propiamente dichos.
Cual es el problema? Vemoslo con un ejemplo y as lo tendremos ms claro:
Dim Ciclos() As String = {"DAM", "ASIR", "AF", "GCM"}
Dim Otros() As String
Otros = Ciclos ' Hace una copia por referencia, ambos apuntan a los mismos valores
Ciclos(0) = "Dam o Daw"
MessageBox.Show(Otros(0 )) ' Vale "Dam o Daw"

Qu ha ocurrido? Pues que como los arrays son tipos por referencia, solamente existe una
copia de los datos por lo que ambas variables, Ciclos y Otros, contienen una referencia (o
puntero) a los mismos datos.
Si realmente queremos tener copias independientes, debemos hacer una copia del array
Ciclos en el array Otros, esto es fcil de hacer si usamos el mtodo CopyTo. ste mtodo
existe en todos los arrays y nos permite copiar un array en otro empezando por el ndice que
indiquemos.
El nico requisito es que el array de destino debe estar inicializado y tener espacio suficiente
para contener los elementos que queremos copiar.
Tambin podemos utilizar el mtodo
pero de todo el array.

Clone

que devuelve una copia al estilo de CopyTo

Ciclos2 = Ciclos.Clone

En el siguiente cdigo de ejemplo hacemos una copia del contenido del array Cursos en el
array Otros, de esta forma, el cambio realizado en el elemento 0 de Cursos no afecta al del array
Otros.
Dim Ciclos() As String = {"DAM", "ASIR", "AF", "GCM"}
Dim Otros(3) As String ' Tiene que tener un tamao como mnimo de 4 elementos (que
son los que vamos a intentar copiar en este ejemplo)
Ciclos.CopyTo(Otros, 0)
Ciclos(0) = "Dam o Daw"
MessageBox.Show("Ciclos(0) = " & Ciclos(0) & ControlChars.CrLf & "Otros(0) = " &
Otros(0)) ' Ciclos (0) es "Dam o Daw" pero Otros(0) sigue valiendo "DAM"

Cuidado! Si el array que va a recibir la copia no est dimensionado o es menor que lo que
se intenta copiar, se produce un error de ejecucin, como puedes apreciar en la siguiente figura:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 111

Desarrollo de Aplicaciones Multiplataforma

Crear un array al vuelo


Hay ocasiones en que tenemos mtodos, subprogramas o funciones que esperan un array en
alguno de sus argumentos. En estos casos podemos hacer dos cosas:
Crear previamente el array y despus pasarlo como argumento.
Function Suma(ByRef numeros() As Integer) As Integer
Dim s As Integer = 0
For i As Integer = 0 To numeros.Length - 1
s += numeros(i)
Next
Return s
End Function

La llamada podramos hacerla en la forma:


Dim valores() As Integer = {10, 20, 30}
Dim miSuma As Integer = Suma(valores)

Crear directamente el array al llamar al mtodo. Esta ser especialmente til en los
casos en que solo lo necesitemos para esa llamada.
Dim valores() As Integer = {10, 20, 30}
Dim miSuma As Integer = Suma(New Integer() {10, 20, 30})' Crea el array
directamente en la llamada

Otros mtodos interesantes de arrays


Adems del mtodo CopyTo, los arrays tienen otros miembros que nos pueden ser de
utilidad:
Dim Ciclos() As String = {"DAM", "ASIR", "AF", "GCM"}

Length usada

en los ejemplos anteriores, para saber cuantos elementos tiennoe un

array
MessageBox.Show("Longitud = " & Ciclos.Length) ' Indicar que tiene 4

El mtodo Contains para saber si un elemento est contenido o no en el array.


Devuelve un valor True en el caso de que lo encuentre y False en caso contrario. Si
queremos conocer la posicin deberemos utilizar los mtodos IndexOf o
LastIndexOf de la clase Array, que puedes ver en el siguiente apartado.
Dim ciclo As String = txt.Text.ToUpper ' ciclo recibe el dato de la caja
de texto pero en maysculas para que los mtodos puedan encontrala
If Ciclos IsNot Nothing AndAlso Ciclos.Contains(ciclo) Then ' Si el array
existe y contiene ese elemento
MessageBox.Show("Ya existe en la posicin " & Array.IndexOf(Ciclos,
ciclo)
End If

Cuidado! Si el array es String, solo encuentra si el string a buscar est


exactamente igual escrito, por eso es prctico definir el array con los valores en

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 112

Desarrollo de Aplicaciones Multiplataforma

maysculas y luego preguntar por el dato tambin en maysculas como en el ejemplo


de arriba.

Max y Min que devuelven el valor mximo y mnimo respectivamente.


lbl.Text = Ciclos.Min ' Escribe AF por ser alfabticamente el menor
lbl.Text = Ciclos.Max ' Escribe GCM que es el mayor

First

y Last devuelven el primer y ltimo elemento respectivamente. Si el array


tiene longitud 0 daran error de ejecucin. Tambin existen FirstOrDefault y
LastOrDefault semejantes a las anteriores pero si el array est vaco (sin
elementos pero existiendo) devuelve el valor por defecto del tipo correspondiente (es
decir, si el array es de string la cadena vaca, 0 para los numricos, ).
MessageBox.Show(Ciclos.FirstOrDefault) ' ' Muestra "DAM" si existe o
blanco si el array est vaco

Tambin podemos recuperar o modificar el valor de un elemento mediante los


mtodos GetValue o SetValue respectivamente.
cursos.SetValue("2DAM", 1) ' Equivale a cursos(1) = "2DAM"
lbl.Text = cursos.GetValue(1) ' Equivale a lbl.Text = cursos(1)

Atencin! Recuerda que si el array est a Nothing (por definicin vaca o tras eliminarlo)
no podemos aplicarle ningn miembro al array (propiedad o mtodo), como si de otro objeto se
tratase:
Dim Ciclos() As String
Sub Ejemplo
If Ciclos.Contains("DAM") Then ' Si el array no existe
MessageBox.Show("Ya existe")
End If
End Sub

SE ROMPE!!!

Deberamos controlar primero que realmente existe. Una posible forma es:
Sub Ejemplo
If Ciclos IsNot Nothing AndAlso Ciclos.Contains("DAM") Then ' Si el array
existe y no contiene ese elemento
MessageBox.Show("Ya existe")
End If
End Sub

Clase Array
Para finalizar este tema, solo nos queda por decir, que los arrays de VB.Net realmente son
tipos de datos derivados de la clase Array y por tanto disponen de todos los miembros
definidos en esa clase, como ya hemos ido comentando en el punto anterior.
Atencin Como podrs observar cuando estamos accediendo a un array nos aparecen
mtodos que luego nos dan error de escritura, por ejemplo, si empiezas a escribir
Ciclos.Clear( comprobars que te pide un array y si escribes Ciclos.Clear(Ciclos,2,3) el
IDE te mostrar el error con esta posible solucin (ya que en realidad Clear es un mtodo
compartido de la clase)

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 113

Desarrollo de Aplicaciones Multiplataforma

As que veamos algunos de estos mtodos:


Los mtodos IndexOf o LastIndexOf para saber si un elemento est contenido y
en que posicin empezando por la izquierda (IndexOf) o por la derecha (LastIndexOf).
Si el elemento no se encuentra devuelven -1.
Dim Palabras() As String = {"HOLA", "ADIOS", "PERSONA", "ADIOS", "HOLA",
"ADIOS"}
Dim palabra As String = txt.Text.ToUpper ' palabra recibe el dato de la
caja de texto pero en maysculas para que los mtodos puedan encontrala
If Array.IndexOf(Palabras, palabra.ToUpper) = -1 Then ' -1 indica que no
existe, podramos haber usado If Palabras.Contains(palabra) Then
MessageBox.Show("No existe")
ElseIf Array.IndexOf(Palabras, palabra) = Array.LastIndexOf(Palabras,
palabra) Then
MessageBox.Show("Existe una y sola una vez")
Else
MessageBox.Show("La primera ocurrencia es " &
Array.IndexOf(Palabras, palabra) & " y la ltima " &
Array.LastIndexOf(Palabras, palabra))
End If

Notas
En el caso de que solo haya una sola aparicin IndexOf y LastIndexOf daran el
mismo valor (ya que sera el nico a encontrar), por lo que esto nos sirve para saber si
es nico.
LastIndexOf da la posicin por la derecha pero contando desde la izquierda, es decir,
en el ejemplo anterior si la palabra fuese ADIOS indica 5.

Clear inicializa los elementos del array que le indiquemos por parmetro,

es decir,
les devuelve los valores por defecto: 0 si es numrico, False en el caso de ser boolean,
para los String,
Array.Clear(Ciclos, 1, 2) ' Deja en blanco las posiciones 1 y 2
Array.Clear(Ciclos, 0, Ciclos.Length) ' Limpia el array completo, desde
la posicin 0 tantos elementos como tiene

Para copiar un array en otro y que no hagan referencia a la misma direccin de


memoria, hemos comentado que debemos usar el mtodo CopyTo de los arrays. El
mtodo Copy de la clase Array es semejante pero da ms posibilidades, permitiendo
copiar de un array en otro desde cualquier elemento en cualquier posicin del destino
y tantos elementos como deseemos.
Array.Copy(numeros, otros, 0) ' Copia el array numeros en el array otros
a partir del primer elemento

Ejemplo: Supongamos que nmeros es el siguiente array:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 114

Desarrollo de Aplicaciones Multiplataforma


Array.Copy(numeros, 2, otros, 4, 3) ' Copia los 3 elementos de nmeros
que empiezan desde el de posicin 2, en el array otros a partir de la
posicin 4
4
0

54
1

34
2

121
3

343
4

2
5

0
1

0
2

0
3

0
4

0
5

0
6

0
7

0
2

0
3

34
4

121
5

343
6

0
7

Y otros el siguiente
0
0

Tras la ltima Copy quedara


0
0

0
1

Resize: Es semejante a la instruccin ReDim Preserve, sirve para redimensionar el


array, mantiendo los datos que tena y permitiendo redimensionarlo a un array de
longitud 0.
Array.Resize(numeros, 0) ' El ltimo nmero se refiere a la longitud no
al ndice, por tanto decimos que lo redimensione a 0 elementos

Observa: Una gran ventaja de este mtodo es que podemos dejarlo sin
elementos sin necesidad de eliminar el array.
Si queremos limpiar un array, es decir, poner sus elementos a 0, o False
dependiendo del tipo del array, usaremos el mtodo Clear en la forma:
Array.Clear(numeros, 2, 4) ) ' Pone a los 0 nmeros que hay desde la
posicin 2

Para ordenar un array tenemos el mtodo Sort.


Dim pal() As String = {"Persona", "1DAM", "adios", "Hola", "Adios"}
Array.Sort(pal) ' El array queda ordenado en la siguiente forma: "1DAM",
"adios", "Adios","Hola" y "Persona"

Para invertir el contenido de un array usaremos el mtodo Reverse.


Dim pal() As String = {"Persona", "1DAM", "adios", "Hola", "Adios"}
Array.Reverse(pal) ' El array queda con los elementos "al revs", "Adios"
ser el primero y "Persona" el ltimo

Si consideramos la clase Array para definir e instanciar una variable lo haramos


mediante el mtodo CreateInstance en forma:
Dim cursos As Array
cursos= Array.CreateInstance(GetType(String), 2) ' Crea una instancia de
cursos, de tipo String y de tamao 2 de forma semejante a Dim cursos(1)
As String

Atencin Observa que no hemos puesto cursos = New Array ya que la clase
Array no lo permite por estar declarada como MustInherit, es decir, que no permite
crear un objeto directamente a partir de ella.
Buscar elementos en un array: Para eso tenemos los mtodos Find y
Estos son ms difciles de implementar. Veamos esto con un ejemplo:

FindAll.

Supongamos que tenemos definida la clase Localidad en la forma

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 115

Desarrollo de Aplicaciones Multiplataforma


Public Class Localidad
Public Property Nombre As String
Public Property NumHabitantes As Integer ' Lgicamente definiramos
el Get y Set para que este controle que no es un n negativo
Public Sub New(ByVal nombre As String)
Me.Nombre = nombre
End Sub
Public Sub New(ByVal nombre As String, ByVal numHabitantes As
Integer)
Me.New(nombre)
Me.NumHabitantes = numHabitantes
End Sub
End Class

Y la siguiente funcin, que devuelve un valor True si la localidad pasada como


parmetro comienza por B o no.
Private Function ComienzaPorB(ByVal loc As Localidad) As Boolean
Return loc.Nombre.StartsWith("B") ' Devuelve True cuando comienza por
B, False el resto de las palabras
End Function

El siguiente cdigo devolvera un array con las localidades de Burlada y Baraain:


Dim loc() As Localidad = {New Localidad("Pamplona", 300000), New
Localidad("Burlada"), New Localidad("Baraain"), New Localidad("Tudela")}
Dim locPorB() As Localidad = Array.FindAll(loc, AddressOf ComienzaPorB)

Atencin! Si definimos un array con la clase Array hay mtodos que no existe, como por
ejemplo Contains
Dim palabras() As String = {"hola", "adios", "vale", "si"}
Dim palabrasArr As Array = {"hola", "adios", "vale", "si"}
If palabras.Contains("adios") Then' Estara bien
If palabrasArr.Contains("adios") Then ' No tiene este mtodo

Mtodos que crean arrays


El mtodo ToCharArray de la clase String permite crear un array de Char a partir de un
String en la forma:
Dim palabra As String = "Hola"
Dim caracteres() As Char = palabra.ToCharArray

Aunque realmente este mtodo no lo necesitemos especialmente, ya que tambin podemos


acceer a los distintos caracteres de un array mediante la propiedad Chars o SubString.
Dim car As Char = palabra.Chars(0)
car = palabra(1) ' Si no indicamos nada, es como poner la propiedad Chars
car = palabra.Substring(1, 1)

Igualmente la clase String incluye el mtodo Split que nos permite crear un array a partir de
una cadena. Este mtodo trocea una cadena en elementos de un array usando un separador.
Dim frase As String = "Hola*alumn@*de*1DAM"
Dim pal() As String = frase.Split("*") ' Crea un array de 4 elementos: Hola,
alumn@, de y 1DAM
Dim frase As String = "Hola 1DAM"
Dim palabras() As String = frase.Split(" ") ' Devuelve un array con 2 elementos:
Hola y 1DAM, usando el espacio en blanco como separador

Si el separador no se encuentra en el string, devuelve un elemento con toda la cadena:


Dim frase As String = "Hola 1DAM"

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 116

Desarrollo de Aplicaciones Multiplataforma


Dim palabras() As String = frase.Split("&") ' Devuelve un array con 1 elemento
que contiene toda la frase, ya que el carcter & no se encuentra en la cadena

Crear una cadena a partir de un array


Tambin podemos efectuar la conversin inversa gracias al mtodo Join, es decir, convertir
un array de tipo String en una cadena en la que cada elemento del array se asignar separndolo
con el carcter o la cadena que indiquemos.
Dim pal() As String = {"Hola", "1DAM"}
Dim frase As String = String.Join(" ", pal) ' frase = "Hola 1DAM"
rase = String.Join("&&&", pal) 'frase = "Hola&&&1DAM"

Arrays de objetos
Lgicamente tambin podemos definir arrays con objetos de clase. Para las siguientes
explicaciones vamos a utilizar la clase Localidad definida anteriormente:

Declaracin e inicializacin de un array de objetos


Desde el punto de vista de array clsico sera:
Dim ciudadesTam(9) As Localidad ' Definimos un array de 10 elementos.
Inicialmente no tenemos referencia a ninguno, es decir, los elementos tiene el
valor de Nothing
Dim ciudadesSin() As Localidad ' En este caso el array es Nothing
Dim ciudadesCon() As Localidad = {New Localidad("Pamplona", 300000), New
Localidad("Burlada", 80000)} ' Tenemos un array con 2 localidades ya creadas

Si lo definimos como objeto de la clase Array:


Dim ciudadesTam As Array = Array.CreateInstance(GetType(Localidad), 9) '
Definimos un array de 10 elementos. Inicialmente no tenemos referencia a ninguno,
es decir, los elementos tiene el valor de Nothing
Dim ciudadesSin As Array = Array.CreateInstance(GetType(Localidad), 0) ' En este
caso el array no es Nothing, sino que ya existe pero con 0 elementos
Dim ciudadesCon As Array = {New Localidad("Pamplona", 300000), New
Localidad("Burlada", 80000)} ' Tenemos un array con 2 localidades existentes

Miembros que son arrays (Propiedades o Mtodos)


Supongamos ahora que definimos una segunda clase Autobus, con las siguientes
propiedades.
Public Class Autobus
Public Property NLinea As Integer
Public Property Origen As String
Public Property Destino As String
End Class

Cmo conseguimos que Localidad tenga una propiedad LineasAutobuses que sea un array
de objetos de esta clase?
Podemos definir una variable como los ejemplos anteriores, con cualquiera de estas formas:
Private _LineaAutobuses() As Autobus = {} ' Si queremos que el Array no sea
Nothing
Private _LineaAutobuses As Autobus() = {} ' Recuerda que tambin podamos poner
el () en el tipo
Private _LineaAutobuses As Array = Array.CreateInstance(GetType(Autobus), 0) '
Inicialmente no tenemos ninguno, pero si existe el array

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 117

Desarrollo de Aplicaciones Multiplataforma

Pero, cmo definimos la propiedad? Pues en este caso tendremos que indicarle que es array
en el tipo, en la forma:
Public Property LineasAutobuses As Autobus() ' Observa que aqu el () va en el
tipo obligatoriamente
Get
Return _LineaAutobuses
End Get
Set(ByVal value As Autobus()) ' Aqu lo pone as por defecto,pero podemos
cambiarle a Byval value() As Autobus
_LineaAutobuses = value
End Set
End Property

Y si lo que queremos es buscar una localidad en el array de localidades? Podemos usar los
mtodos Contains, IndexOf, comentados anteriormente? S, pero con cuidado.
Nota: Debes tener en cuenta que estos mtodos (a nivel interno) necesitan hacer un
recorrido del array y buscar entre sus elementos si existe alguno igual al recibido por el
parmetro. Pero, Cundo se consideran iguales dos objetos? En principio, y a no ser que se le
indique lo contrario, dos variables se consideran iguales iguales solo cuando apuntan al mismo
objeto (as lo indica el mtodo v). Si queremos hacer otra consideracin deberemos modificar
este mtodo.
Supongamos que hemos definido el array:
Private localidades() As Localidad = {}

Y la siguiente funcin:
Public Sub Aadir(ByVal loc As Localidad)
If localidades.Contains(loc) Then Exit Sub ' No la aade si ya lo tiene,
entiende que est contenida si hay alguna igual (por Equals) a loc
Array.Resize(localidades, localidades.Count + 1)
localidades(localidades.Count - 1) = loc
End Sub

Observa las siguientes instrucciones:


Dim loc As New Localidad("Artaza", 250)
Aadir(loc) ' La aade porque no existe
' Con el mismo objeto apuntado por la misma variable loc
Aadir(loc) ' No la aade porque ya existe
' Ahora creamos otra con datos idnticos, pero siendo un nuevo objeto (aunque la
crease como loc de nuevo, ocurrira lo mismo)
Dim loc2 As New Localidad("Artaza", 250)
Loc2 = New Localidad("Artaza", 250) '
Aadir(loc2) ' S la aade, ya que ahora es aparentemente igual, pero en realidad
son dos objetos diferentes y por tanto Contains devuelve False

Para solucionar esto tenemos dos posibilidades: Una primera


funciones creadas por nosotr@s mism@s.

simularlos

con

No utilizar ninguno de los mtodos Contains, IndexOf, LastIndexOf e inventarnos una


funcin equivalente, por ejemplo:
Function Existe(ByVal loc As Localidad) As Boolean ' Simular el Contains
If localidades Is Nothing Then Return False ' Si no hay ninguna, no
existir
For i As Integer = 0 To localidades.Length - 1
If loc.Nombre.ToUpper = localidades(i).Nombre.ToUpper Then Return
True ' Ha encontrado una localidad con ese mismo nombre. ToUpper para que
no importe como est escrito

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 118

Desarrollo de Aplicaciones Multiplataforma


Next
Return False
End Function
Function posLocalidad(ByVal loc As Localidad) As Boolean ' Simular el
IndexOf
If localidades Is Nothing Then Return False ' Si no hay ninguna, no
existir
For i As Integer = 0 To localidades.Length - 1
If loc.Nombre = localidades(i).Nombre Then Return i ' Posicin en que
lo encuentra
Next
Return -1 ' -1 si no encuentra
End Function

Debiendo modificar el mtodo Aadir para que quedase:


Public Sub Aadir(ByVal loc As Localidad)
If Existe(loc) Then Exit Sub ' En lugar del Contains del array usar mi
propia funcin
Array.Resize(localidades, localidades.Count + 1)
localidades(localidades.Count - 1) = loc
End Sub

Sobreescribir y/o sobrecargar los mtodos Equals. Esto lo veremos ms adelante,


pero te adelanto aqu la solucin, porque esto redefinira a nivel interno los mtodos
Contains, IndexOf y LastIndexOf, ya que ahora va a considerar dos elementos iguales
si coinciden simplemente en el nombre. En este caso deberemos implementar el
mtodo IEQualtable(Of T).Equals. Si ejecutas las instrucciones anteriores, veras que
ahora no aade loc2 ya que considera que ya existe.
Public Class Localidad: Implements IEquatable(Of Localidad) ' Debemos
implementar esta interfaz, y el mtodo Equals de instancia
Public Overloads Function Equals(ByVal loc As Localidad) As Boolean

Implements IEquatable(Of Localidad).Equals


Return Equals(Me, loc) ' LLama al compartido. Conseguimos que loc se
considere igual al objeto de la clase, cuando tienen el mismo nombre
End Function
Public Overloads Shared Function Equals(ByVal loc1 As Localidad, ByVal
loc2 As Localidad) As Boolean ' El mtodo compartido
Return loc1.Nombre.ToUpper = loc2.Nombre.ToUpper ' Considera dos
localidades iguales cuando tienen el mismo nombre
End Function

Hay otras ocasiones en que puede haber ms de un elemento que cumpla la condicin. En
este caso deberamos devolver todos los elementos o ninguno caso de que no haya.
En este tercer ejemplo vamos a obtener las ciudades que tienen ese nombre. Si no hay
ninguna devuelve un array de longitud 0 (podramos devolver Nothing).
Public Function CiudadesDeNombre(ByVal nombre As String) As Localidad()
Dim c() As Localidad = {}
Dim tc As Integer
If ciudades Is Nothing Then Return c ' o Return Nothing si as se desea
For i As Integer = 0 To ciudades.Length - 1
If ciudades(i).Nombre.ToUpper = nombre.ToUpper Then
tc += 1
Array.Resize(c, tc)
c(tc - 1) = ciudades(i)
End If
Next
Return c
End Function

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 119

Desarrollo de Aplicaciones Multiplataforma

Colecciones
Una coleccin es un objeto que sirve para agrupar objetos relacionados, pudiendo aadir o
quitar elementos en tiempo de ejecucin gracias a mtodos preparados para estas tareas.
Toda coleccin estar definida de la clase Collection que nos proporciona funcionalidad
integrada que permite Aadir o/y Borrar elementos con mtodos del tipo: Add, Remove, ,
recorrer en iteracin los miembros mediante la instruccin For Each...Next (la veremos en este
captulo) y recuperar los elementos usando su ndice o una clave String.
Tenemos colecciones con las que ya hemos venido trabajando, y que se encuentran en todo
formulario como las colecciones de elementos Items o elementos seleccionados SelectedItems
incorporadas en toda ListBox o ComboBox , la de controles Controls de todo formulario o
control
contenedor,
la
de
formularios
abiertos
en
la
aplicacin

My.Application.OpenForms

Operaciones con una coleccin.


Las operaciones base, mtodos de una coleccin suelen ser los imprescindibles para su
gestin. En toda coleccin podremos hacer las siguientes operaciones:
Aadir un elemento
Quitar un elemento
Limpiar o vaciar la coleccin.
Comprobar si existe un elemento determinado.
Recorrer la coleccin.
Acceder a un elemento de la coleccin.
Devolver cuentos elementos hay en la coleccin.

Tipos de coleccin.
Los tipos de colecciones existentes van en funcin de lo que se hace normalmente con el
manejo de sus datos, pudiendo encontrarnos con:
Lista.
Pila.
Cola.
Emparejamiento de datos, clave y valor.
El acceso a dichas colecciones, y sus mtodos, depender del tipo de estructura a la cual esta
dirigida la coleccin.

Uso del bucle For

Each para las colecciones o arrays

Este bucle permite recorrer los elementos de una coleccin o array mediante una variable
auxiliar elemento que deber ser del mismo tipo que la coleccin. En cada iteraccin, esta
variable har referencia a un elemento, lgicamente de forma correlativa, es decir, al comienzo
(y siempre que la coleccin no est a Nothing o con Count a 0) elemento har referencia al
primero de la coleccin, en la siguiente vuelta al 2, y as sucesivamente mientras haya
elementos.
For Each elemento As tipoDeLaColeccion In coleccion
instrucciones()
Next

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 120

Desarrollo de Aplicaciones Multiplataforma

Ejemplos de bucle For Each y su homlogo For tpico.


Private Ciudades() As String = {"Pamplona", "Burlada", "Baraain", "Tudela"} '
Array de string, que contiene una serie de ciudades. Puede ir cambiando en tiempo
de ejecucin
' Con este For la variable ciudad ir recorriendo las diferentes ciudades del
array. Esta variable (ciudad) debe ser, por tanto, del mismo tipo que el array
(String).
For Each ciudad As String In Ciudades
lbl.Text &= ciudad
Next
' El siguiente For hara exactamente lo mismo. Observa que en este caso la
variable i es Integer, ya que define la posicin del elemento en el array.
For i As Integer = O To Ciudades.Count - 1
lbl.Text &= Ciudades(i)
Next

De la misma forma, si queremos recorrer los diferentes elementos de una ListBox, podemos
hacerlo mediante los dos for siguientes, en los que recorre los diferentes elementos de la
ListBox, y selecciona aquellos que empiecen por B, almacenndolos en una etiqueta.
For i As Integer = 0 To lstCiudades.Items.Count - 1
If lstCiudades.Items(i).StartsWith("B") Then
lblCiudades.Text &= lstCiudades.Items(i) & " "
End If
Next

Con el nuevo bucle sera:


For Each elem As String In lstCiudades.Items
If elem.StartsWith("B") Then
lblCiudades.Text &= elem & " "
End If
Next

Es decir, un bucle For Each es equivalente a recorrer con una variable entera desde la
posicin 0 hasta la Count -1.
Supongamos que tenemos una coleccin (o array) de Personas (de la clase Persona). El
siguiente bucle recorrera todas
Private Personas As List(Of Persona) = {}
For Each per As Persona In Personas ' Recorre todas las personas y muestra la
edad de aquellas que se llamen igual al valor que est en la caja de texto.
If per.Nombre = txtNombre.Text Then
MessageBox.Show (per.Edad)
End If
Next

Lgicamente si deseamos recorrer la coleccin en otro orden, orden inverso, recorriendo solo
los elementos pares, deberemos usar siempre el For tradicional.
Cuidado! No podremos utilizar este bucle si lo que deseamos es borrar alguno de sus
elementos. Observa el siguiente ejemplo:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 121

Desarrollo de Aplicaciones Multiplataforma


For Each ciudad As String In Ciudades ' Error de ejecucin
Ciudades.Remove(ciudad)
Next

Aparentemente ira recorriendo los diferentes elementos y los ira eliminando, de la misma
forma que tampoco podramos usar su equivalente, ya que tras borrar el primer elemento,
detecta que la coleccin ha cambiado y se la.
For i As Integer = 0 To Ciudades.Count 1 ' Como en el caso anterior, error
Ciudades.Remove(Ciudades(i))
Next

eliminar elementos de una


deberemos recorrer la coleccin en orden inverso, en la forma:
Es por eso, que siempre que queramos

coleccin

For i As Integer = Ciudades.Count - 1 To 0 Step -1 ' Recorrer en orden inverso


Ciudades.Remove(Ciudades(i))
Next

Coleccin de tems en las ListBox, ComboBox,


Para repasar desde conceptos que ya conocemos, supongamos que tenemos una lista llamada
lstCiudades. Para ella podremos escribir el siguiente cdigo, con el que veremos los diferentes
mtodos o propiedades que podemos utilizar gracias a ser una coleccin de elementos.
If lstCiudades.Items.Count = 0 Then ' Count indica la cantidad de elementos que
tiene la lista
MessageBox.Show("Lista vaca")
End If
lstCiudades.Items.Add("Pamplona") ' Aade un nuevo elemento con el dato
"Pamplona"
Dim ciudades() As String = {"Burlada", "Baraain", "Tudela"}
lstCiudades.Items.AddRange(ciudades) ' Aade 3 nuevos elementos
lstCiudades.Items.Remove("Burlada") ' Elimina el elemento cuyo dato es "Burlada"
lstCiudades.Items.RemoveAt(0) ' Elimina el elemento que se encuentra en la
posicin 0 (el 1, en este ejemplo "Pamplona")
If Not lstCiudades.Items.Contains(txtCiudad.Text) Then
lstCiudades.Items.Add(txtCiudad.Text)
End If
Dim pos As Integer = lstCiudades.Items.IndexOf(txtCiudad.Text)
If pos = -1 Then ' No se encuentra
MessageBox.Show(txtCiudad.Text & " no existe")
Else ' Esta en la posicin devuelta por IndexOf
MessageBox.Show(txtCiudad.Text & " est en la posicin " & pos)
End If

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 122

Desarrollo de Aplicaciones Multiplataforma


' Recorrer sus elementos, ejemplo, para mostrar los que empiezan por una letra
For i As Integer = 0 To lstCiudades.Items.Count - 1 ' Count nos indica la
cantidad de elementos de la lista
If TryCast(lstCiudades.Items(i), String).StartsWith("B") Then 'En VB se podra
poner: lstCiudades.Items(i).StartsWith("B") pero con TryCast es ms lgico, ya
que hay que indicarle que es un String
MessageBox.Show(lstCiudades.Items(i))
End If
Next
lstCiudades.Items.Insert(0, "Viana") ' inserta en la posicin 0 un nuevo
elemento, trasladando el resto hacia "abajo"
Dim ciudadesCopia(lstCiudades.Items.Count - 1) As String ' Creo un array para
guardar los elementos de la lista
lstCiudades.Items.CopyTo(ciudadesCopia, 0) ' CopyTo permite copiar a un array o
coleccin
lstCiudades.Items.Clear() ' Quita todos los elementos de la lista

Colecciones de solo lectura. Ejemplo: coleccin de formularios


abiertos en la aplicacin
La propiedad OpenForms o MdiChildren representan un par de colecciones de slo
lectura en las que se pueden recorrer todos sus elementos (formularios) como en el caso
anterior, buscar o posicionarse en uno (por la posicin de ndice o por la propiedad Name de
Form), o saber cuantos elementos tiene, pero no se permite aadir, borrar, o eliminar todos los
elementos de forma directa como en los mtodos anteriores.
La coleccin OpenForms contiene los formularios que estn abiertos (cargados en memoria)
en el momento; es decir, no los posibles existentes en el proyecto, sino los que estn cargados
en el momento de ejecucin.
De la misma forma la coleccin MdiChildren, contiene los formularios hijos cargados en
un formulario Mdi (concepto que veremos en otro captulo).
En ambos casos, aadiremos o eliminaremos elementos al cargar / descargar el formulario
correspondiente, es decir, al realizar una instruccin del tipo frm.Show() se aadir un nuevo
elemento a la lista y en cambio frm.Close() lo eliminara.
Si queremos recorrer todos los formularios de la coleccin podremos hacerlo mediante
cualquiera de los bucles for:
' Cambia el texto de todos los formularios excepto el que tiene de ttulo Men
For i As Integer = 0 To My.Application.OpenForms.Count - 1
If My.Application.OpenForms(i).Text <> "Men" Then
My.Application.OpenForms(i).Text = "Texto comn"
End If
Next

Igualmente podemos usar el For Each en la forma:


' Cambia el texto de todos los formularios excepto el que tiene de ttulo Men
For Each frm As Form In Application.OpenForms ' frm sirve para ir recorriendo la
coleccin. En cada iteraccin ir haciendo referencia al siguiente formulario de
la coleccin
If frm IsNot Me Then ' Si no soy yo, es decir, para el resto de los
formularios abiertos
frm.Text = "Ttulo comn"
End If
Next

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 123

Desarrollo de Aplicaciones Multiplataforma

Coleccin de controles
Cada formulario o control contenedor (ejemplo: GroupBox), est formado por una propiedad
Controls que contiene la coleccin de controles de los que est compuesto el formulario (o
control). Esto nos permitir recorrerlos como en los casos anteriores.
Veamos un ejemplo, en el que intentamos limpiar todas las cajas de texto que haya en el
formulario. Para eso podemos recorrer todos los controles, analizando para cada uno de ellos, si
es o no una caja de texto, y solo en el caso de que lo sea se limpiar su texto. Esto lo podremos
hacer con cualquiera de los dos For (si no entiendes el For Each vete al apartado anterior donde
se explica).
For Each miControl As Control In Me.Controls ' Recorre todos los controles
If miControl.GetType = GetType(TextBox) Then ' Si el control es una caja de
texto
TryCast(miControl, TextBox).Clear() ' Limpia la caja de texto
End If
Next

Expliquemos un poco el cdigo. El For Each nos permite recorrer todos los controles de la
coleccin Controls del formulario.
Cuidado! Aunque solo queramos pasar por las cajas de texto, la variable deberemos
declararla del tipo de la coleccin. El siguiente bucle dara error de ejecucin
For Each txt As TextBox In Me.Controls ' Como va recorriendo todos los controles,
al encontrarse con un control que no sea caja de texto, se producira una
excepcin

Una vez que nos encontramos en un control, debemos saber si es una caja de texto, y para
eso preguntaremos si su tipo coincide con el de la clase TextBox (es decir, si es una caja de
texto). Esta pregunta se puede hacer de ms formas, por ejemplo:
If miControl.GetType.Name = -"TextBox" Then ' Si el nombre del tipo es TextBox

Y para qu necesitamos poner el TryCast al control? Pues para convertir el tipo de la


variable miControl (que en principio es Control) a TextBox (una vez que hemos garantizado
que lo es mediante el If en el que se encuentra). Ya sabemos que en el caso de VB no es
extrictamente necesario, pero si lo haces, entre otras cosas, podrs acceder a todas las
propiedades de las cajas de texto. Si no, solo nos aparecern (en tiempo de diseo) las genricas
por ser control.
Lgicamente el ejemplo anterior tambin lo podemos resolver con el tpico For, en la forma:
For i As Integer = 0 To Me.Controls.Count - 1
If Me.Controls(i).GetType = GetType(TextBox) Then
TryCast(Me.Controls(i), TextBox).Clear() ' Limpia la caja de texto
End If
Next

Observa el formulario de
la imagen. La coleccin
Me.Controls del formulario
solo tiene 3 controles: el
marco de Ventas, el de Nuevo
artculo y el botn Fin
programa. Los otros controles
no pertenecen a esa coleccin
sino al marco correspondiente:
Me.grbVentas.Controls

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 124

Desarrollo de Aplicaciones Multiplataforma

Agregar controles a un formulario o control en tiempo de ejecucin. Add


y AddRange
Veamos, mediante un ejemplo de creacin de un botn, como se pueden crear controles en
tiempo de ejecucin.
Para ello debemos declarar un objeto de la clase control correspondiente, darle los valores
oportunos y aadirlo a la coleccin de controles mediante el mtodo Add de la coleccin.
' Declaramos la variable de la clase de control a crear
Dim boton As Button ' Variable de tipo Button
boton = New Button
' Crea el botn, creando una nueva instancia de la clase
Button. Como siempre ambas lneas se pueden reducir a una sola.
' Damos valor a las propiedades que consideremos necesarias
boton.Location = New Point(20, 10) ' Posicin donde se crear respecto al
contenedor (formulario o control). Pueden ser valores variables
boton.Name = "btnAceptar" ' El nombre, que se considera como la clave del control
boton.Text = "&Aceptar"
boton.Size = New Size(70, 50) ' Tamao. Si no damos valores lo crea de un tamao
concreto.
Me.Controls.Add(boton) 'Lo aadimos a la coleccin de los controles.

Lgicamente tambin podemos modificar otras propiedades, ejemplo:


boton.Tag = "Barco"

En este ejemplo indicamos que el control que aadimos pertenece a la coleccin de controles
del formulario (por poner la palabra Me o si no la ponemos).
Si queremos que esta coleccin est dentro de otro control lo indicaramos poniendo
Controls como mtodo del control propietario.
Ejemplo:
grbTenderos.Controls.Add(boton)

Indicara que el nuevo botn se aade en un marco (GroupBox) llamado grbTenderos.


Para crear varios a la vez podramos usar AddRange en la forma:
Dim btn(5) As Button ' Botones a crear
Dim x As Integer = 160
For i As Integer = 0 To 5
btn(i) = New Button
btn(i).Name = "btn" & i.ToString ' Pongo diferente nombre a cada control.
Tambin podra ser el mismo para todos (en tiempo de diseo esto no puede ser,
pero aqu s)
btn(i).Location = New Point(x, 60)
btn(i).Size = New Size(70, 30)
btn(i).Text = i.ToString
x += btn(0).Width + 10 ' La nueva posicin depende del ancho del control
Next
Me.Controls.AddRange(btn) ' Se aaden a los controles del formulario

Ya tenemos el o los controles creados, ahora nos falta conectar los eventos del botn (en el
siguiente ejemplo lo haremos con el evento Click) con un procedimiento ya declarado (ver
ejemplo con BotonClic). Para poder asociarlo usaremos la palabra clave AddHandler,
pasndole la direccin del procedimiento a asociar con AddressOf. Si necesitamos quitar esta
asociacin tenemos RemoveHandler.
AddHandler boton.Click, AddressOf BotonClic

Siendo el subprograma, por ejemplo:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 125

Desarrollo de Aplicaciones Multiplataforma


Private Sub BotonClic(ByVal sender As Object, ByVal e As System.EventArgs)
MessageBox.Show(sender.Text) ' Aunque esta forma no es aconsejable (ver
siguiente comentario) en VB funciona sin hacer conversin en sender
End Sub

Recuerda que la variable sender (le puedes poner otro nombre, aunque no es habitual)
indica el objeto sobre el que se ha realizado el evento (en este caso el clic). El subprograma de
arriba mostrara un mensaje con el texto del control. Pero como sender es una variable Object
genrica es mejor hacer una conversin de tipo en cualquiera de las formas planteadas a
continuacin:
Private Sub BotonClic(ByVal sender As Object, ByVal e As System.EventArgs)
frmTienda.Text = TryCast(sender, Button).Text) ' Convertir el objeto Object al
tipo correspondiente
End Sub

Las funciones TryCast, DirectCast o Ctype permiten convertir de un tipo


genrico (en este caso Object) a uno ms concreto (en nuestro ejemplo Button) mostrando as
todas las propiedades que la nueva clase (Button) dispone. Pero cuidado! si el objeto al que
hace referencia la variable sender no fuese un botn (puede ocurrir que al subprograma
BotonClic se pudiese llegar mediante eventos de otros controles) la instruccin provocara un
error de ejecucin.
En los tres casos la forma de conversin es semejante:
Dim btn As Control = TryCast(sender, Button)
Dim btn As Control = Ctype(sender, Button)
Dim btn As Control = DirectCast(sender, Button)

Aunque en este caso las tres formas de conversin seran vlidas, tienen ciertas diferencias.
sirven para todos los tipos de datos, TryCast solo para tipos por referencia
(veremos estos conceptos ms adelante).
Ctype y DirectCast

Otra cosa que les diferencia, es como tratar los posibles errores de conversin. Supongamos
que el procedimiento BotonClic tambin est asociado a un evento de otro tipo de control, por
ejemplo, de una etiqueta. Al intentar hacer la conversin, Ctype y DirectCast produciran un
error de ejecucin InvalidCastException, mientras que TryCast devuelve el valor Nothing,
de modo que en lugar de controlar la posible excepcin, slo debemos comprobar el resultado
devuelto con Nothing.
Por tanto, para controlar los posibles errores tenemos varias posibilidades:
Averiguar el tipo antes de intentar hacer la conversin, en cualquiera de las formas
siguientes:
Mediante el mtodo GetType:
If
el
If
el

sender.GetType.Name = "Button" Then ' Como analizamos la propiedad Name ser


nombre en String
sender.GetType = GetType(Button) Then ' Preguntamos si el tipo del objeto es
mismo que el de la clase Button, por eso Button va sin comillas

Incluso con la funcin de VB TypeName (aunque este caso mejor dejarlo ya como obsoleto):
If TypeName(sender) = "Button" Then

Otra posibilidad con la instruccin TryCast sera:


Dim boton As Button = TryCast(sender, Button) ' Si no puede realizer la
conversin devuelve Nothing
If boton Is Nothing Then Exit Sub ' No era un botn

O bien directamente:
If TryCast(sender, Button) Is Nothing Then Exit Sub

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 126

Desarrollo de Aplicaciones Multiplataforma

Atencin: Si creamos los controles en tiempo de ejecucin su orden en la coleccin ser


ascendente, es decir, si creamos el 4 el siguiente ser el 5, pero si la creacin ha sido en tiempo
de diseo, el Controls(0) curiosamente ser el ltimo que hayamos dibujado, ya que VB los
aade en orden contrario al diseo.

Eliminar un control: Remove, RemoveAt y RemoveByKey


Para eliminar un control debemos usar un mtodo Remove.
Si tenemos el control en concreto podemos borrarlo gracias al mtodo Remove. Veamos un
par de ejemplos:
Supongamos que en tiempo de diseo hemos creado el botn btnPersona, podemos
eliminarlo en la forma:
Me.Controls.Remove(btnPersona)

Igualmente si conocemos el control por otro motivo, como por ejemplo, si es el objeto sobre
el que se ha producido un evento:
Private Sub BotonClic(ByVal sender As Object, ByVal e As System.EventArgs)
Me.Controls.Remove(sender) ' elimina el control sobre el que se ha producido
el evento
End Sub

Si en lugar del objeto, conocemos el ndice usaramos RemoveAt, en la forma:


Me.Controls.RemoveAt(Me.Controls.Count - 1) ' elimina el ultimo control creado
(no importa que sea en tiempo de diseo o ejecucin)

Si en lugar de la posicin lo que conocemos es el nombre, podramos hacer:


Me.Controls.RemoveByKey("btn") ' elimina el control que tenga ese nombre. Si
hay varios con el mismo nombre elimina solo uno, el "primero" que lo tiene

Eliminar todos los controles: Clear


Y por ltimo, si queremos eliminar TODOS los controles, haramos:
Me.grbTienda.Controls.Clear()' elimina todos los controles del marco

Eliminar controles de forma selectiva: bucle descendente


Como ya comentamos en el prrafo referente al bucle For Each, para eliminar los controles
no podemos realizar ningn bucle en orden ascendente ya que nos borrar mal los elementos
(borrar unos y no otros, aunque cumplan la condicin) o incluso dar error de ejecucin.
Por qu puede borrar unos y no otros? Supongamos que tenemos 4 controles: en la posicin
0 un botn, y en las posiciones 1 a 3 tres etiquetas (prueba con un formulario, creando
fsicamente primero el botn y luego las tres etiquetas).
For Each miC As Control In Me.Controls ' Queremos eliminar todas las cajas de texto
If miC.GetType = GetType(TextBox) Then
Me.Controls.Remove(miC)
End If
Next
For i As Integer = 0 To Me.Controls.Count - 1
If Me.Controls(i).GetType =
GetType(TextBox) Then
Me.Controls.Remove(Me.Controls(i))
End If
Next

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 127

Desarrollo de Aplicaciones Multiplataforma

Si al hacer clic sobre el botn pones uno de estos dos bucles vers que deja una etiqueta sin
borrar con el primer For (el For Each) y en el segundo adems de no borrar la segunda etiqueta
da error de ndice ya que la i intenta llegar a un valor 3 que ya no existe.
El motivo de que no borre la etiqueta Labe2 es porque en la iteraccin, al borrar la Label3
(primera que borrara) la Label2 cambia de posicin en la coleccin de los Controls (antes
estaba en la posicin 1 y ahora en la 0) por lo que se da ya por analizada y por tanto no la
borrar.
For i As Integer = Me.Controls.Count 1 To 0 Step -1
descendente
If Me.Controls(i).GetType = GetType(TextBox) Then
Me.Controls.Remove(Me.Controls(i))
End If
Next

' Eliminar en orden

Busqueda de un control en la coleccin de los controles


Cmo averiguar si existe uno o varios controles que cumplan una caracterstica
concreta? Dependiendo de lo que conozcamos y deseemos encontrar tenemos varias
posibilidades.
Conociendo el nombre: ContainsKey, IndexOfKey, Find
Suponiendo que conocemos el nombre: Tenemos los mtodos ContainsKey,
IndexOfKey y Find que nos indicarn si hay o no (ContainsKey), la posicin en que se
encuentra el primero que tenga ese nombre o -1 para indicar que no hay ninguno (IndexOfKey)
o una matriz de controles con todos los controles que tengan ese nombre siendo de longitud 0 si
no hay ninguno (Find). Veamos unos ejemplos de su posible uso:
If Me.grb.Controls.ContainsKey("btn") Then ' Si hay al menos un control en el
marco con ese nombre (exactamente ese nombre)
Dim posBoton As Integer = Me.grb.Controls.IndexOfKey("btn") ' Devolver la
posicin en que se encuentra el control que tenga ese nombre (o el primero si hay
varios)

El mtodo Find tiene un segundo parmetro para indicar si se deben buscar los controles
secundarios o no. Se consideran controles secundarios los que estn dentro de un control que
est dentro de este. Si observas el formulario del apartado Coleccin de controles si
Dim controles() As Control = Me.Controls.Find("btn", False) ' Busca todos los
controles que hay directamente en el formulario con ese nombre. Si no hay ninguno
controles tendr longitud 0. Si hay alguno pero esta dentro de un marco no lo
reconoce.
Dim botones() As Control = Me.Controls.Find("btn", True) ' Como en el caso
anterior, pero en este caso busca en el formulario y en los contenedores que
estn dentro de l, es decir, si hay en algn marco, panel, .. tambin los
devuelve.

Cuidado! El array lo hemos definido de la clase Control y no Button, debido a que el


mtodo Find devuelve una coleccin de controles y por tanto obliga a que ese sea el tipo.
Observa la siguiente figura:

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 128

Desarrollo de Aplicaciones Multiplataforma

Obtener o modificar el ndice de un control: GetChildIndex y SetChildIndex


Obtener o modificar el ndice de un control dentro de la coleccin: GetChildIndex y
SetChildIndex. En el caso de GetChilIndex tiene un segundo parmetro boolean para
indicarle que genere una excepcin (True) o devuelva -1 si no lo encuentra (False). En
SetChildIndex cambia el ndice que tena, modificando
Dim n As Integer = Me.Controls.GetChildIndex(btnCrear, False) ' Devuelve el
ndice (posicin) del botn btnCrear en la coleccin de controles del formulario.
Si no existe devuelve -1
n = Me.Controls.GetChildIndex(btnCrear, True) ' Devuelve el ndice (posicin)
del botn btnCrear en la coleccin de controles del formulario. Si no existe
produce una excepcin
Me.Controls.SetChildIndex(btnCrear, 0) ' Le pone a btnCrear el ndice 0,
modificando el resto en funcin de este cambio

Buscar por otras caractersticas


Si no conocemos la clave (el nombre) sino solo una parte de l, queremos buscar por otra
propiedad, como por ejemplo por el Tag, o por otro tipo de casustica, necesitaremos recorrer la
coleccin mediante un bucle For.
Dim txtCajas() As TextBox = {} ' Array para guardar las cajas de texto del
formulario
For Each miControl As Control In Me.Controls
If miControl.GetType = GetType(TextBox) Then ' Si el control es una caja de
texto
Array.Resize(txtCajas, txtCajas.Length + 1) ' redimensionamos el array
txtCajas(txtCajas.Length - 1) = miControl ' hace referencia a ella en el
array
End If
Next
For Each txt As TextBox In txtCajas ' Recorro todas las cajas para limpiarlas
txt.Clear()
Next

Cuando se agregan varios controles a un control principal, es recomendable llamar al


mtodo SuspendLayout antes de inicializar los controles que se van a agregar. Despus de
agregar los controles al control principal, hay que llamar al mtodo ResumeLayout. De esta
forma, aumenta el rendimiento de las aplicaciones que tienen muchos controles.

Copiar la coleccin en un array


Si deseamos guardar todos los controles en un array compatible (de controles), podemos
hacerlo cmodamente gracias al mtodo CopyTo.
Dim misControles(Me.Controls.Count - 1) As Control
Me.Controls.CopyTo(misControles, 0) ' el 0 indica que la copia empieza desde la
posicin 0.

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 129

Desarrollo de Aplicaciones Multiplataforma

Creando nuestras propias colecciones


Hasta ahora hemos trabajado con arrays y las colecciones nos dan las clases existentes.
La diferencia principal entre las colecciones y los arrays, o al menos una de las principales,
es que podemos agregar nuevos elementos, y tambin eliminarlos, de una forma ms sencilla
que los arrays. Por ejemplo, para aadir un nuevo elemento al array debemos hacer un hueco
para ese nuevo elemento (redimensionando el array), mientras que con las colecciones no
tenemos que ocuparnos de ese detalle ya que habr un mtodo que lo haga. Por tanto, aunque en
ciertas ocasiones es preferible usar arrays, porque puede resultar un cdigo ms rpido y que
consuma menos memoria (sobre todo si sabemos que no estaremos cambiando continuamente el
nmero de elementos) seguro que en la mayor parte de las ocasiones preferiremos las
colecciones por su sencillez de uso y el cdigo que nos ahorra.
El espacio de nombres System.Collections del entorno de .NET Framework, es el encargado
de agrupar el conjunto de clases e interfaces que nos permiten la creacin de los distintos tipos
de objetos Collection. Por lo que si necesitamos un array con alguna caracterstica especial, slo
hemos de instanciar un objeto de alguna de las clases de este espacio de nombres para disponer
de un array con esa funcionalidad. Entre las clases ms significativas de System.Collections,
podemos destacar las siguientes.
Las colecciones son tipos de datos por referencia, por tanto, al igual que cualquier clase,
para crear un nuevo objeto de un tipo de coleccin debemos usar New.
Dim Nombres As New ArrayList

ArrayList. Proporciona una coleccin, cuyo array es redimensionado dinmicamente


segn se requiera.
Hashtable. Las colecciones de este tipo, contienen un array cuyos elementos se basan
en una combinacin de clave y valor, de manera que el acceso a los valores se facilita,
al realizarse mediante la clave.
SortedList. Consiste en una coleccin de pares de clave y valor ordenados por claves a
los que se puede tener acceso por clave y por ndice.
Queue (Cola). Representa una coleccin de objetos de tipo FIFO (First in, first out)
primero en entrar, primero en salir
Stack (Pila). Representa una lista de valores LIFO (Last in, firt out), en el que el ltimo
valor que entra, es el primero que sale.
Y las paralelas que definiremos como colecciones generic.
List (Of T). Representa una lista fuertemente tipada de objetos a los que se puede
obtener acceso por el ndice. Proporciona mtodos para buscar, ordenar y manipular
listas.
SortedList(Of TKey, TValue): Representa una coleccin de pares clave/valor que se
ordenan conforme a la clave.
LinkedList(Of T): Lista doblemente vinculada.
Queue (Of T): Coleccin de objetos FIFO.
Stack(Of T). Coleccin LIFO.
Dictionary(Of TKey, TValue) Representa una coleccin de claves y valores.
Una coleccin es un objeto que internamente gestiona un array o una lista, pero que est
preparado, dependiendo del tipo de coleccin, para manejar el array que contiene de una manera
especial; podramos definirlo como un array optimizado o especializado en ciertas tareas.

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 130

Desarrollo de Aplicaciones Multiplataforma

Cmo podemos definir nuestras propias colecciones? Veamos una forma con la coleccin
ArrayList.

La clase ArrayList
Los objetos de tipo coleccin creados con la clase ArrayList, implementan un array cuyo
nmero de elementos puede modificarse dinmicamente, permitiendo aadir, eliminar y
modificar fcilmente los elementos que contiene. Tambin podemos recorrerlos mediante un
bucle For accediendo a los elementos por medio de un ndice o con un For Each pasando por
cada uno los elementos en la iteraccin (ver punto anterior).
Al igual que ocurre con los arrays, el ndice inferior es siempre cero y los elementos se
almacenan de forma consecutiva, es decir, si aadimos dos elementos a una coleccin de tipo
ArrayList, el primero ocupar la posicin cero y el segundo la posicin uno. La ventaja de
trabajar con las colecciones es que no debemos preocuparnos de reservar memoria cada vez que
vayamos a aadir un nuevo elemento, simplemente usamos el mtodo Add y asunto arreglado.
Lo mismo ocurre a la hora de quitar elementos de una coleccin, no tenemos que
preocuparnos demasiado por el espacio dejado al quitar elementos, de eso se encarga el propio
.NET, nosotros simplemente debemos llamar al mtodo Remove o RemoveAt indicando
respectivamente el elemento a eliminar o el ndice en el que se encuentra almacenado.
Cuidado! Si decidimos eliminar varios elementos de una coleccin de tipo ArrayList (al
igual que ocurra con los arrays normales), lo normal es que lo hagamos usando un bucle For;
pero recuerda que debemos recorrer el bucle desde el final hacia adelante, con idea de que al
cambiar el nmero de elementos no falle intentado acceder a un elemento que ya no existe.

Instanciacin de objetos ArrayList


Podemos instanciar una coleccin ArrayList con los siguientes modos. Observa cmo en el
ltimo ejemplo, el constructor de ArrayList recibe como parmetro una coleccin dinmica.
Dim ciudades1 As ArrayList()' definir una lista pero sin crear ninguna instancia
Dim ciudades2 As New ArrayList()' crear una lista que como tal ya existe pero sin
elementos
Dim ciudades3 As New ArrayList(10)' Indica que crea una lista sin elementos
aunque inicialmente con Capacidad 10 (no confundir con Count, ya que realmente no
tiene ningn elemento como en el caso anterior)
Dim ciudades4 As New ArrayList(New String() {"Berln", "Lisboa"})' crearla
utilizando una coleccin dinmica y con valores

Observa que si intentamos acceder a las diferentes listas, en el caso de ciudades1 puede que
no exista (en las otras s aunque tenga tamao 0).
Ejemplo. Si intento acceder a ciudades1 despus de la declaracin anterior, se producir un
error de ejecucin:
For Each c As Ciudad In ciudades1
' trabajar con c
Next

' ciudades1 puede ser Nothing

En este caso una posible solucin sera:


If ciudades1 IsNot Nothing Then
For Each c As Ciudad In ciudades1
' trabajar con c
Next
End If

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 131

Desarrollo de Aplicaciones Multiplataforma

Clases que vamos a usar para los siguientes ejemplos:


Supongamos las siguientes clases en su forma ms sencilla de diseo (sin controlar nada en
las propiedades, ):
Public Class Persona
Public Property Nombre As String ' No controla nada en Get ni Set por lo que
dejamos as la propiedad
Public Property Edad As Integer
Public Sub New() ' Constructor vaco, Nombre y Edad empiezan con valores "" y
0 respectivamente
End Sub
Public Sub New(ByVal nombre As String, ByVal edad As Integer) ' Constructor
con parmetros, la persona comienza con un nombre y una edad
Me.Nombre = nombre
Me.Edad = edad
End Sub
End Class
Public Class Pais
Public Property NomPais As String
Public Property Capital As String
Public Property DifHoraria As Integer
Public Sub New()
End Sub
Public Sub New(ByVal nombre As String, ByVal capital As String, ByVal
difHoraria As Integer)
Me.NomPais = nombre
Me.Capital = capital
Me.DifHoraria = difHoraria
End Sub
End Class

Inicializadores de una coleccin: From


Los inicializadores de coleccin proporcionan una sintaxis abreviada que permite crear una
coleccin y rellenarla con un conjunto inicial de valores. Este tipo de inicializadores son tiles
cuando se crea una coleccin a partir de un conjunto de valores conocidos como, por ejemplo,
una lista de opciones de men o categoras, un conjunto inicial de valores numricos, una lista
esttica de cadenas (como nombres de da o mes), o ubicaciones geogrficas (por ejemplo, una
lista de estados que se usa con fines de validacin).
Un inicializador de coleccin se identifica mediante la palabra clave From seguida de llaves
( {}). En los siguientes ejemplos se muestran varias formas de usar los inicializadores de
coleccin para crear colecciones.
' Crea una coleccin con 3 elementos iniciales de la clase Pais, los dos primeros
con datos pasados para el constructor de parmetros y el 3 se crear mediante el
constructor vaco (NomPais, Capital y DifHoraria empezarn en blanco y 0
respectivamente)
Dim miMundo As New ArrayList From {
{New Pais("Francia", "Paris", 1)},
{New Pais("Rusia", "Mosc", 4)},
{New Pais()}
}

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 132

Desarrollo de Aplicaciones Multiplataforma

Agregar valores a un ArrayList: Add, AddRange, Insert, InsertRange y


SetRange
Una vez creado un ArrayList, podemos utilizar algunos de los mtodos ya conocidos para
aadir valores a la coleccin.
Add(Valor). Aade el valor representado por Valor.
Dim Paises As New ArrayList(10)
Paises.Add(New Pais("Alemania", "Berlin", 2))
Dim p As New Pais("Portugal", "Lisboa", 1)
Paises.Add(p)

AddRange(Coleccin). Aade un conjunto de valores mediante un objeto del interfaz


ICollection, es decir, una coleccin dinmica creada en tiempo de ejecucin.
Supongamos que tenemos definido la siguiente coleccin:
Dim Profes As New ArrayList

Si queremos aadir varias personas a la vez, podemos hacer:


Dim profesAadir As New ArrayList From {"Mara", "Susana", "Pello"}
Profes.AddRange(profesAadir)

Insert(Posicin, Dato). Inserta el Dato en la posicin Posicin del array, desplazando el


resto de elementos una posicin adelante. Lgicamente el valor de Posicin deber ser
un valor no negativo y menor o igual que el tamao de la coleccin.
Profes.Insert(1, "Elisa") ' Desplaza a Susana 1 posicin
Paises.Insert(0, New Pais("Alemania", "Berln", 2)) ' Inserta en la
posicin 0 este nuevo pas, desplazando los existentes

InsertRange(Posicin, Coleccin). Inserta un conjunto de valores mediante una


coleccin dinmica, a partir de una posicin determinada dentro del array.
SetRange(Posicin, Coleccin). Sobrescribe elementos de la coleccin con los valores
de la coleccin Coleccin, comenzando en la posicin Posicin
Veamos un ejemplo de uso de estos mtodos:
Private Sub btnAceptar_Click(ByVal ) Handles btnAceptar.Click
Dim capitales As New ArrayList(10) ' Admite inicialmente 11 datos de cualquier
tipo (de tipo Object)
capitales.Add("Berlin")
capitales.AddRange(New String() {"Pars", "Lisboa", "Madrid"})
Label1.Text = "Tras usar Add() y AddRange() : "
RecorrerAList(Label1, capitales)
capitales.Insert(2, "Roma")
Label2.Text = "Tras usar Insert() : "
RecorrerAList(Label2, capitales)
capitales.InsertRange(1, New Integer() {55, 77, 88})
Label3.Text = "Despus de usar InsertRange() : "
RecorrerAList(Label3, capitales)
capitales.SetRange(3, New String() {"Tudela", "Burlada"})
Label4.Text = "Despus de SetRange() : "
RecorrerAList(Label4, capitales)
End Sub
Private Sub RecorrerAList(ByVal lbl As Label, ByVal Valores As ArrayList)
For Each elem As String In Valores
lbl.Text &= elem & ","

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 133

Desarrollo de Aplicaciones Multiplataforma


Next
End Sub

El resultado sera:

El tipo de datos de almacenamiento en un ArrayList: GetType


Estos elementos internamente estn almacenados como objetos del tipo Object, por tanto
podemos aadir cualquier tipo de datos a una coleccin de este tipo, ya que todos los tipos de
datos de .NET estn basados en la clase Object, y es por ello, que en principio siempre que
queramos acceder a un elemento de este tipo de colecciones deberamos hacer una conversin al
tipo adecuado.
Ejemplo: Supongamos que definimos el siguiente ArrayList
Private Datos As New ArrayList From {
{New Persona("Mara", 25)},
{New Pais("Francia", "Pars", 1)},
{New Pais("Alemania", "Berln", 2)},
{"Tontera"}
}

Observa lo que hara el siguiente subprograma:


Private Sub RecorrerArray()
lbl.Text = ""
For Each elem As Object In Datos
Select Case elem.GetType.Name
Case "Persona" : lbl.Text &= " persona: " & TryCast(elem, Persona).Nombre &
ControlChars.CrLf
Case "Pais" : lbl.Text &= " pas: " & TryCast(elem, Pais).NomPais &
ControlChars.CrLf
Case "String" : lbl.Text &= " string " & TryCast(elem, String) &
ControlChars.CrLf
End Select
Next
End Sub

Obtencin de subarrays a partir de un objeto ArrayList: GetRange,


FixedSize, Repeat, ToArray, ReadOnly
La clase ArrayList nos proporciona mtodos tanto para obtener un fragmento o rango
(subarray) de un objeto ArrayList, como para crear nuevos objetos mediante mtodos shared o
compartidos. Entre este tipo de mtodos, se encuentran los siguientes.
GetRange(Posicin, Elementos). Obtiene un subarray comenzando en el ndice
Posicin, y tomando el nmero que indica Elementos.

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 134

Desarrollo de Aplicaciones Multiplataforma

FixedSize(ArrayList). Mtodo compartido que crea un array de tamao fijo a partir de


un objeto ArrayList pasado como parmetro. Sobre el nuevo array obtenido, podemos
modificar los elementos existentes, pero no aadir nuevos.
Repeat(Valor, Cantidad). Mtodo compartido que crea un ArrayList de valores
repetidos, tomando como valor a repetir el parmetro Valor, y creando tantos elementos
como se especifica en el parmetro Cantidad.
ToArray(). Copia los elementos del ArrayList en un objeto Array, al ser ambos arrays
independientes, el objeto sobre el que se han copiado los elementos puede modificarse
sin que afecte al ArrayList.
ReadOnly( ). Mtodo compartido que crea un objeto ArrayList de slo lectura a partir
de un array existente.
Dim alLetras As New ArrayList(10) ' Capacidad inicial 10
alLetras.AddRange(New String() {"a", "b", "c", "d", "e", "f", "g"})
Label1.Text = "Array alLetras : "
RecorrerAList(Label1, alLetras)
Dim alRangoLetras As ArrayList
alRangoLetras = alLetras.GetRange(4, 2) ' obtener un subarray con un rango
determinado
Label2.Text = "Array alRangoLetras : "
RecorrerAList(Label2, alRangoLetras)
Dim alLetrasFijo As ArrayList = ArrayList.FixedSize(alLetras) ' obtener un
subarray de tamao fijo, se pueden modificar sus elementos, no se pueden aadir
valores
'alLetrasFijo.Add("m") <-- esto provocara error
alLetrasFijo(2) = "vvv" ' S est permitido cambiar el contenido
Label3.Text = "Array alLetrasFijo : "
RecorrerAList(Label3, alLetrasFijo)
Dim alRepetidos As ArrayList
alRepetidos = ArrayList.Repeat("hola", 3) ' ArrayList de valores repetidos
alRepetidos.Add("otro valor")
Label4.Text = "Array alRepetidos :"
RecorrerAList(Label4, alRepetidos)
Dim aNuevo As Array
aNuevo = alLetras.ToArray()' copiar ArrayList sobre un array normal
aNuevo(2) = "zzz"
Label5.Text = "Array aNuevo : "
RecorrerArray(Label5, aNuevo) ' En este caso no podemos usar RecorrerAList porque
aNuevo no es un ArrayList
Dim alLetrasSoloLeer As ArrayList = ArrayList.ReadOnly(alLetras) ' crear
ArrayList de slo lectura a partir de un array existente solamente podemos
recorrerlo
Label6.Text = "ArrayList de slo lectura : "
RecorrerAList(Label6, alLetrasSoloLeer)
' las dos lneas siguientes provocaran un error
'alLetrasSoloLeer.Add("yyy")
'alLetrasSoloLeer(2) = "wwer"

Donde RecorrerAList y RecorrerArray son:


Sub RecorrerArrayList(ByVal etiqueta As Label, ByVal Valores As ArrayList)
For Each elem As String In Valores
etiqueta.Text &= elem & ","
Next
End Sub

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 135

Desarrollo de Aplicaciones Multiplataforma


' O lo que sera equivalente
For i As Integer = 0 To Valores.Count - 1
etiqueta.Text &= Valores(i) & ","
Next

' Count indica el n de elementos

Y RecorrerArray
Sub RecorrerArray(ByVal etiqueta As Label, ByVal Valores As Array)
For Each elem As String In Valores
etiqueta.Text &= elem & ","
Next
'For i As Integer = 0 To Valores.Length - 1 ' En arrays la propiedad es Length
'
etiqueta.Text &= Valores(i) & ","
'Next
End Sub

Bsquedas en colecciones ArrayList: Contains, IndexOf y LastIndexOf


Adems de los mtodos IndexOf y LastIndexOf, disponibles en los arrays estndar, un
ArrayList aporta el mtodo Contains, que como ya sabemos nos devuelve un valor lgico
indicando si el valor pasado como parmetro existe en el array.
Lgicamente si el ArrayList es de tipos estndar la bsqueda es muy fcil, pero cuidado si
contiene objetos de otras clases: en ese caso solo funcionar si modificamos los mtodos

Equals de la clase base.


Private Datos As New ArrayList From {
{New Persona("Mara", 25)},
{New Pais("Francia", "Pars", 1)},
{New Pais("Alemania", "Berln", 2)},
{"Tontera"}
}

El objeto pasado deber ser del tipo, por lo que si estamos con el String, lo siguiente tiene
sentido:
If Datos.Contains("Tontera") Then MessageBox.Show("Si contiene el string
Tontera")
MessageBox.Show(Datos.IndexOf("Tontera")) ' Devuelve la posicin 3
MessageBox.Show(Datos.IndexOf("Otra cosa")) ' Devuelve la posicin -1 pues no
contiene este String

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 136

Desarrollo de Aplicaciones Multiplataforma

Pero cuidado! Porque el siguiente cdigo puede parecer extrao aunque en el fondo es muy
lgico:
Dim pers As New Persona("Mara", 25) ' Nueva persona con estos datos
MessageBox.Show(Datos.Contains(pers)) ' Devuelve False ya que pers es una nueva
persona, y aunque coincida en los datos con el elemento 0 de Datos NO es el mismo
objeto a no ser que en la clase persona hayamos modificado el/los mtodos Equals.
Ejemplo indicando que dos personas son iguales cuando les coincide el Nombre (o
el nombre y la edad, o)
Public Overloads Function Equals(ByVal per As Persona) As Boolean
Return Me.Nombre = per.Nombre
End Function

Borrado de elementos en una coleccin ArrayList: Remove, RemoveAt,


RemoveRange y Clear
Para realizar un borrado de valores, la clase ArrayList proporciona los mtodos ya
conocidos:
Remove(Valor). Elimina el elemento del array que corresponde a Valor.
RemoveAt(Posicion). Elimina el elemento del array situado en el ndice Posicin.
RemoveRange(Posicin, Elementos). Elimina el conjunto de elementos indicados en
el parmetro Elementos, comenzando por el ndice Posicin.
Clear( ). Elimina todos los elementos del objeto

Ordenar elementos en un objeto ArrayList: Sort y Reverse


Al igual que en la clase base Array, los objetos ArrayList disponen de los mtodos:
Sort( ): ordena los elementos del array.
Reverse( ): invierte las posiciones de un nmero determinado de elementos del array.
Ejemplo
Supongamos que tenemos la clase ya conocida Persona de la cual podemos conocer su
Nombre y Edad, y otra Grupo que ser una coleccin de Personas. Esta clase permitir Aadir,
Modificar, Borrar una persona, Borrar todas, Buscar una persona conociendo su nombre,
En la clase Grupo podramos definir pPersonas de la siguiente forma:
Private pPersonas As New ArrayList ' New para que exista

Pudiendo aadir elementos en la forma:


pPersonas.Add(New Persona(txtNombre.Text, txtEdad.Text))

O bien:
Dim per As New Persona(txtNombre.Text, txtEdad.Text)
pPersonas.Add(per)

Para borrar un elemento podramos poner:


Dim p As Persona = pPersonas(0) ' La primera
pPersonas.Remove(p)

Aunque en realidad deberamos hacer primero la conversin, ya que el ArrayList en


principio es de tipo Object (haciendo la conversin con TryCast, CType o DirectCast.
Dim p As Persona = TryCast(pPersonas(0), Persona)

Tambin podemos borrar un elemento conociendo el ndice, (que generalmente ser como lo
hagamos) en la forma:
VB.Net (Cap 7. Arrays y Colecciones)

Pg. 137

Desarrollo de Aplicaciones Multiplataforma


pPersonas.RemoveAt(0)

' Borra la primera

Si queremos borrar todas, tenemos el mtodo Clear:


pPersonas.Clear() ' Elimina todos los elementos, Count pasa a ser 0

Y por ltimo, para recorrer las distintas personas podramos usar el For Each tpico:
For Each p As Persona In pPersonas
Me.ListBox1.Items.Add(p.Nombre)
Me.ListBox2.Items.Add(p.Edad)
Next

ArrayList de objetos
Cuidado, si lo que tenemos es un ArrayList de objetos de una clase, como en este enunciado,
las cosas se pueden complicar un poco.
Veamos unos ejemplos:
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
Dim pers As New ArrayList
Dim p As New Persona
p.Nombre = "Mara"
p.Edad = 30
pers.Add(p)
MostrarValores(Label1, pers)
p = New Persona("Pili", 34)
pers.Add(p)
MostrarValores(Label2, pers)
p = New Persona("Antonio", 20)
pers.Add(p)
MostrarValores(Label3, pers)
p = New Persona("Ignacio", 40)
pers.Add(p)
p = New Persona("Demi", 18)
pers.Add(p)
MostrarValores(Label4, pers)
Dim pc As New ArrayList
p = New Persona
p.Nombre = "Maramod"
p.Edad = 45
pc.Add(p)
p = New Persona
p.Nombre = "Pilimod"
p.Edad = 10
pc.Add(p)
pers.SetRange(0, pc)
MostrarValores(Label5, pers)
End Sub

Donde MostrarValores es:


Sub MostrarValores(ByVal etiqueta As Label, ByVal valores As ArrayList)
etiqueta.Text = ""
For i As Integer = 0 To valores.Count - 1
etiqueta.Text &= TryCast(valores(i), Persona).Nombre & ", "
Next
End Sub

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 138

Desarrollo de Aplicaciones Multiplataforma

Colecciones generic
Como hemos visto, un ArrayList almacena los elementos como una referencia a un objeto de
tipo Object, por lo que cada vez que utilicemos una coleccin debemos tomar precauciones si
nuestra intencin es que solo se puedan almacenar elementos de un tipo determinado.
Como representacin de colecciones

List (Of T)
En este caso definimos una coleccin basndonos en una clase en concreto, y ser el propio
compilador quien detecta el error en el caso de que intentemos aadirle un objeto que no sea de
la clase declarada, como puedes apreciar en el siguiente trocito de cdigo:
Ejemplo. Sunpongamos que tenemos una clase Biblio con la siguiente definicin:
Private _Personas As New List(Of Persona)
_Personas.Add(per) ' Instruccin permitida en un Sub o Function, siempre que per
sea de la clase Persona
_Personas.Add(btnFin) ' Si btnFin es un Button, dara como ERROR DE COMPILACIN:
Un valor de tipo System.Windows.Forms.Button no se puede convertir en Persona

La forma de usar una lista de este tipo, ser semejante a todo lo explicado para ArrayList.
Ejemplo, si tenemos una clase Libro con un constructor que permite crearlo pasndole el ttulo,
autor, precio y editorial, la siguiente declaracin creara una lista con 2 libros.
Private libros As New List(Of Libro) From {
New Libro("El camino", "Miguel Delibes", 18, "Ediciones Destino"),
New Libro("Terapia Gestalt", "Carmen Vazquez", 11.5, "Ctp")
}

A veces tenemos algunos cambios con respecto a los ArrayList, como por ejemplo,
determinar que una coleccin sea de solo lectura. Veamos como lo haramos en los dos casos.
Supongamos que continuamos con la coleccin anterior _Personas de la clase Grupo:
Podemos definir una propiedad que nos muestre y permita modificar estas personas:
Public Property Personas As List(Of CPersona) ' Podr hacer los cambios que desee
Get
Return _Personas
End Get
Set(ByVal value As List(Of CPersona))
_Personas = value
End Set
End Property

Es decir, las siguientes instrucciones son todas vlidas (con el objeto miGrupo de la clase
Grupo):
miGrupo.Personas.Add(New Persona()) ' Aade una nueva persona a la coleccin
miGrupo.Personas = otraLista ' Personas cambia totalmente con la otra lista
miGrupo.Personas(0).Nombre = "Mara" ' Cambia el nombre de la primera persona

Pero hay ocasiones en que no queremos permitir que modifiquen una lista. Para conseguir
esto, posiblemente se nos ocurrira definir una propiedad de solo lectura en la forma:
Public ReadOnly Property PersonasRO As List(Of CPersona) ' Devuelve la coleccin
tal cual, al ser ReadOnly la Property, no podremos hacer una asignacin
PersonasRO = OtrasPersonas pero S podr hacer PersonasRO.Add(persona)
Get
Return _Personas
End Get
End Property

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 139

Desarrollo de Aplicaciones Multiplataforma

Con esto solo conseguimos que no se pueda hacer una asignacin completa (del estilo
miGrupo.Personas = otraLista), pero s seran validas las otras posibilidades.
miGrupo.PersonasRO.Add(New Persona()) ' Esto est permitido, e igual que en el
ejemplo anterior, aade una nueva persona a la coleccin
miGrupo.PersonasRO = otraLista ' ERROR DE EJECUCIN, ya que no existe el Set de
la propiedad
miGrupo.PersonasRO(0).Nombre = "Mara" ' Permitido, y como antes, pone nombre a
la primera persona (o lo cambia si ya tena uno)

Para acercarnos a lo que deseamos, deberamos usar el mtodo AsReadOnly de las List(Of
T), teniendo en cuenta que no nos devuelve una List(Of T) sino una coleccin de solo lectura:
System.Collections.ObjectModel.ReadOnlyCollection(Of T). La propiedad quedara:
Public ReadOnly Property PersonasSoloLect As

System.Collections.ObjectModel.ReadOnlyCollection(Of CPersona)
Get
Return _Personas.AsReadOnly
End Get
End Property

Ahora solo admitira el cambio de algn campo, ya que eso no podremos evitarlo de ninguna
forma:
miGrupo.PersonasSoloLect = New List(Of CPersona) ' ERROR DE COMPILACIN, Es una
propiedad de solo lectura

Si buscamos el mtodo Add, veremos que ni siquiera lo tiene, es decir, no se puede escribir
miGrupo.PersonasSoloLect.Add
miGrupo.PersonasSoloLect(0).Nombre = "Mara" ' Permitido, y como en todos los
casos, cambia el nombre a la primera persona

Si esto lo quisiramos hacer con un ArrayList, sera:


Private _PersonasAList As New ArrayList ' ArrayList que contiene a una serie de
personas (aunque en realidad admite cualquier tipo de Object)
Public ReadOnly Property PersonasAListRO As ArrayList ' Devuelve la coleccin no
permitiendo Add, ... aunque s permite modificar las propiedades de un elemento
TryCast(miGrupo.PersonasAListRo(0), CPersona).Nombre = "Nuevo nombre"
Get
Return ArrayList.ReadOnly(_PersonasAList)
End Get
End Property

Ahora solo admitira el cambio de algn campo, aunque tengamos los mtodos:
miGrupo.PersonasAListRO.Add(New Persona()) ' ERROR DE EJECUCIN, no permite usar
los mtodos que cambien la coleccin entera
miGrupo.PersonasAList = otraLista ' ERROR DE EJECUCIN, al igual que en el caso
anterior, pues no tiene el Set de la proiedad
TryCast(miGrupo.PersonasAlistRO(0), CPersona).Nombre = "Mara" ' Permitido, y
como en todos los casos, cambia el nombre a la primera persona

Dictionary (Of TKey, TValue)


La clase genrica Dictionary <(Of <(TKey, TValue >)>) proporciona una asignacin de un
conjunto de claves a un conjunto de valores. Cada elemento que se agrega al diccionario est
compuesto de un valor y su clave asociada.Recuperar un valor utilizando su clave es muy
rpido, cerca de O(1), porque la clase Dictionary <(Of <(TKey, TValue >)>) se implementa
como una tabla hash.

VB.Net (Cap 7. Arrays y Colecciones)

Pg. 140

Desarrollo de Aplicaciones Multiplataforma

Cap 8. Herencia
Se trata de la caracterstica ms importante de la OOP, y establece que partiendo de una clase
a la que denominamos clase base, padre o superclase, creamos una nueva clase denominada
clase derivada, hija, o subclase. En esta clase derivada dispondremos de todo el cdigo de la
clase base, ms el nuevo cdigo propio de la clase hija, que escribamos para extender sus
funcionalidades.
A su vez podemos tomar una clase derivada, creando una nueva subclase a partir de ella, y
as sucesivamente, componiendo lo que se denomina una jerarqua de clases, que explicaremos
seguidamente.
Existen dos tipos de herencia: simple y mltiple. La herencia simple es aquella en la que
creamos una clase derivada a partir de una sola clase base, mientras que la herencia mltiple nos
permite crear una clase derivada a partir de varias clases base. El entorno de .NET Framework
slo permite utilizar herencia simple.
Un ejemplo sera disponer de nuestra ya conocida clase Persona. Si intentamos definir una
nueva clase Empleado indicando que hereda de la clase Persona, ya que todo empleado es, por
supuesto, una persona. En esta nueva clase tendramos que aadir las nuevas propiedades y
mtodos que le confieren en empleado: Ejemplo FechaEntrada, Sueldo, mientras que el
Nombre, FechaNacimiento, ya lo tendra por el mero hecho de de haber heredado de
Persona.

Jerarquas de clases
Uno de los fines de la OOP consiste en la clasificacin del cdigo; para ello se emplean
jerarquas o rboles de clases, en los que a base de niveles, se muestra un conjunto de clases
conectadas por una relacin de herencia como podra verse en la siguiente figura:

En esta representacin de ejemplo, como nivel superior de la jerarqua o clase base estara
Medios de transporte, de la que se derivaran las clases Barco, Tren, Automvil, y a su

vez, de estas ltimas, partiran nuevas clases hijas.


En el momento de declarar una clase derivada, y sin haber escrito ms cdigo, ya tenemos
acceso a todos los miembros de la clase base; posteriormente, podemos escribir cdigo
adicional en la clase derivada para ampliar sus funcionalidades.
Para crear una clase derivada, debemos declarar una nueva clase, especificando cul es su
clase base mediante la palabra clave Inherits. En el siguiente cdigo se muestran los dos
modos disponibles de crear una clase heredada.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 141

Desarrollo de Aplicaciones Multiplataforma

' crear clase derivada en dos lneas


Public Class Profed
Inherits Persona
Public Class Profe : Inherits Persona ' ' crear clase derivada en una sola lnea
con los : de continuacin

Una vez que creemos la clase derivada, tendremos a nuestra disposicin todos los elementos
de la clase base, tanto desde la propia clase, como desde el cdigo cliente.
Public Class Profe : Inherits Persona
Private _Sueldo As Decimal
Public Property Sueldo() As Decimal
Get
Return _Sueldo
End Get
Set(ByVal value As Decimal)
If value < 500 Then
Throw New Exception("No puede ser inferior a 500")
End If
_Sueldo = Sueldo
End Set
End Property
End Class

Supongamos que le definimos una nica propiedad Sueldo.


Sin embargo sucede al instanciar un objeto de la clase podremos hacer referencia a Nombre
y FechaNacimiento ya que al heredar de Persona, no se necesita crear de nuevo dichas
propiedades, sino que reutilizaremos las existentes en la clase base.
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
Try
Dim pr As New Profe
Dim prNombre As Persona.NombreCompleto
prNombre.Apellido1 = txtApellido1.Text
prNombre.Apellido2 = txtApellido2.Text
prNombre.Nom = txtNom.Text
pr.Nombre = prNombre
pr.FechaNacimiento = txtFechaNacimiento.Text
pr.Sueldo = txtSueldo.Text
Profes.Add(pr)
Mostrar()
Catch ex As Exception
MessageBox.Show(ex.Message, "Error de entrada")
End Try
End Sub

Todas las clases necesitan una clase base


El diseo del CLR dicta como norma que toda clase creada necesita heredar de una clase
base. Esto puede resultar un tanto confuso al principio, ya que en los ejemplos con la clase
Persona, no hemos heredado, al menos aparentemente, de ninguna clase.
Cuando creamos una nueva clase, si en ella no establecemos una relacin explcita de
herencia con otra clase, el CLR internamente la crear haciendo que herede de la clase
Object, que se encuentra en el espacio de nombres System. Esto es debido a que el tipo de
herencia en .NET Framework es simple, y en la jerarqua de clases de la plataforma, Object es la
clase base, a partir de la cul, se deriva el resto de clases.
Por este motivo, las siguientes declaraciones seran equivalentes.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 142

Desarrollo de Aplicaciones Multiplataforma

' declaracin normal (se hereda implcitamente de Object)


Public Class Persona
' declaracin heredando explcitamente de Object
Public Class Persona : Inherits System.Object

Reglas de mbito especficas para clases


Las normas de mbito que ya conocemos, establecen que cuando declaramos un miembro de
clase con el modificador de mbito Public, dicho elemento ser accesible por todo el cdigo
de la clase, clases heredadas y cdigo cliente; mientras que si lo declaramos con Private, ese
miembro slo ser accesible por el cdigo de la propia clase.
Adems de estas normas, ya conocidas, disponemos de los modificadores descritos en los
siguientes apartados, diseados para resolver problemas concretos de mbito entre clases.

Protected
Un miembro de clase declarado con este modificador, ser accesible desde el cdigo de su
propia clase y desde cualquier clase heredada, pero no desde una instancia del objeto. El
siguiente cdigo muestra un ejemplo del uso de Protected. Supongamos que en la clase Persona
definimos la siguiente propiedad:
Protected ReadOnly Property Apellidos() ' En Persona
Get
Return Nombre.Apellido1 & " " & Nombre.Apellido2
End Get
End Property

En la clase Persona podramos usarla, como se puede apreciar en el Throw de Sueldo.


Public Property Sueldo() As Decimal
Get
Return _Sueldo
End Get
Set(ByVal value As Decimal)
If value < 500 Then
Throw New Exception("El sueldo de " & Me.Apellidos & " no puede ser
inferior a 500")
End If
_Sueldo = Sueldo
End Set
End Property

Sin embargo si intentamos instanciar una variable de la clase Profe (o Persona, da igual), no
podramos acceder a dicha propiedad.
Dim pr As Profe, per As Persona
MessageBox.Show(pr.Apellidos) ' Imposible, no tiene esta propiedad

Friend
Un miembro de clase declarado con este modificador, ser accesible por todo el cdigo de su
proyecto o ensamblado. Es decir, si tenemos la clase y su uso en el mismo proyecto, equivaldra
a Public, pero si la clase est en una DLL, se considerara como privada, puesto que no
podramos acceder a ella.
Aunque hemos descrito su modo de manejo a travs de clases, la palabra clave Friend
tambin puede ser utilizada como modificador de mbito para variables y procedimientos
situados en mdulos de cdigo. (En este caso recuerda que importbamos la clase con
Imports).

Visual Basic.Net (Cap. 8 Herencia)

Pg. 143

Desarrollo de Aplicaciones Multiplataforma

Protected Friend
Los miembros de clase declarados al mismo tiempo con Protected y Friend, obtendrn una
combinacin de ambos modificadores; por lo tanto, sern accesibles desde el cdigo de su clase,
clases derivadas, y por todo el cdigo que se encuentre dentro de su ensamblado

Herencia y sobrecarga de mtodos


Podemos sobrecargar mtodos existentes en una clase base dentro de una clase derivada,
para ello simplemente escribimos la implementacin del mtodo sobrecargado utilizando la
palabra clave Overloads, tal y como ya conocemos.
Supongamos que queremos redefinir la propiedad Edad de Persona, pero ahora pasndole
una fecha como parmetro (para poder saber la edad en fechas diferentes).
Public Overloads Function Edad() As Integer ' En Persona
If _fechaNacimiento = #12:00:00 AM# Then
Throw New Exception("No conoce la fecha de nacimiento")
End If
Edad = Today.Year - _fechaNacimiento.Year
If Today.Month < _fechaNacimiento.Month Or (Today.Month =
_fechaNacimiento.Month And Today.Day < _fechaNacimiento.Day) Then
Edad -= 1
End If
End Function

Podramos definir una nueva Edad en Profe como se muestra en el siguiente cdigo.
Observa que para que reconozca la variable _fechaNacimiento declarada en Persona, deber
tener un mbito de Protected, para que desde el programa no se pueda acceder a ella pero si
desde su clase derivada.
Public Overloads Function Edad(ByVal fecha As Date) As Integer
If _fechaNacimiento = #12:00:00 AM# Then ' _fechaNacimiento est declarada
Protected en Persona
Throw New Exception("No conoce la fecha de nacimiento")
End If
Edad = fecha.Year - _fechaNacimiento.Year
If fecha.Month < _fechaNacimiento.Month Or (fecha.Month =
_fechaNacimiento.Month And fecha.Day < _fechaNacimiento.Day) Then
Edad -= 1
End If
End Function

Herencia y sobre-escritura de mtodos


Esta tcnica consiste en la capacidad de crear, en una clase derivada, un mtodo que altere
parcial o totalmente, la implementacin ya existente de dicho mtodo en la clase base. Una de
las diferencias existentes con la sobrecarga de mtodos, estriba en que al sobrescribir, el mtodo
en la subclase puede tener el mismo nombre y lista de parmetros que el ya existente en la clase
padre. Podemos sobrescribir tanto mtodos como propiedades.
Para indicar en la clase base que un mtodo podr ser sobrescrito en una subclase, debemos
declarar dicho mtodo utilizando la palabra clave Overridable. Posteriormente, cuando en
una clase derivada queramos rescribir el mtodo de la clase base, lo declararemos empleando la
palabra clave Overrides.
Podemos deducir por lo tanto, que la reescritura de mtodos es un proceso que se debe
realizar con el consentimiento previo de la clase base.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 144

Desarrollo de Aplicaciones Multiplataforma

Supongamos por ejemplo, que para que una persona pueda trabajar, obligatoriamente debe
tener una edad superior a 16 aos. Si modificamos la propiedad FechaNacimiento en la clase
Persona en la forma.
Public Overridable Property FechaNacimiento() As Date
' Overridable para que se pueda reescribir
Get
Return _fechaNacimiento
End Get
Set(ByVal value As Date)
If DateDiff(DateInterval.Day, value, Today) < 0 Then
Throw New Exception("La fecha de nacimiento no puede ser superior a
la actual")
End If
_fechaNacimiento = value
End Set
End Property

En la clase Profe podramos poner:


Public Overrides Property FechaNacimiento() As Date ' Overrides: reescribir la
Overridable
Get
Return _fechaNacimiento
End Get
Set(ByVal value As Date)
_fechaNacimiento = value ' Para que pueda calcular la Edad
If Edad() < 16 Then
_fechaNacimiento = #12:00:00 AM#
Throw New Exception("Para trabajar la edad debe ser minimo 16")
End If
End Set
End Property

MyBase, acceso a los mtodos de la clase base


Pero, qu sucede si queremos utilizar la implementacin del mtodo base en la clase
derivada?, pues slo necesitamos llamar al mtodo de la clase padre usando la palabra clave
MyBase.
Ejemplo:
Supongamos que en la clase Profe usamos un mtodo para calcular el sueldo, en la forma:
Public Class Profe
Protected _Salario As Decimal ' Para que se pueda usar en derivadas
Public Overridable Function Salario() As Decimal
' Aqu hara los clculos oportunos para calcular el salario de cualquier
empleado
Return _Salario
End Function
End Class

Pero adems usamos otra clase Cargo que deriva de la anterior, y que su salario se calcula
en base al anterior pero aadiendo un plus dependiendo del tipo de cargo. El nuevo mtodo
quedara:
Public Class Cargo : Inherits Profe
Public Overrides Function Salario() As Decimal
' Se basa en el de su clase base
_Salario = MyBase.Salario
_Salario += _Plus(_tipoCargo)
Return _Salario
End Function

Visual Basic.Net (Cap. 8 Herencia)

Pg. 145

Desarrollo de Aplicaciones Multiplataforma

Debido a cuestiones de diseo, en algunas ocasiones precisaremos que al mismo tiempo que
sobrescribimos un miembro dentro de una clase heredada, dicho miembro no pueda ser
sobrescrito por las clases que hereden de esta. En estas situaciones, al declarar el miembro,
usaremos la palabra clave NotOverridable.
Si mantenemos el ejemplo anterior, supongamos que an podemos tener otras clases que
siguen heredando de la anterior, pero no queremos que estas puedan modificar ya la forma de
calcular el salario, en ese caso la definicin habra sido:
Public Class Cargo : Inherits Profe
Public NotOverridable Overrides Function Salario() As Decimal

Por lo que la siguiente declaracin sera errnea:


Public Class Direccion : Inherits Cargo
Public Overrides Function Salario() As Decimal
' ERROR, no se puede reescribir el mtodo ya que Cargo lo impide con el
NotOverridable

No podemos utilizar NotOverridable en mtodos de una clase base, ya que la misin de


este modificador es impedir la sobre-escritura de miembros en clases derivadas, pero desde una
clase que a su vez tambin ha sido derivada desde la clase base. Si no queremos, en una clase
base, que un mtodo pueda ser sobrescrito, simplemente no utilizamos en su declaracin la
palabra clave Overridable.

Herencia y mtodos constructores


Podemos crear una clase base que implemente un constructor y una subclase sin l. En esta
situacin, cuando instanciemos un objeto de la subclase, se llamar implcitamente al
constructor de la clase base para ejecutar el cdigo de inicializacin. Tambin es posible crear el
constructor slo en la clase derivada.
Si ambas clases disponen de un constructor, en primer lugar se ejecutar el constructor de la
clase base y despus el de la clase derivada. Realmente, el primer constructor ejecutado
corresponde a la clase Object, y sucesivamente, se irn ejecutando todos los constructores de la
jerarqua de clases hasta llegar a la clase que origin la llamada.
El problema sobreviene cuando en la clase base creamos un constructor parametrizado, ya
que ello obliga a sus clases derivadas a crear tambin un mtodo constructor dentro del cul se
haga una llamada al constructor de la clase base. Para llamar explcitamente a un mtodo de la
clase base desde una subclase utilizaremos la palabra clave MyBase, que contiene una
referencia hacia la clase padre.
Veamos un ejemplo. Supongamos que en nuestra clase Persona solo tenemos el siguiente
constructor parametrizado:
Public Class Persona

' nico Constructor:


Public Sub New(ByVal nombre As NombreCompleto, ByVal fNac As Date)
Me.Nombre = nombre
Me.FechaNacimiento = fechaNac
End Sub

End Class

Si luego en Profe no ponemos constructor nos aparecer un mensaje de compilacin como


el que se puede apreciar en la siguiente figura (La clase Profe debe declarar un Sub New porque
su clase base Persona no dispone de un Sub New accesible al que se pueda llamar sin
argumentos).

Visual Basic.Net (Cap. 8 Herencia)

Pg. 146

Desarrollo de Aplicaciones Multiplataforma

Si ahora intentamos declarar un constructor en la clase derivada nos muestra un mensaje


como el que se ve abajo, es decir, que la primera instruccin de este Sub New debe ser una
llamada a MyBase.New porque la clase base Persona de Profe no tiene un Sub New accesible
que se pueda llamar sin argumentos.

Un ejemplo sera:
Public Class Profe : Inherits Persona
Public Sub New(ByVal nombre As NombreCompleto, _
ByVal fechaNac As Date, ByVal sueldo As Decimal)
MyBase.New(nombre, fechaNac)
Me.Sueldo = sueldo
End Sub

Podemos no obstante, evitar la obligacin de escribir un constructor en la clase derivada, si


en la clase padre creamos un constructor sin parmetros, incluso aunque est vaco en la forma:
Public Sub New()

' En la clase Persona

End Sub

Finalmente, debemos apuntar dos reglas que debe cumplir todo mtodo constructor de una
subclase que llame al constructor de su clase base: en primer lugar, el constructor base debe ser
llamado en la primera lnea del constructor derivado; en segundo lugar, el constructor base slo
puede ser llamado una vez desde el constructor derivado.

Clases selladas o no heredables


Toda clase que declaremos en nuestro cdigo es heredable por defecto. Si no queremos que
nuestra clase pueda ser heredada por otras, debemos declararla de forma que no permita
herencia; a este tipo de clase se le denomina clase no heredable o sellada (sealed).
Para definir una clase no heredable, debemos utilizar la palabra clave NotInheritable
en el momento de su declaracin.
En la siguiente figura hemos creado la clase Fichero como no NotInheritable, por ello,
cuando a continuacin declaramos la clase FiTexto e intentamos que herede de Fichero, se
mostrar un mensaje de error en el editor de cdigo, indicndonos que no es posible establecer
esta relacin de herencia puesto que Fichero es una clase sellada.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 147

Desarrollo de Aplicaciones Multiplataforma

Clases abstractas o no instanciables


Una clase abstracta es aquella que no permite la instanciacin directa de objetos a partir de
ella, siendo necesaria una clase derivada para acceder a sus miembros. Una clase concreta es el
tipo de clase que venimos utilizando hasta el momento, desde la cul, podemos instanciar
objetos.
Aunque en una clase abstracta podemos escribir un mtodo constructor, slo ser accesible
desde el constructor de la subclase.
Para definir una clase abstracta utilizaremos la palabra clave MustInherit en el momento
de su declaracin.
Ejemplo:
Public MustInherit Class Persona

Por lo que si intentamos declarar una variable de la clase Persona el propio compilador nos
indicar el siguiente mensaje de error:

Dentro de una clase abstracta podemos implementar propiedades y mtodos, en la forma que
hemos visto hasta el momento. Adicionalmente, podemos obligar a que determinados miembros
sean sobrescritos por la clase heredada; son los denominados miembros abstractos, y se
declaran usando la palabra clave MustOverride, como vemos en el siguiente cdigo:
Public MustInherit Class Persona
' mtodo abstracto: Este mtodo debe ser sobrescrito por la clase derivada
' En este caso solo escribimos la cabecera, sin cdigo
Public MustOverride Sub MesesActivo()
Public Sub New() ' Resto de miembros...

Y en la clase derivada haramos:


Public Class Profe : Inherits Persona
' en esta clase sobrescribimos este mtodo declarado como abstracto en la
clase abstracta
Public Overrides Sub MesesActivo()
' Aqu S escribiramos el cdigo deseadO
End Sub
End Class

Debemos tener en cuenta que los miembros abstractos slo tienen sentido si son declarados
en clases abstractas. Por tal motivo, slo podremos crear mtodos con MustOverride en clases
que hayan sido definidas como MustInherit.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 148

Desarrollo de Aplicaciones Multiplataforma

Resumiendo
Toda clase creada hereda de una clase base. Aunque no se haga explcito, todas heredan de la
primera clase: Object, que se encuentra en el espacio de nombres System, es decir,
implcitamente es como si pusisemos: Inherits System.Object
La herencia nos permite la reuntilizacin de cdigo.
Palabras clave de la CLASE BASE (aparecen delante de Class)
Por defecto todas pueden ser heredadas y sus miembros no redefinidos. Para cambiar estos
comportamientos tenemos:
NotInheritable: Clase sellada o no heredable. La clase no puede ser heredada. Ejem: Los
tipos de datos base, no se puede heredar de Integer. Ejemplo la clase Array: no se puede
heredar.
MustInherit: Clase abstracta o no instanciable. Debe ser obligatoriamente heredada para
poder acceder a sus miembros. Aunque tenga mtodo constructor solo ser accesible
desde la clase derivada.
Palabra clave de la CLASE DERIVADA (Debe ser la primera lnea)
Inherits: Hereda de otra clase existente.
Palabra clave de los MIEMBROS de la clase BASE (aparecen delante del nombre del
miembro)
Overridable: Puede ser redefinido. Si se define Public no puede ser redefinido.
NotOverridable: No puede ser sobrescrito por las clases heredadas. Esto ser cuando sea
un miembro que estamos rescribiendo. Ejemplo: Tenemos una clase derivada que
sobrescribe el mtodo Sueldo
Public NotOverridable Overrides Function Sueldo As Decimal
MustOverride: Debe ser obligatoriamente sustituido.
El mbito de las variables o miembros puede ser:
Public: Se puede acceder desde cualquier aplicacin que utilice la clase.
Private: Se puede acceder a ese miembro solo desde el mdulo en que es declarado.
Todas las variables locales deben serlo, y ninguna otra clase (ni las derivadas) o
aplicaciones podrn verlas.
Protected: Los miembros protegidos tienen mbito pblico y privado, ya que se puede
acceder a ellos en la clase derivada, pero no en las aplicaciones que utilicen estas clases.
En la clase derivada tiene un mbito privado.
Friend: Es accesible por todo el cdigo del proyecto o ensamblado.
Protected Friend: Combinacin de los dos anteriores. El miembro est disponible para la
propia clase, para las que heredan de ella y para cualquier otro componente del mismo
ensamblado (pero no si se usa la clase en otros proyectos).
Palabras clave de los MIEMBROS de clase DERIVADA
Overrides: (Sobre-escritura de miembros) Indica que el miembro de la clase derivada
sustituye al de la clase base. No se puede usar para aquellos miembros que fueron
declarados NotOverridable o Protected en la clase base. Es decir, el nuevo miembro altera
parcial o totalmente la implementacin existente del mismo miembro en la clase base. En
este caso, el sobrescrito puede tener absolutamente la misma apariencia que el que
sobrescribe.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 149

Desarrollo de Aplicaciones Multiplataforma

Otras palabras clave que pueden estar en cualquier clase:


Overloads: Permite la sobrecarga de un miembro, para permitir que un mismo miembro
trabaje con tipos de datos o parmetros diferentes. Puede estar en cualquier miembro que
se desee sobrecargar, tanto en clases padre como en las derivadas.
Hay ocasiones en que deberemos unir varias de estas palabras. Ejemplo:
Public Overridable Overloads Sub Prestar() Indicara que este mtodo
podemos sobrescribirlo y sobrecargarlo.
MyBase: Hace referencia a la clase base
MyClass y Me: Hace referencia a la propia clase.
Herencia y mtodos constructores
Podemos crear las clases con o sin constructores, e incluso con constructores en solo una de
ellas.
Si la clase base tiene constructor y la derivada no, se llamar implcitamente al constructor
de la clase base para ejecutar el cdigo de inicializacin.
Si lo tenemos en ambas, primero se ejecutar el de la clase base y despus el de la derivada.
Si en la clase base creamos un constructor parametrizado, las derivadas estarn obligadas a
crear tambien un constructor dentro del cul se haga una llamada al constructor de la clase
base. Recuerda que para llamar explcitamente a un mtodo de la clase base usaremos
MyBase.
Si no queremos obligar a que se escriba un constructor en la clase derivada, crearemos un
constructor sin parmetros en la clase base (aunque no le escribamos cdigo).
Si en un constructor de la clase derivada llamamos al constructor de la clase base
(generalmente ser as), esta llamada ser la primera lnea del constructor derivado.

Visual Basic.Net (Cap. 8 Herencia)

Pg. 150

Desarrollo de Aplicaciones Multiplataforma

Cap 9. Eventos en .NET


Cindonos al mbito de la programacin, un evento es, dentro de una aplicacin, una
notificacin lanzada por un objeto, que podr ser respondida por aquellos otros objetos
interesados en darle soporte.

Un escenario de trabajo sin eventos


Supongamos que nos encargan desarrollar una clase llamada Empleado, entre cuyos
miembros tenemos la propiedad Sueldo. Uno de los requerimientos respecto a esta propiedad es
que su valor se debe encontrar entre 1000 y 4000; por ello, en su procedimiento Property,
realizamos una validacin a tal efecto, lanzando, como venimos haciendo hasta ahora, un
mensaje cuando el sueldo que asignemos sea errneo.
Public Class Empleado
' variables de propiedad
Private mNombre As String
Private mSueldo As Double
Public Property Nombre() As String
Get
Return mNombre
End Get
Set(ByVal Value As String)
mNombre = Value
End Set
End Property
Public Property Sueldo() As Double
Get
Return mSueldo
End Get
Set(ByVal Value As Double)
If Value < 1000 Or Value > 4000 Then
Throw New Exception("Asignacin de sueldo incorrecta")
End If
mSueldo = Value
End Set
End Property
End Class

Programacin basada en eventos


La aparicin de Windows trajo consigo un nuevo esquema en el desarrollo de aplicaciones.
En un programa que se ejecute dentro de un sistema basado en eventos como pueda ser
Windows, se estn produciendo constantemente eventos (sucesos), provocados por las acciones
del usuario o por el propio sistema. Tan elevado es el nmero de eventos que se producen, que
dar respuesta a todos, es decir, codificar todas aquellas situaciones que acontecen a lo largo de
la ejecucin de un programa, es algo impensable.
Por tal motivo, la tcnica seguida al escribir cdigo orientado a eventos, se basa en codificar
slo los eventos que nos interese tratar, ya que para el resto, ser el propio sistema quien
proporcione el comportamiento por defecto.
En una aplicacin Windows tpica, todos los elementos que forman parte de la misma, es
decir, el propio formulario y los controles contenidos en l, lanzan eventos en respuesta a las
acciones del usuario o usuaria. El ejemplo ms habitual: al pulsar un botn, se produce su
evento clic; si queremos que el programa realice alguna accin al pulsar dicho botn, deberemos
escribir cdigo en el procedimiento

Visual Basic.Net (Cap 9. Eventos)

Pg. 151

Desarrollo de Aplicaciones Multiplataforma

Esquema bsico de un sistema orientado a eventos


Un sistema conducido por eventos basa su funcionamiento en dos pilares fundamentales: un
emisor y un receptor de eventos.
El emisor genera y lanza el evento al sistema, mientras que el receptor, si est interesado en
tratar el evento lanzado, lo captura y le da respuesta. Si un objeto receptor no necesita gestionar
eventos, simplemente no lo obtiene. Ver figura:

El emisor de eventos
Un emisor de eventos, tambin denominado origen de eventos (event source o event sender),
es un objeto capacitado para generar y lanzar eventos al sistema, que puedan ser recuperados
por otros objetos preparados para realizar su tratamiento.
Para que un objeto pueda desencadenar eventos, en su clase debemos realizar dos tareas:
Declarar el propio evento usando la palabra clave Event, especificando si es necesario una
lista de parmetros que acompaan al evento.
Lanzar el evento mediante la palabra clave RaiseEvent, seguida del nombre del evento. Si
lo hemos declarado con parmetros, deberemos aadir los valores para cada uno de los
parmetros en el mismo orden en el que los hemos declarado.
Situndonos pues ante el problema planteado por la clase Empleado en un apartado anterior,
la solucin que proponemos consistir en generar desde la clase Empleado un evento cuando se
produzca un fallo en la validacin del sueldo. De esta manera, el cdigo cliente que lo necesite,
responder al evento; y el que no lo precise, har caso omiso del evento lanzado.
En primer lugar, declaramos en la zona de declaraciones de la clase el evento LimiteSueldo,
que ir acompaado de un parmetro que nos informar del importe errneo que se intentaba
asignar a la propiedad.
A continuacin, en la propiedad Sueldo, cuando detectemos que el sueldo sobrepasa el valor
permitido, en lugar de lanzar el error, generaremos el evento LimiteSueldo, que podr ser
recuperado por el cdigo cliente que haga uso de la clase, actuando como necesite en cada
ocasin. Observa, que al mismo tiempo que lanzamos el evento, le pasamos el importe del
sueldo que se intentaba asignar. Veamos el siguiente cdigo:

Visual Basic.Net (Cap 9. Eventos)

Pg. 152

Desarrollo de Aplicaciones Multiplataforma

Public Class Empleado


' variables de propiedad
Private mNombre As String
Private mSueldo As Double
' declaramos el evento

Public Event LimiteSueldo(ByVal importe As Double)


Public Property Nombre() As String
Get
Return mNombre
End Get
Set(ByVal Value As String)
mNombre = Value
End Set
End Property
Public Property Sueldo() As Double
Get
Return mSueldo
End Get
Set(ByVal Value As Double)
If Value < 1000 Or Value > 4000 Then
' Lanzamos el evento, y le pasamos como parmetro informativo el valor
incorrecto que intentba asignar

RaiseEvent LimiteSueldo(Value)
End If
mSueldo = Value
End Set
End Property
End Class

Con estas modificaciones sobre la clase Empleado, ya tenemos listo nuestro emisor de
eventos. Queda ahora por completar la parte que captura los eventos lanzados por el emisor.

El receptor de eventos
Un receptor de eventos, tambin denominado manipulador de eventos (event receiver o event
handler), es aquella parte del cdigo cliente, que configuramos para que sea capaz de recibir los
eventos generados por un objeto emisor. Para que ambos elementos, en este canal de
comunicacinque es la transmisin de eventos puedan operar, es necesario conectarlos.

Conexin de un emisor de eventos con un manipulador de


eventos
Como ya sabemos existen dos medios para comunicar un evento con un manipulador de
eventos:
En tiempo de compilacin, realizando un enlace esttico entre la clase y el manipulador
mediante las palabras clave WithEvents y Handles. Esta tcnica tiene la ventaja de que
permite escribir un cdigo mucho ms legible, en cuanto a la manipulacin de eventos se
refiere.
En tiempo de ejecucin, realizando un enlace dinmico entre la clase y el manipulador
mediante la palabra clave AddHandler. La ventaja en este caso, es que podemos asociar
procedimientos manipuladores de evento dinmicamente durante el transcurso de la
ejecucin del programa.

Visual Basic.Net (Cap 9. Eventos)

Pg. 153

Desarrollo de Aplicaciones Multiplataforma

Enlace esttico de eventos


Este es el modo ms sencillo para implementar la conexin entre un evento y un
procedimiento manipulador de evento.
En primer lugar, declaramos una variable del tipo de objeto cuyos eventos queremos
capturar, en la zona de declaraciones del mdulo, clase, etc., utilizando la palabra clave
WithEvents. Veamos el siguiente cdigo:
Public WithEvents mEmple As Empleado

A continuacin, tenemos que escribir el procedimiento manipulador, que ser invocado cada
vez que se dispare el evento. Dicho procedimiento debe ser de tipo Sub, ya que un evento no
puede devolver valores, por lo que no podremos utilizar un Function; tambin debemos finalizar
su declaracin con la palabra clave Handles, seguida del nombre de la variable del objeto que
hemos declarado en la zona de declaraciones, y el nombre del evento que el procedimiento va a
tratar. En el Cdigo fuente, el procedimiento mEmple_LimiteSueldo( ), ser llamado cada vez
que se produzca el evento LimiteSueldo en el objeto Empleado.
Private Sub mEmple_LimiteSueldo(ByVal importe As Double)

Handles

mEmple.LimiteSueldo
MessageBox.Show("Error en el sueldo " & importe & " que se quiere asignar
a " & mEmple.Nombre)
End Sub

Como siempre, el nombre utilizado para el procedimiento puede ser cualquiera, aunque
generalmente usaremos la convencin NombreObjeto_NombreEvento para facilitar la lectura
del cdigo, aunque ya sabemos que podramos haber empleado otro, como se muestra en el
siguiente cdigo fuente:
Public Sub Sobrepasado(ByVal importe As Double) Handles mEmple.LimiteSueldo

Y como en el resto de controles y sus eventos, podemos utilizar el editor de cdigo de


VS.NET, para facilitar la creacin de los procedimientos manipuladores de evento, abriendo la
lista Nombre de clase y seleccionar el nombre de la variable que hemos declarado WithEvents.

El enlace esttico tiene el inconveniente que la variable objeto de la cual deseamos


manipular sus eventos debemos declararla en la zona de declaraciones del mdulo en el que
furamos a utilizarlo (no puede ser local a un procedimiento o funcin ni global de otro
mdulo).

Enlace dinmico de eventos


Siendo un poco ms complejo a nivel sintctico que el enlace esttico, el enlace dinmico de
eventos a sus correspondientes manipuladores, tiene la ventaja de que nos permite asociar el
mismo evento a diferentes procedimientos manipuladores de dicho evento, durante el transcurso
de la ejecucin del programa, y sobre todo que el objeto sobre el que vamos a manipular sus
eventos podemos declararlo tanto a nivel local como en la zona de declaraciones, a diferencia
del enlace esttico, que nos obligaba a declarar el objeto en la zona de declaraciones del
mdulo en el que furamos a utilizarlo, y que en este caso no hace falta la palabra WithEvents.
' manipulador de evento que conectaremos en tiempo de ejecucin
Private Sub Error_Sueldo(ByVal importe As Double)
MessageBox.Show("Error al introducir el sueldo " & importe)
End Sub

Visual Basic.Net (Cap 9. Eventos)

Pg. 154

Desarrollo de Aplicaciones Multiplataforma

Para establecer un enlace dinmico entre un evento y un manipulador, utilizaremos la forma


ya conocida AddHandler. Esta instruccin, recibe como primer parmetro el evento a conectar
en el formato NombreObjeto.NombreEvento. Como segundo parmetro, pasaremos la direccin
de entrada al procedimiento que deber ejecutar el evento, y que obtenemos a travs de la
instruccin AddressOf. El siguiente ejemplo, muestra un procedimiento, en el que recogemos de
una caja de texto un nmero, y segn el valor obtenido, conectamos el evento con uno de los
dos procedimientos manipuladores antes descritos.
Private Sub btnAceptar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnAceptar.Click
miEmpleGlobal = New Empleado ' Variable declarada como Public en Mdulo
(no en este formulario)
Dim emple As New Empleado ' Variable local
AddHandler miEmpleGlobal.LimiteSueldo, AddressOf Error_Sueldo
AddHandler emple.LimiteSueldo, AddressOf Error_Sueldo
miEmpleGlobal.Sueldo = 200 ' Ambas provocaran el evento y por tanto
mostraran el mensaje de error
emple.Sueldo = 250
End Sub

La clase EventArgs, o cmo obtener informacin del objeto


emisor del evento
En los ejemplos sobre captura de eventos realizados hasta ahora con la clase Empleado,
dentro de los procedimientos manipuladores de evento, no disponemos de acceso a los
miembros del objeto que ha originado el evento.
El nico modo de los vistos hasta ahora de conseguir tal acceso, es declarar el objeto en la
zona de declaraciones del mdulo y, en ese caso, al tener visibilidad sobre la variable del objeto
en todos los procedimientos del mdulo, s podramos manejar el objeto.
Sin embargo, qu ocurre cuando instanciamos un objeto Empleado con mbito local en un
subprograma, y asociamos sus manipuladores de evento con AddHandler?. Simplemente, que
desde dichos procedimientos manipuladores de evento, no podemos obtener informacin del
objeto Empleado para, por ejemplo, recuperar el valor de la propiedad Nombre.
Una solucin simple, pero no eficaz, consistira en pasar la/s propiedad/es como parmetro
cuando lanzamos el evento, es decir, deberamos cambiar el evento y su lanzamiento de la clase
Empleado, como se puede apreciar en el siguiente cdigo.
Public Class Empleado
Public Event LimiteSueldo(ByVal importe As Double, ByVal nombre As String)
Public Property Sueldo() As Double
' Get
Set(ByVal Value As Double)
If Value < 1000 Or Value > 4000 Then
RaiseEvent LimiteSueldo(Value, Me.Nombre)
End If
mSueldo = Value
End Set
End Property

En este caso nuestro subprograma orientado al evento podra ser:


Private Sub Error_LimiteSueldo(ByVal importe As Double,ByVal nombre As String)
MessageBox.Show("Error en el sueldo " & importe)
End Sub

Pero seguiramos limitados, en el caso de que necesitramos pasar cualquier otro tipo de
informacin que no estuviera directamente relacionada con el objeto.
Para solucionar este problema, podemos utilizar la tcnica empleada por la propia plataforma
.NET en la retransmisin de eventos, y que explicamos a continuacin. La jerarqua de clases de

Visual Basic.Net (Cap 9. Eventos)

Pg. 155

Desarrollo de Aplicaciones Multiplataforma

.NET dispone de la clase EventArgs, diseada para guardar la informacin adicional que
pasamos a un procedimiento manipulador de evento.
Podemos crear una clase que herede de EventArgs, y adaptarla, en este caso, para que
contenga la informacin adicional sobre un evento que se ha producido en la clase Empleado, de
modo que cuando se ejecute su manipulador asociado, pasemos a dicho manipulador, como
primer parmetro, el propio objeto Empleado, y como segundo, un objeto de nuestra clase
EventArgs personalizada, con datos adicionales sobre el evento generado. Este es el esquema
general de trabajo con los eventos en .NET.
Vamos a definir una nueva clase Empleada (semejante a la anterior pero en la que haremos
ciertos cambios), y una segunda clase EmpleadaEventArgs, que hereda de EventArgs, y que
servir para que cuando a un objeto Empleada se le intente asignar un sueldo incorrecto, se
almacene en ella dicho valor errneo. Veamos este ejemplo:
' Clase EmpleadaEventArgs, para guardar informacin sobre los eventos lanzados
por la clase Empleada. Esta clase en concreto, guardar el valor del sueldo
errneo que se ha intentado asignar a una empleada

Public Class EmpleadaEventArgs : Inherits EventArgs


Private mSueldoIntentadoAsig As Double
Public Property SueldoIntentadoAsig() As Double
Get
SueldoIntentadoAsig = mSueldoIntentadoAsig
End Get
Set(ByVal Value As Double)
mSueldoIntentadoAsig = Value
End Set
End Property
End Class

Seguidamente en la nueva clase Empleada, cambiaremos la declaracin del evento


LimiteSueldo, y la seccin Set del procedimiento Property Sueldo:
Public Class Empleada
' Al declarar el evento LimiteSueldo, el primer parmetro ser la instancia
del objeto Empleada actualmente en ejecucin y el segundo parmetro ser un
objeto EmpleadaEventArgs, con la informacin adicional del evento producido

Public Event LimiteSueldo(ByVal sender As Empleada, ByVal e As


EmpleadaEventArgs)
Private mSueldo As Double
Public Property Sueldo() As Double
Get
Return mSueldo
End Get
Set(ByVal Value As Double)
If Value < 1000 Or Value > 4000 Then
' Creamos un objeto EmpleadaEventArgs y le pasamos a sus
propiedades la informacin sobre el evento; en este caso slo pasamos el valor
incorrecto que se intent asignar a la propiedad Sueldo

Dim mEvArgs As New EmpleadaEventArgs()


mEvArgs.SueldoIntentadoAsig = Value
' despus lanzamos el evento y le pasamos como parmetro el
propio objeto Empleada actual y el objeto con la informacin del evento

RaiseEvent LimiteSueldo(Me, mEvArgs)


End If
mSueldo = Value
End Set
End Property
... Resto de propiedades y/o mtodos
End Class

Los nombres empleados en la declaracin del evento de esta clase: sender, para designar al
emisor del evento; y e, para designar los argumentos del evento, no son en absoluto
obligatorios, pudiendo utilizar los nombres que deseemos, pero es ms aconsejable seguir la
misma convencin que utiliza la plataforma.

Visual Basic.Net (Cap 9. Eventos)

Pg. 156

Desarrollo de Aplicaciones Multiplataforma

Para terminar, escribimos en el mdulo un procedimiento manipulador para el evento


LimiteSueldo, y en el proyecto instanciamos un objeto Empleada, asociando el evento del
objeto al manipulador de evento que acabamos de escribir.
Private Sub btnEmpleada_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnEmpleada.Click
' declarar e instanciar un objeto Empleada
Dim mEmpleada As New Empleada
' aadir un manipulador de evento para el evento LimiteSueldo

AddHandler mEmpleada.LimiteSueldo, AddressOf ErrorAsignacionSueldo


mEmpleada.Nombre = "ANA"
mEmpleada.Sueldo = 5000 ' esto provoca el evento
End Sub
' Procedimiento manipulador del evento LimiteSueldo.
' Del parmetro sender obtenemos toda la informacin de la Empleada.
' Del parmetro e obtenemos el importe incorrecto que intentbamos asignar al
sueldo de la empleada

Public Sub ErrorAsignacionSueldo(ByVal sender As Empleada, ByVal e As


EmpleadaEventArgs)
MessageBox.Show ("Se intent asignar a la empleada " & sender.Nombre & " el
sueldo " & e.SueldoIntentadoAsig)
End Sub

Supongamos ahora, que queremos que, adems de informar al usuario de lo que est
ocurriendo, queremos que pueda cancelar el valor a asignar. En este caso nos inventaramos una
nueva propiedad en la clase EmpleadaEventArgs.
Private mCancelar As Boolean
Public Property Cancelar() As Boolean
Get
Return mCancelar
End Get
Set(ByVal value As Boolean)
mCancelar = value
End Set
End Property

Y modificaramos el Set de la propiedad Sueldo en la forma:


Set(ByVal Value As Double)
If Value < 1000 Or Value > 4000 Then
Dim mEvArgs As New EmpleadaEventArgs()
mEvArgs.SueldoIntentadoAsig = Value
RaiseEvent LimiteSueldo(Me, mEvArgs)
' Si el usuario cambiar la propiedad Cancelar, no asignamos el Value.

If mEvArgs.Cancelar Then Exit Property


End If
mSueldo = Value
End Set

El usuario en este caso, hara algo parecido a:


Private Sub ErrorAsignacionSueldo(ByVal sender As Empleada,ByVal e As
EmpleadaEventArgs)
If MessageBox.Show(sender.Nombre & " el sueldo a asignar" & e.ValorAsignado
& " es muy bajo, lo cancelas? ", "Atencin", MessageBoxButtons.YesNo) =
Windows.Forms.DialogResult.Yes Then e.Cancelar = True
End Sub

Este es la forma en que trabajaremos habitualmente para lograr que los eventos de nuestras
clases tengan una estructura semejante al resto de eventos de las clases pertenecientes a la
plataforma.

Visual Basic.Net (Cap 9. Eventos)

Pg. 157

Desarrollo de Aplicaciones Multiplataforma

Cap 10. Ficheros


Clases StreamReader y StreamWriter
Para acceder a ellos tenemos dos clases: StreamReader y StreamWriter.
La Clase StreamReader est diseada para la entrada de caracteres, es decir, para
permitirnos la lectura de ficheros. El archivo a ser ledo puede ser abierto declarando un nuevo
StreemReader al que se le da el nombre de archivo entre parentsis.
Dim fic As New StreamReader("c:\Test.txt")

El fichero debe existir, si no fuese as, el programa produce un error de ejecucin.


Una vez que el reader (lector) tiene asignado un archivo una serie de mtodos stream reader
(flujo de lectura) pueden ser invocados para leer la informacin del mismo, e incluso para
cerrarlo:
Mtodo

Descripcin

Close

Cierra el StreamReader y libera cualquier recurso del sistema asociado al


reader, es decir, cierra el fichero.

ReadLine

Lee una lnea de caracteres del stream actual y devuelve los datos como
String.

ReadToEnd

Lee un stream desde la posicin actual hasta el final del fichero.

Read

Lee el prximo caracter o prximo conjunto de caracteres de la entrada


stream.

EndOfStream Es True si la actual posicin est al final de la secuencia; en caso contrario, es


False. Si leemos una lnea y es la ltima, EndOfStream se pone a True.
Entendiendo por buffer al espacio de memoria diseada para el almacenamiento temporal de
datos.
Para hacer uso de esta clase es prctico incluir mediante Imports la biblioteca de Clase
System.IO al principio del cdigo del formulario (al estilo de las include de C++).
Tambin se puede incluir desde Propiedades de proyecto y seleccionarla en la lista. Si no lo
hacemos
as,
deberemos
escribrilo
continuamente
en
la
forma:
System.IO.StreamReader()).
Ejemplos:
Imports System.IO
Public Class Form1
Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) _ Handles btnCargar.Click
Dim fic As New StreamReader("c:\Test.txt")
txtDatos.Text = fic.ReadToEnd
fic.Close()
End Sub

End Class

Visual Basic.Net (Cap 10. Ficheros)

Pg. 159

Desarrollo de Aplicaciones Multiplataforma

O bien:
Dim fichero As New StreamReader(rutaFichero)
Do Until fichero.EndOfStream
Aqu pregunta por el Fin de Fichero
Dim linea As String = fichero.ReadLine
' la variable linea guarda la lnea del fichero y
'fichero.EndOfStream se pone a True o False dependiendo de si es la ltima o
no
' Aqu pondramos las instrucciones para trabajar con lo ledo en linea
Loop
fichero.Close

Si no queremos usar el mtodo EndOfStream, tambien se puede hacer:


linea = fichero.ReadLine
Do Until linea Is Nothing
' La linea ser Nothing si no ha podido leer nada
' Trabajar con linea para lo que se quiera antes de volver a leer otra
linea = fichero.ReadLine
Loop
fichero.Close()

De la misma forma, la Clase StreamWriter est diseada para la salida de caracteres,


asignando el archivo de escritura mediante la creacin de un nuevo StreamWriter.
Dependiendo de cmo usemos el constructor de esta clase, indicaremos que el fichero se cree
siempre independientemente`n de si exista previamente, o que si existe se coloque al final de
texto para seguir escribiendo y mantener lo ya existente (lgicamente si no existiese tambin se
crea nuevo).
Dim fic As New StreamWriter(nomFichero) Siempre se crea nuevo
Dim fic As New StreamWriter(nomFichero, True) Si existe el fichero lo que
grabemos nuevo se aade al final.
Mtodo
Close
Write
WriteLine
Flush

Descripcin
Cierra el StreamReader y el stream subyacente.
Escribe en el archivo.
Escribe datos tal y como son especificados por los parmetros sobrecargados,
seguidos de una lnea de terminacin, en definitiva, escribe una nueva lnea.
Limpia el buffer para el actual writer y provoca que cualquier dato contenido en
el buffer sea escrito al stream subyacente.

Ejemplo de uso de estos mtodos:


Dim nomFich As String = My.Application.Info.DirectoryPath & \Ejem.txt)
Dim linea As String
Dim fich As New StreamWriter(nomFich)
For Each per As st_Persona In Personas ' Personas sera un array de tipo
st_Persona
fich.WriteLine(per.Nombre & "*" & per.Apellidos)
Next
fich.Close()

Visual Basic.Net (Cap 10. Ficheros)

Pg. 160

Desarrollo de Aplicaciones Multiplataforma

Clase File
Otra forma de trabajar con los ficheros, es utilizando la clase compartida File
(que tambin se encuentra en el espacio de nombres de System.IO) con los siguientes mtodos.
Mtodo

Descripcin

OpenText

Devuelve un objeto StreamReader, que podemos usar para leer en el


archivo pasado como parmetro.

ReadAllLines Abre el fichero de texto, lee todas las lneas y a continuacin lo cierra.
Devuelve un array de string.
CreateText

Devuelve un objeto StreamWriter que nos permite escribir en el archivo


pasado como parmetro.

WriteAllLines Crea un archivo nuevo, escribe en l el array de cadenas pasado como


parmetro y cierra el archivo. Si el fichero exista lo sobreescribe.
WriteAllText Crea un archivo nuevo, escribe la cadena pasada como parmetro y cierra el
archivo. Si el fichero exista lo sobreescribe.
Exists

Devuelve un valor boolean indicando si existe el archivo pasado como


parmetro.

Es decir, las dos instrucciones siguientes seran equivalentes, ambas intentan abrir un
fichero que deber existir previamente.
Dim fic As New StreamReader("c:\Test.txt")
Dim fic As StreamReader = File.OpenText("c:\Test.txt")

En los dos casos, por tanto, solo hemos abierto el archivo, ahora seguiramos trabajando con
l, como en lo comentado anteriormente.
Nota: Si usamos File.CreateText y el archivo especificado no existe se crea, y si existe se
sobrescribe (es decir, siempre se crea de nuevo, no tiene opcin de Append).
Ejemplo:
Dim fich As StreamReader = File.OpenText(nomFichero)
Do While Not fich.EndOfStream
Me.lstDatos.Items.Add(fich.ReadLine)
Loop
fich.Close()

Sin embargo con el mtodo ReadAllLines lo anterior podra quedarse en:


Dim lineas() As String = File.ReadAllLines(nomFichero) ' Abre, lee y cierra
Me.lstDatos.Items.AddRange(lineas) ' Uso el array para lo que quiera, ejemplo
llenar una ListBox

Igualmente, si queremos crear un fichero con datos podemos hacerlo tambin con las
siguientes formas:
Con CreateText:
Dim fichero As StreamWriter = File.CreateText(fich)
' Recuerda que eso equivale a: Dim fichero As New StreamWriter(fich)
For Each per As st_Persona In Personas ' Personas sera un array de tipo
st_Persona
fichero.WriteLine(per.Nombre & "*" & per.Apellidos)
Next
fichero.Close()

Visual Basic.Net (Cap 10. Ficheros)

Pg. 161

Desarrollo de Aplicaciones Multiplataforma

Pero tambin, con los mtodos WriteAllLines y WriteAllText en la forma:


Dim misDatos() As String = {"Mara", "Martn", "Martn",
"maria_martin@cuatrovientos.org"}
File.WriteAllLines(nomFichero, misDatos) ' Abre, escribe esas 4 lneas y lo
cierra.

O(bien)
File.WriteAllText(nomFichero, txtTexto.Text) ' Abre, graba el texto y lo cierra

Pero, qu ocurre con los posibles errores de ejecucin, ejemplo si el fichero no existe? Si
necesito tratar este caso, tenemos, como siempre varias posiblidades:
Usando la instruccin Try que nos detecte el error:
Dim nomFichero As String = My.Application.Info.DirectoryPath & "\Ejemplo.txt"
Try
Dim sr As New StreamReader(nomFichero)
Do Until sr.EndOfStream
Dim linea As String = sr.ReadLine
' Tratamiento de linea
Loop
sr.Close()
Catch ex As FileNotFoundException
' Instrucciones a ejecutar en el caso de que se produzca en concreto el error
de no existir
Catch ex As IOException
' Instrucciones a ejecutar si se produce otro posible error de fichero
Catch ex As Exception
' Instrucciones a ejecutar si se ha producido otro posible error
End Try

Con el mtodo Exits de la clase compartida File


If Not File.Exists(nomFichero) Then 'System.IO.File.Exists(nomFichero)
MessageBox.Show("No existe " & nomFichero)
Exit Sub
End If

Carpeta del proyecto


Y por ltimo hablar de la carpeta en la que se encuentra el proyecto.
Debemos conocer la funcin My que proporciona acceso en tiempo de ejecucin a la
informacin y a las instancias de objeto predeterminadas relacionadas con la aplicacin y su
entorno: My.Application, para indicar si deseamos informacin de la propia aplicacin,
My.Computer nos hablar del ordenador en que se est ejecutando, .
As pues: My.Application.Info.DirectoryPath indicar la carpeta en que se est
ejecutando el proyecto actual.
No confundir con la palabra clave Me que hace referencia a la instancia especfica de
una clase o estructura donde se est ejecutando el cdigo. Me se comporta como una variable de
objeto o de estructura que hace referencia a la instancia actual.
Ejemplo:
Me.txtNombre.Text = "" 'La caja de texto est en el propio formulario
Me.Nombre = nom
' la variable o propiedad Nombre es del objeto actual de la
clase (recuerda que el formulario tambin es una clase)

Visual Basic.Net (Cap 10. Ficheros)

Pg. 162

Desarrollo de Aplicaciones Multiplataforma

Cap 11. Varias intancias de un formulario.


Formularios Mdi
Aplicaciones de estilo SDI
Una aplicacin de tipo o estilo SDI (Single Document Interface), Interfaz de Documento
Sencillo, est compuesta fundamentalmente de un nico formulario, a travs del cual, el o la
usuaria realiza toda la interaccin con el programa. Como ejemplos de este tipo de aplicacin
tenemos el Bloc de Notas o la Calculadora de Windows.
Generalmente un programa SDI tendr ms de un formulario, pero generalmente estos se
ejecutan independientemente, sin un elemento contenedor que los organice.

Aplicaciones Mdi
Una aplicacin de tipo o estilo MDI (Multiple Document Interface), Interfaz de
Documento Mltiple, se compone de un formulario principal, tambin denominado formulario
MDI, que actuar como contenedor de otros formularios (documentos) abiertos durante el
transcurso del programa, denominados formularios hijos o secundarios MDI. Como ejemplos de
este tipo de aplicacin tenemos PowerPoint o Access.
A diferencia de lo que ocurra en versiones anteriores de VB, un formulario MDI admite los
mismos controles que un formulario normal, aunque dada su orientacin de formulario
contenedor, se recomienda limitar los controles en un MDI a los estrictamente necesarios. El
men es el ejemplo ms identificativo de control idneo para un formulario MDI, ya que a
travs de sus opciones, podremos abrir los formularios hijos de la aplicacin.
La base de una Aplicacin con Interfaz de mltiples documentos (MDI) ser el formulario
primario MDI que contiene las "subventanas" MDI secundarias, dentro de las cuales los
usuarios interactan con la aplicacin.

Creacin de un formulario MDI


La creacin de un formulario MDI primario resulta sencilla, tanto en el Diseador de
Windows Forms como mediante programacin; basta con poner la propiedad IsMdiContainer
a True. Lo veremos por cdigo en los siguientes ejemplos.

Creacin de formularios hijos o MDI secundarios


Vamos a hacerlo mediante un ejemplo. Para poder hacerlo tendremos un segundo formulario
que nos har de plantilla o dicho ms claramente, en el que vemos la clase de la cual crear
nuevos objetos (varios formularios de la misma clase).
Supongamos que queremos crear un formulario MDI que contenga formularios secundarios
con imgenes, al estilo de la figura.
En este caso habremos creado, mediante el diseador, un par de formularios. El que va a ser
contenedor, con men, barra de herramientas, de estado, y el que va a definir sus hijos con un
control para contener una imagen.

Visual Basic.Net (Cap 11. Varias intancias de un formulario. Formularios MDI)

Pg. 163

Desarrollo de Aplicaciones Multiplataforma

Pero cmo conseguimos tener varias copias de un mismo tipo de formulario, en nuestro
caso llamado frmSecundario? Observa las siguientes instrucciones:
Me.IsMdiContainer = True ' Esto se puede hacer en tiempo de diseo, en el
frmMdi_Load, .... Aqu le indicamos que el actual es MDI contenedor, es decir,
que puede contener formularios como subventanas.

Dim frm As New frmSecundario ' Creamos un nuevo objeto de la clase


frmSecundario

frm.MdiParent = Me ' Para indicar que es hijo del actual. Si fuese hijo de
otro pondramos frm.MdiParent = frmPrin
frm.rutaFichero = fichero ' rutaFichero es una variable Public que tiene la
clase frmSecundario. As cada formualario creado de esta clase lo contendr.
frm.Text = nomFichero ' ttulo que se ver en la nueva ventana
Try
frm.picImagen.Image = Image.FromFile(fichero) ' Carga el fichero en el control
picImagen del creado. Esto tambin se podra hacer en el evento Load del
frmSecundario
'frm.picImagen.Image = New System.Drawing.Bitmap(fichero)
frm.Show() ' Lo muestra en pantalla, en este caso "dentro" del MDI
Catch ex As Exception
frm.Close() ' Debemos eliminarlo (cerrarlo) ya que se ha producido un error y
no queremos que aparezca, ya que en este caso ya se haba aadido a la coleccin
MdiChildren
MessageBox.Show("Error en fichero '" & nomFichero & "'" &
Me.MdiChildren.Count, "Atencin", MessageBoxButtons.OK,
MessageBoxIcon.Exclamation)
End Try

Colecciones de formularios hijos: MdiChildren


Ese nuevo formulario creado se ha aadido, de forma automtica a la coleccin MdiChildren
que tiene todo formulario.
Por eso, si queremos recorrerlos para, por ejemplo, existe otro formulario cargado con la ruta
que deseamos actualmente podramos hacerlo como se muestra a continuacin.
Supongamos que todos los formlarios hijos son del mismo tipo.

Visual Basic.Net (Cap 11. Varias intancias de un formulario. Formularios MDI)

Pg. 164

Desarrollo de Aplicaciones Multiplataforma

For Each frmHijo As frmSecundario In Me.MdiChildren ' Recorre la coleccin de los


formularios hijos. Podremos declarar la variable frmHijo de tipo frmSecundario si
sabemos positivamente que no habr formularios de otro tipo.
If frmHijo.rutaFichero = fichero Then
MessageBox.Show(fichero & " ya est cargada", "Atencin")
frmHijo.Focus()' Da el foco al que tiene esa imagen
Exit Sub
End If
Next

Si el formulario contenedor pudiese tener hijos de varios tipos, deberamos hacer:


For Each frmHijo As Form In Me.MdiChildren
If frmHijo.GetType Is GetType(frmSecundario) Then ' Garantizar que es de
este tipo
' Tambin se podra poner: If frmSecundario.GetType.Name = "frmSecundario"
Then

Igualmente, para descargarlos todos deberamos recorrer la coleccin.


Atencin. En este caso podemos recorrerlos en el orden deseado (con For Each o de 0 a
MdiChildren.Count -1) o al revs, pero te recomiendo en orden descendente ya que para la
coleccin OpenForms que veremos en otro apartado deber ser as obligatoriamente.
For i As Integer = Me.MdiChildren.Count - 1 To 0 Step -1
Me.MdiChildren(i).Close()
Next

Formulario activo: ActiveMdiChild


En determinadas ocasiones, desearemos realizar una accin que acte sobre el formulario
secundario actualmente activo. Por ejemplo, supongamos que deseamos que al hacer clic sobre
la imagen de un formulario este nos muestre datos referentes a esa imagen.
Para especificar que nos referimos al formulario activo usaremos la propiedad
ActiveMdiChild, que devuelve el formulario secundario que tiene el foco o el que estuvo activo
ms recientemente.
Cuando tengamos varios controles en un formulario, podremos especificar tambin qu
control est activo. Al igual que tenemos la propiedad ActiveMdiChild, existe la propiedad
ActiveControl que devuelve el control que tiene el foco en el formulario secundario activo.
Veamos un par de ejemplos:
Supongamos que una opcin de men mnuDescargar nos pide cerrar el formulario activo:
Private Sub mnuDescargar_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles mnuDescargar.Click, tbDescargar.Click
Try
Me.ActiveMdiChild.Close()' cierra el formulario activo
Catch ex As Exception
MessageBox.Show(ex.Message, "No hay formulario para descargar") ' si no hay
ninguno, ActiveMdiChild estar a Nothing
End Try
End Sub

Si necesitamos acceder a alguna de sus propiedades, variables, controles, deberemos


asegurarnos que realmente lo es (si ya est garantizado sobrara el If)
If frmHijo.GetType Is GetType(frmSecundario) Then
Dim frm As frmSecundario = Me.ActiveMdiChild
frm.picImagen.BackgroundImage = Image.FromFile(fichero)

O lo que es lo mismo:

Visual Basic.Net (Cap 11. Varias intancias de un formulario. Formularios MDI)

Pg. 165

Desarrollo de Aplicaciones Multiplataforma

TryCast(Me.ActiveMdiChild, frmSecundario).picImagen.BackgroundImage =
Image.FromFile(fichero)

Organizacin de los formularios secundarios en el MDI


El mtodo LayoutMdi se utiliza para organizar los formularios secundarios del formulario
MDI principal de modo que se facilite el desplazamiento por los mismos y su manipulacin.
Los formularios secundarios se pueden disponer en mosaico horizontal y vertical, en cascada
o como iconos dentro del formulario MDI principal.
Si por ejemplo, queremos que su distribucin sea en mosaico horizontal pondremos:
Me.LayoutMdi(MdiLayout.TileHorizontal)

Para conseguir que bajo una opcin de men se muestre la lista de ventanas abiertas
usaremos la propiedad MdiWindowListItem del MenuStrip (asignndole el
ToolStripMenuItem correspondiente).
En el siguiente ejemplo tendramos las ventanas en Cascada. Observa que bajo la opcin
Ventana aparecen las abiertas y marcadas la 3, ya que esta es la activa en este momento. Es
decir, el ToolStripMenuItem al que le hemos aplicado la propiedad MdiWindowListItem es al
de ttulo Ventana.

Si en el submen deventanas abiertas seleccionamos otra opcin, se pasar el foco a la


ventana seleccionada, de forma automtica.

Creacin de varias instancias de un fomulario


De la misma forma que podemos mostrar formularios hijos de un formulario MDI, tambin
podemos crear nuevos formularios sin ser necesariamente cargados dentro del mismo. Para eso
bastara con las siguientes instrucciones:
Dim frm As New frmSegundo ' Crea una nueva instancia de este tipo
frm.Show() ' Lo muestra. Aparece una nueva instancia en pantalla.
numFormulario+=1
frm.Nombre = "Formulario" & numFormulario ' Podemos acceder a sus variables,
controles, ...

Coleccin de formularios abiertos: OpenForms


De la misma forma que existe la coleccin MdiChildren, podemos acceder a todos los
formularios abiertos en el momento en que lo deseemos mediante la propiedad OpenForms de
My.Application

Ejemplo, supongamos que queremos recorrerlos todos y hacer distintas cosas dependiendo
del tipo de formulario que sea:

Visual Basic.Net (Cap 11. Varias intancias de un formulario. Formularios MDI)

Pg. 166

Desarrollo de Aplicaciones Multiplataforma

For Each frm As Form In My.Application.OpenForms ' Recorre todos los formularios
abiertos, incluso el actual
Select Case frm.GetType.Name
Case "frmSegundo"
' Instrucciones si es de este tipo
Case "frmAyuda"
' En el caso de que sea de este otro
Case "frmPrincipal"
' Tercera posibilidad
End Select
Next

Atencin. Si lo que deseamos es recorrerlos todos para cerrarlos, obligatoriamente


deberemos hacer un recorrido del ltimo formulario al primero. Ejemplo: Vamos a cerrar los
formularios de tipo frmSegundo cargados, sabiendo que podemos tener de otros tipos.
For i As Integer = My.Application.OpenForms.Count - 1 To 0 Step -1
Dim frm As Form = My.Application.OpenForms(i) ' Asigno a variable por comodidad
If frm.GetType.Name = "frmSegundo" Then
frm.Close()
End If
Next

Visual Basic.Net (Cap 11. Varias intancias de un formulario. Formularios MDI)

Pg. 167

You might also like