Visual Basic 2012 (VB - NET) - Los Fundamentos Del Lenguaje PDF
Visual Basic 2012 (VB - NET) - Los Fundamentos Del Lenguaje PDF
Visual Basic 2012 (VB - NET) - Los Fundamentos Del Lenguaje PDF
Se dedica un capítulo al acceso a las bases de datos con la ayuda de ADO.NET y SQL, lo
que le permitirá avanzar hacia el desarrollo de aplicaciones cliente-servidor. Se presentan y
detallan las potentes funcionalidades de LINQ para facilitar el acceso y manipulación de
los datos. También se presenta el uso del lenguaje XM, que facilita el intercambio de
información con otras aplicaciones.
Los usuarios de versiones anteriores descubrirán las novedades y mejoras de esta versión
2012 para desarrollar, incluso de manera más rápida y sencilla, aplicaciones para el
Framework .NET 4.5.
Introducción
ShareVideos
Desde la primera versión aparecida en 2002, el lenguaje Visual Basic ha seguido una
evolución constante hasta esta versión 2012. Sigue siendo el lenguaje de referencia de
Microsoft a pesar de la competencia de su joven compañero C#. Esta popularidad se debe
seguramente a la excepcional longevidad de este lenguaje, cuyos orígenes se remontan al
lenguaje GW-BASIC disponible con MS-DOS. En efecto, son muchos los informáticos que
dieron sus primeros pasos en el mundo del desarrollo mediante este lenguaje.
El objetivo de este libro consiste en presentar las bases de este lenguaje para permitirle
explotar lo mejor posible las funcionalidades de la versión 4.5 del Framework .NET. Una
vez aprendidas estas bases, tendrá usted la sartén por el mango para tratar el diseño de las
aplicaciones gráficas.
Aunque el despliegue es, por supuesto, la última etapa de la elaboración de una aplicación,
no debe descuidarse. En el último capítulo de este libro se tratan las dos tecnologías
disponibles de despliegue que le permiten simplificar la instalación de sus aplicaciones en
los puestos de los usuarios.
Este libro, sin embargo, no tiene como vocación sustituir la documentación del
Framework .NET, que debe seguir siendo su referencia para obtener datos como la lista de
métodos o propiedades presentes en una clase.
Introducción
La plataforma .NET facilita un conjunto de tecnologías y herramientas que simplifican el
desarrollo de aplicaciones y propone una solución para casi cualquier tipo de aplicaciones:
ShareVideos
El Framework contiene dos elementos principales: el Common Language Runtime y la
librería de clases del .NET Framework.
Las ventajas de esta solución son obvias, ya que para ejecutar una misma aplicación en
varias plataformas de hardware o de software basta con obtener la máquina virtual capaz de
efectuar la traducción. Esta máquina virtual está disponible para todos los sistemas
Microsoft. El proyecto Mono propone una versión de la máquina virtual para las
plataformas siguientes:
Linux,
Mac OS X,
Sun Solaris,
BSD - OpenBSD, FreeBSD, NetBSD.
ShareVideos
Están disponibles para descargar en el sitio http://www.mono-project.com.
La máquina virtual no se conforma con efectuar la traducción del código. El código MSIL
también se llama código gestionado, lo que supone que un cierto número de operaciones
adicionales se realizarán sobre el código en el momento de la ejecución. La figura siguiente
recoge el conjunto de las funcionalidades disponibles en el Common Language Runtime.
Class Loader
IL to Native Compilers
Code Manager
Garbage Collector
Security Engine
Debug Engine
Type Checker
ShareVideos
Exception Manager
Thread Support
COM Marshaler
Permite traducir llamadas hacia componentes COM, asegurando por ejemplo la conversión
de los tipos de datos.
La biblioteca contiene una cantidad increíble de espacios de nombres y clases; tantos, que
es muy posible que no tenga que utilizar nunca algunos de ellos a lo largo de sus
desarrollos con Visual Basic.
ShareVideos
System
Es el espacio de nombres raíz para los tipos de datos en el Framework .NET. Contiene en
particular la definición de la clase Object, que es el ancestro de todos los tipos de datos del
Framework .NET.
System.Windows
Contiene el conjunto de los elementos que permiten la creación de interfaces para usuarios
de Windows.
System.Web
Contiene todos los recursos necesarios para la creación de aplicaciones Web, con las clases
de la tecnología ASP.NET, por ejemplo, o las clases utilizables para la creación de
servicios Web XML.
System.Data
System.Xml
El lenguaje XML está ahora por todas partes y este espacio de nombres contiene las clases
que permiten la manipulación de documentos XML.
La primera versión (1.0) de la plataforma .NET salió en enero de 2002 con Visual Studio
2002. Esta versión se sustituyó rápidamente por la versión 1.1, que corrigió algunos
problemas de juventud de la versión anterior y añadió tecnologías que solo estaban
disponibles antes como instalaciones independientes. Las principales aportaciones de esta
versión fueron:
ShareVideos
Está disponible con la versión 2003 de Visual Studio en abril 2003.
Hubo que esperar a noviembre de 2005 para ver llegar la versión 2.0 asociada a la salida de
Visual Studio 2005. Esta versión aporta muchas mejoras:
La versión 3.0 llega en noviembre 2006 y aporta nuevas tecnologías a la vez que sigue
siendo principalmente una versión 2.0. Estas tecnologías están disponibles en descargas que
vienen a integrarse al Framework 2.0. A continuación le mostramos un vistazo de estas
novedades:
ShareVideos
La versión 3.5, de noviembre de 2007, aporta principalmente mejoras y evoluciones a las
tecnologías aparecidas con la versión 3.0. La única verdadera novedad de esta versión
corresponde a la aparición del lenguaje LINQ (Language Integrated Query). El objetivo de
este lenguaje consiste en uniformizar el método utilizado para extraer información de una
fuente de datos. Este nuevo lenguaje permite consultar colecciones de objetos, bases de
datos SQL Server, DataSet ADO.NET y documentos XML con la misma sintaxis.
La versión 4.0, publicada en mayo de 2010, mejora aun más las capacidades y
funcionalidades disponibles. Entre sus novedades podemos señalar:
La mejora del recolector de basura, que se ejecuta ahora en segundo plano. Durante
una operación de recolección, los hilos de la aplicación ya no quedan suspendidos
para facilitar la limpieza de la memoria, lo que aumenta naturalmente el
rendimiento de la aplicación.
Poder tener en cuenta más fácilmente los procesadores multinúcleo que permiten el
reparto de los procesos con la programación paralela.
La versión 4.5, que salió al mercado en junio del año 2012, es un complemento de la
versión 4.0. La principal novedad es la simplificación de la programación en modo
asíncrono. Esta técnica evita el bloqueo de un thread mientras se ejecuta un método.
ShareVideos
1. Escritura del código
Un editor de texto.
Un compilador.
Un depurador.
Este enfoque es, de lejos, el más cómodo. Sin embargo se necesita una pequeña fase de
aprendizaje para familiarizarse con la herramienta. Para nuestra primera aplicación, vamos
a utilizar un proceso un poco diferente ya, que vamos a emplear herramientas individuales:
el bloc de notas de Windows para la escritura del código y el compilador en línea de
comandos para Visual Basic.
Nuestra primera aplicación será muy sencilla, ya que simplemente mostrará el mensaje
«Buenos días» en una ventana de comandos.
Este es el código para nuestra primera aplicación, que enseguida explicaremos. Se debe
introducir con la ayuda del bloc de notas de Windows o cualquier otro editor de texto
siempre que este no añada ningún código de compaginación en el interior del documento,
como hacen por ejemplo los programas de tratamiento de texto.
Ejemplo
Imports System
public Module test
dim mensaje as string="Buenos días"
public sub main ()
console.writeline(mensaje)
end sub
end module
Hay que guardar este código dentro de un archivo con la extensión .vb. Dicha extensión no
es obligatoria, pero usándola se respetan las convenciones de Visual Studio.
Imports System
Esta línea permite acceder a los elementos presentes en el espacio de nombres System. Sin
ella, habría que utilizar los nombres plenamente cualificados para todos los elementos
contenidos en el espacio de nombres. En nuestro caso, deberíamos utilizar entonces:
System.Console.writeline("Buenos días")
ShareVideos
En Visual Basic, toda parte de código debe estar contenida dentro de un módulo o clase.
Esta línea declara una variable. Se deben declarar todas las variables antes de poder
utilizarlas. La declaración permite especificar el tipo de información que la variable va a
contener: aquí, una cadena de caracteres y eventualmente un valor inicial, "Buenos días" en
nuestro caso.
Console.writeline("Buenos días")
La clase Console definida dentro del espacio de nombres System proporciona un conjunto
de métodos, que permiten mostrar información en la consola o leer información de ella. El
procedimiento writeline permite mostrar una cadena de caracteres en la consola.
Hay que destacar también que Visual Basic no hace distinción entre minúsculas y
mayúsculas dentro de las instrucciones. Si se utiliza el editor de Visual Studio para escribir
el código, este insertará automáticamente las modificaciones para hacer uniforme la
«ortografía» del código.
El Framework .NET incluye un compilador en línea de comandos para Visual Basic. Para
compilar el código fuente de nuestro ejemplo, debemos abrir una ventana de comando DOS
con objeto de poder lanzar el compilador. Para ello se ha creado un método abreviado en el
menú Inicio durante la instalación. Este método abreviado lanza la ejecución de un archivo
.bat que coloca algunas variables de entorno necesarias para el correcto funcionamiento de
las herramientas Visual Studio en línea de comandos.
ShareVideos
Tras un breve instante, el compilador nos devuelve el mando. Podemos comprobar la
presencia del archivo ejecutable y su correcto funcionamiento.
Nuestra primera aplicación es realmente muy sencilla. Para aplicaciones más complejas,
será útil especificar algunas opciones para el funcionamiento del compilador. El conjunto
de las opciones disponibles se puede obtener lanzando el comando vbc / ?.
/out:archivo.exe
Esta opción permite especificar el nombre del archivo resultado de la compilación. Por
defecto, se utiliza el nombre del archivo fuente actual que está siendo compilado.
/target :exe
Esta opción pide al compilador la generación de un archivo ejecutable para una aplicación
en modo consola.
/target :winexe
/target :library
Ahora que se ha creado nuestro archivo ejecutable, intentemos ver lo que contiene.
ShareVideos
Hemos dicho que el compilador genera código MSIL. Por lo tanto, este es el código que
visualizamos en el bloc de notas. Para visualizar el contenido de un archivo MSIL, el
Framework .NET propone una herramienta más adecuada.
Permite visualizar un archivo generado por el compilador de forma más clara que con el
bloc de notas. Conviene indicar el archivo que se desea examinar a través del menú
Archivo - Abrir. El desensamblador visualiza entonces su contenido.
En el manifiesto encontraremos datos que indican que, para que la aplicación pueda
funcionar, necesita los ensamblados externos mscorlib, Microsoft.VisualBasic y System.
Símbolo Significado
Más información
Espacio de nombres
Clase
Interfaz
Clase de valores
Enumeración
Método
Método estático
Campo
Campo estático
ShareVideos
Evento Como para el manifiesto, un doble clic en un elemento
permite obtener más detalles. De esta manera
Propiedad
podemos, por ejemplo, visualizar la traducción de
Elemento de manifiesto o nuestro procedimiento main.
de información de clase
using System;
class Program
{
static String mensaje = "Buenos días";
static void Main(string[] args)
{
Console.WriteLine(mensaje);
}
}
Tras la compilación y desensamblaje por ildasm, veamos lo que nos presenta para el
método Main.
No hay diferencias en relación con la versión Visual Basic del método Main.
También es posible dar los pasos inversos y transformar un archivo de texto que contiene
código MSIL en el archivo binario correspondiente. Esta transformación se hace gracias al
ensamblador ilasm. La única dificultad consiste en crear el archivo de texto que contiene el
código MSIL, ya que, aunque la sintaxis es comprensible, no resulta muy intuitiva. Una
solución puede consistir en pedir a la herramienta ildasm (el desensamblador) que genere
este archivo de texto. Para ello, después de haber abierto el archivo ejecutable o la librería
dll con ildasm, usted debe utilizar la opción Dump del menú Archivo. Se le invita entonces
a elegir el nombre del archivo que desea generar (extension .il).
Este archivo se puede modificar a continuación con un simple editor de texto. Sustituya por
ejemplo el contenido de la variable mensaje con la cadena "Hello".
ShareVideos
.maxstack 8
IL_0000: ldstr "Hello"
IL_0005: stsfld string Program::message
IL_000a: ret
} // end of method Program::.cctor
Guarde el archivo. Ahora solo queda volver a generar el archivo ejecutable gracias al
ensamblador ilasm. Para ello, introduzca la línea de comandos siguiente:
ShareVideos
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method a:: .ctor
} // end of class a
El código original:
El código generado:
ShareVideos
return local1;
i0: local1 = local0;
}
i1: local0 = System.String.Compare(this.b, (c) A_0.b);
goto i0;
}
¡El análisis de miles de líneas de código de este tipo puede provocar dolor de cabeza! Por lo
tanto, es preferible conservar el código original para las modificaciones posteriores. Hay
más información disponible en el sitio web: http://www.preemptive.com/
Cuando un usuario ejecuta una aplicación gestionada, el cargador de código del sistema de
explotación carga el Common Language Runtime, que luego lanza la ejecución del código
gestionado. Como el procesador de la máquina en la que se ejecuta la aplicación no puede
encargarse directamente del código MSIL, el Common Language Runtime debe convertirlo
en código nativo.
De la versión 1.0 a la versión 3.0, no asistimos a ninguna revolución en VB, sino a las
evoluciones clásicas de un lenguaje de programación.
ShareVideos
Con la aparición de la versión 4.0 en 1996, VB pasó a medirse con los mejores, gracias a
una multitud de evoluciones:
A pesar de, o más bien a causa de, todas estas evoluciones, la versión 4.0 de VB no era muy
estable.
Rápidamente, en 1997, Microsoft sacó la versión 5.0 de Visual Basic, que no aportó,
grandes evoluciones salvo la desaparición de las aplicaciones de 16 bits.
Las evoluciones de la versión 6.0, que salió un año más tarde, se basan principalmente en el
método de acceso a las bases de datos, con la sustitución de DAO (Data Access Object) de
las versiones anteriores por ADO (Active Data Object), que se convierte de hecho en el
método común a los lenguajes Microsoft para el acceso a los datos.
Sin embargo, esta versión deberá esperar el service pack 4 para permitir el funcionamiento
correcto de ciertos controles de acceso a los datos (el Data Environment).
Aunque esté generada en código nativo por la compilación, una aplicación VB siempre
requiere el módulo runtime para poder ejecutarse en una máquina (vbrun.dll), ya que, a
diferencia de los lenguajes como C++, VB no utiliza la interfaz de programación WIN 32
para llamar las funciones del sistema operativo.
La versión siguiente, que se estrena en 2002, aporta cambios radicales en Visual Basic. Esta
versión se integra en la suite Visual Studio .NET, que se basa en una nueva infraestructura
para la creación y la ejecución de aplicaciones bajo Windows: el Framework .NET. Los
principios de funcionamiento de esta infraestructura se describen en el capítulo
Presentación de la plataforma .NET.
Las versiones 2003 y 2005 siguen la evolución del Framework.NET (versión 1.1 luego 2.0)
aportando cada vez más funcionalidades y herramientas que facilitan y aceleran el
desarrollo de aplicaciones.
La versión 2008 también aporta su conjunto de novedades, entre las cuales las más notables
son las siguientes:
Posibilidad de generar una aplicación para una versión específica del Framework
(2.0, 3.0, 3.5).
Compatibilidad o mejora de la compatibilidad de nuevas tecnologías para el
desarrollo Web (AJAX, JavaScript, CSS...).
ShareVideos
Integración de LINQ en los lenguajes Visual basic y Visual C#, que permite
uniformizar el acceso a los datos de manera independiente de la fuente (objetos,
bases de datos, archivo XML).
Inclusión de una herramienta de mapeo objeto/relacional (O/R Designer).
Creación de aplicaciones WPF optimizadas para Windows Vista.
Posibilidad de crear informes con Report Designer (en sustitución de Crystal
Report).
Posibilidad de escribir una instrucción sobre varias líneas sin tener que utilizar el
carácter de continuación (_) exigido en las versiones anteriores.
La versión 2012 de Visual Basic integra las novedades del Framework 4.5, como por
ejemplo la simplificación de la programación asíncrona, añadiendo dos nuevas palabras
claves: async y await. El entorno de desarrollo también ofrece nuevas funcionalidades.
Entre ellas, la jerarquía de llamadas será una preciada ayuda para mejorar el seguimiento
del flujo de ejecución de una aplicación y anticipar las consecuencias de una modificación
del código.
ShareVideos
2,8 a 3,8 GB en otro disco 2.
Vídeo 1024 x 768 1280 x 1024 o más Proce
Lector CD-Rom o dimie
Indispensable Indispensable
DVD nto de
Cualquier versión instal
Windows 7
Sistema operativo
posterior (Windows) ación
Windows Server
Windows Server 2012 Los
elementos necesarios son:
Es necesario ser paciente porque el proceso de instalación puede ser bastante largo, en
función de las opciones que se hayan seleccionado.
3. Primer lanzamiento
ShareVideos
Durante el primer lanzamiento, Visual Studio le propone personalizar el entorno de trabajo.
En función de su preferencia por un idioma determinado, Visual Studio configura el
entorno con las herramientas adaptadas. Se puede modificar esta configuración más
adelante con el menú Herramientas - Importar y exportar configuraciones.
Esta página se visualiza cada vez que inicia Visual Studio. Le permite acceder rápidamente
a los últimos proyectos en los que ha trabajado, crear un nuevo proyecto o abrir un proyecto
existente. La pestaña Últimas noticias permite activar un flujo RSS que facilita
información de las actualizaciones disponibles.
Al crear un nuevo proyecto o abrir un proyecto existente, se lanza el entorno Visual Studio.
ShareVideos
La utilización de pestañas.
El anclaje de ventanas no sirve para ganar espacio en la pantalla, pero nos permite colgar en
un borde de la pantalla o de una ventana tal o cual ventana. También es posible convertir
cada ventana en flotante, al hacer doble clic en su barra de título o al utilizar el menú
contextual. Luego se puede desplazar o anclar esta ventana en otro borde. Para guiarnos en
el anclaje de una ventana, Visual Studio muestra, durante su desplazamiento, unas guías
que permiten elegir el borde donde efectuar el anclaje.
Más interesantes para ganar espacio en la pantalla, las ventanas ocultables solo son visibles si el
cursor del ratón se encuentra encima de su superficie. Si no, solo una zona de pestañas, ubicada
en el borde del entorno de desarrollo, permite que se muestre su contenido. Para conservar
siempre visible una ventana, basta con bloquearla utilizando la chincheta presente en su barra de
título .
Finalmente, la utilización de pestañas permite compartir una misma zona de pantalla entre
diferentes ventanas y, en este sentido, los diseñadores de Visual Studio las han utilizado sin
moderación.
Estándar
ShareVideos
Editor de texto
Ubicación
Depurar
Las otras barras disponibles se muestran sobre la marcha y en función de sus necesidades
con el fin de evitar sobrecargar su pantalla.
Las ventanas disponibles son también bastante numerosas y vamos a descubrir las más
corrientes.
2. El cuadro de herramientas
A partir del cuadro de herramientas, vamos a elegir los elementos utilizados para el diseño
de la interfaz de la aplicación.
El cuadro de herramientas se organiza por secciones, que permiten encontrar los controles
fácilmente.
Cada uno podrá personalizar su cuadro de herramientas al añadirle, por ejemplo, controles
no disponibles por defecto. Puede ser conveniente, antes de añadir controles al cuadro de
herramientas, crear una nueva sección para albergarlos. Para ello, visualice el menú
contextual del cuadro de herramientas (haciendo clic con el botón secundario del ratón en el
cuadro de herramientas), elija la opción Agregar Ficha, luego dé un nombre a la nueva
sección así creada. Después de haber seleccionado esta nueva sección, puede añadirle
controles. Visualice de nuevo el menú contextual del cuadro de herramientas, y escoja la
opción Elegir elementos.
ShareVideos
3. El explorador de servidores
La mayoría de las aplicaciones requieren otras máquinas presentes en la red para poder
funcionar. Por lo tanto, es necesario tener, durante la fase de desarrollo de una aplicación,
la posibilidad de acceder a los recursos disponibles en otras máquinas.
El explorador de servidores también permite gestionar los servicios que funcionan en las
máquinas, tanto a través de la interfaz gráfica como del código. Ofrece la posibilidad de
visualizar la actividad de las máquinas analizando los contadores de rendimiento o
recuperando la información en los diferentes registros de eventos. Un sencillo arrastrar-
soltar entre el explorador de servidores y una ventana de diseño genera automáticamente el
código que permite manipular este elemento en la aplicación. Por ejemplo, el
desplazamiento de un contador de rendimiento sobre una ventana genera el código
siguiente:
4. El explorador de soluciones
ShareVideos
5. La visualización de clases
La visualización de clases es accesible con el menú Ver - Otras ventanas - Vista de clases
o con la combinación de teclas [Ctrl][Shift] C. Comparte su zona de pantalla con el
explorador de soluciones.
La visualización de clases permite tener una visión lógica de una solución presentando las
diferentes clases utilizadas en esta solución.
6. La ventana de propiedades
7. La lista de tareas
ShareVideos
Puede ubicar en su código comentarios que aparecerán luego en la lista de tareas. Esta
técnica le permite, por ejemplo, indicar una modificación que deba efectuar más tarde en su
código.
Basta con que el comentario empiece por ’todo’ para luego retomarlo automáticamente en
la lista de tareas.
También puede introducir directamente los datos en la lista de tareas. Para ello deberá
elegir tareas de usuario utilizando la zona de lista disponible en la barra de título de la lista
de tareas.
Puede especificar una descripción y una prioridad para la nueva tarea haciendo clic en la
columna de izquierda, en la lista de tareas. Hay tres niveles de prioridad disponibles:
Alta.
Normal.
Baja.
8. La lista de errores
El código que introduce es analizado continuamente por Visual Studio y los posibles
errores de sintaxis que encuentra se muestran en la ventana Lista de errores.
Para ir directamente a la línea donde apareció un error de sintaxis, basta con hacer doble
clic en el elemento correspondiente de la lista (en el ejemplo anterior, haga doble clic en {
El carácter no es válido para alcanzar la línea 7). No es necesario pedir la compilación
completa del código para rastrear todos los errores de sintaxis. En cuanto el error queda
corregido, desaparece automáticamente de la lista de errores.
Los botones de errores, advertencias y mensajes activan un filtro sobre los mensajes
visualizados en la lista de errores.
Vamos a dedicar más tiempo a esta ventana, ya que propone muchas funcionalidades que
permiten automatizar las acciones más corrientes.
ShareVideos
a. Los Snippets o fragmentos de código
Los Snippets son fragmentos de código que se pueden incorporar muy fácilmente a un
archivo fuente. Permiten escribir rápidamente porciones de código relacionado con
situaciones habituales. Visual Studio propone, de forma predeterminada, una multitud de
Snippets. Hay dos soluciones disponibles para insertar un Snippet:
Usar la opción Insertar fragmento de código del menú contextual del editor de
código.
Usar las combinaciones de teclas [Ctrl] K, luego [Ctrl] X.
Para estos dos métodos, Visual Studio le propone elegir en una lista el Snippet que le
interesa. Se pueden personalizar estas porciones de código del Snippet, que están resaltadas
en azul claro. La modificación de una de estas porciones de código repercute en todas las
apariciones en el Snippet.
En el ejemplo que viene a continuación, se utilizó un Snippet para añadir una nueva
propiedad a una clase.
Usted también puede diseñar sus propios Snippets. Para ello, debe crear un archivo XML
que contendrá el código del Snippet, y darle la extensión .snippet.
ShareVideos
<IDname/ID>
<Defaultvalue/Default>
</Literal>
</Declarations>
<Code Language="XML">
<![CDATA[<test>
<name>$name$</name>
$selected$ $end$</test>]]>
</Code>
</Snippet>
</CodeSnippet>
<Header>
<Title>Recorre una matriz de datos</Title>
<Author>Thierry</Author>
<Shortcut>matriz</Shortcut>
<Description>Funcionalidad que permite recorrer una
matriz de datos</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Declarations>
<Literal>
nombreMatriz</ID>
<Default>laMatriz</Default>
</Literal>
<Literal>
tipoMatriz</ID>
<Default>tipoDelaMatriz</Default>
</Literal>
<Literal>
tamañoMatriz</ID>
<Default>tamañoDelaMatriz</Default>
</Literal>
</Declarations>
<Code Language="VB">
<![CDATA[
ShareVideos
dim $nombreMatriz$($tamañoMatriz$) as $tipoMatriz$
dim index as integer
for index=0 to $tamañoMatriz$ -1
’ añada el código que gestiona la matriz
next ]]>
Luego puede guardar el archivo y su Snippet está listo. Conviene ahora integrarlo en Visual
Studio. Para ello, deberá activar el gestor de Snippet a través del menú Herramientas -
Administrador de fragmentos de código.
Puede visualizar los fragmentos de código que ya han sido modificados desde el
lanzamiento de Visual Studio. Se identifican las modificaciones con un borde de color en el
margen del editor de código.
Un borde amarillo indica que se ha modificado el código, pero que aún no ha sido
guardado.
Un borde verde indica que se ha modificado y guardado el código.
ShareVideos
La modificación realizada mediante este cuadro de diálogo repercute sobre el conjunto del
código donde se utiliza la variable.
Los editores de texto de Visual Studio disponen de muchas funcionalidades que permiten
facilitar las operaciones efectuadas con frecuencia durante la escritura del código de una
aplicación.
Selección de texto
Se dispone por ejemplo del método siguiente, que visualiza en la consola los datos
personales de un individuo:
Para modificar este método y escribir estos datos en un archivo en vez de visualizarlos en la
consola, solo es necesario crear el archivo y modificar todas las instrucciones .Write para
que se apliquen en el archivo creado. Para ello, añada simplemente la línea siguiente para la
creación del archivo:
Modifique después cada instrucción .Write para escribir hacia el archivo, y no hacia la
consola. Seleccione para ello una zona rectangular que contenga todas las palabras console
e introduzca la palabra archivo.
ShareVideos
También es posible insertar texto simultáneamente en varias líneas creando una zona de
selección rectangular de cero caracteres de ancho en todas las líneas donde se debe efectuar
la inserción.
Al hacer clic en un símbolo en el código fuente, todas las instancias de este símbolo quedan
marcadas en el documento.
Durante el desarrollo de una aplicación, a veces ocurre que se intenta utilizar un elemento
antes de su declaración, posponiendo esta para más tarde. Sin embargo, esta solución tiene
el inconveniente de no poder realizar ningún test hasta que todos los elementos utilizados
hayan sido definidos. También es deprimente para el desarrollador ver decenas de líneas de
código subrayadas en rojo.
El editor de Visual Studio es capaz de generar el código necesario para los elementos que
faltan. Cuando el ratón pasa sobre el elemento referido, aparece un botón debajo del
elemento.
Al hacer clic en este botón, aparece un menú contextual que propone las opciones que
permiten generar el código que puede resolver los problemas detectados.
Se adaptan las opciones disponibles en este menú contextual según la ubicación del
elemento en el que este está activado. En el ejemplo anterior, el término nombre puede
corresponder a un nombre de método, propiedad o variable. Según los casos, se puede
visualizar un cuadro de diálogo para personalizar la generación del código. Solo hace falta
completar el cuadro de diálogo siguiente para que el esqueleto de código se genere.
ShareVideos
Zoom
Esta funcionalidad permite efectuar un zoom hacia delante o atrás sobre una ventana de
texto. Se puede acceder a ella accionando la rueda del ratón mientras se mantiene la tecla
[Ctrl] pulsada.
Las soluciones
1. Presentación
Para ayudarle en la creación de aplicaciones, Visual Studio le propone varios elementos que
sirven para agrupar los componentes de una aplicación. El contenedor de más alto nivel es
la solución en la que podrá ubicar uno o varios proyectos. Estos proyectos contendrán, a su
vez, todos los elementos para que el compilador sea capaz de generar el archivo ejecutable
o dll del proyecto. El explorador de soluciones nos va a permitir manipular todos estos
elementos.
ShareVideos
Un archivo para el proyecto, con la extensión .vbproj. Este archivo contiene todos
los datos de configuración del proyecto, junto con la lista de los archivos que lo
constituyen, la lista de las referencias utilizadas en él, las opciones a utilizar para la
compilación del proyecto, etc.
Numerosos archivos con la extensión .vb, que contendrán el código fuente de todas
las clases, hojas y módulos que constituyen el proyecto.
Un archivo .resx asociado a cada hoja de su aplicación. Este archivo en formato
XML contiene, entre otras, la lista de los recursos utilizados en esta hoja.
Al final, una solución contiene otros muchos archivos en función de los elementos
utilizados en su proyecto (acceso a una base de datos, archivos HTML...).
Las soluciones, como contenedores que son, permiten gestionar sus elementos. Es posible
añadir, suprimir, cambiar el nombre de elementos en la solución.
a. Añadir un proyecto
Si desea crear un nuevo proyecto, elija la opción Nuevo Proyecto del menú Archivo -
Agregar. Un cuadro de diálogo le propone entonces configurar las características del nuevo
proyecto y, en particular, definir un directorio por defecto para guardar el proyecto. Si este
directorio no corresponde a la ubicación donde usted desea guardar el proyecto, puede
seleccionar una nueva. Esta operación se deberá realizar para cada proyecto que desee
añadir. Puede ser interesante modificar la ruta propuesta por defecto para guardar los
proyectos. Para hacerlo, abra el menú Herramientas - Opciones, en el cuadro de diálogo
elija la opción Proyectos y soluciones y modifique la sección Ubicación de los proyectos.
Si usted desea añadir un proyecto ya existente, elija la opción Abrir proyecto del menú
Archivo - Agregar. Un cuadro de diálogo de selección de archivos le permite entonces
elegir el archivo .vbproj del proyecto que quiere añadir a la solución.
b. Suprimir un proyecto
ShareVideos
c. Cambiar el nombre de un proyecto
d. Descargar un proyecto
Cuando desee excluir de manera temporal un proyecto del proceso de generación o impedir
la edición de sus componentes, puede descargar el proyecto de la solución usando la opción
Descargar el proyecto.
Si está trabajando con una solución que contiene varios proyectos, puede añadir un nuevo
nivel de jerarquía creando carpetas de solución. Estas permiten la agrupación lógica de
proyectos dentro de una solución.
Para ello, cree primero las carpetas en la solución, y después organice los proyectos en
estas carpetas.
Las carpetas de solución no crean carpetas físicas en el disco, solo son contenedores lógicos
en el interior de la solución.
ShareVideos
A continuación utilice el menú Proyecto - Agregar nueva carpeta de solución o el menú
contextual disponible haciendo clic con el botón secundario del ratón en el nombre de la
solución.
Sea cual sea el método utilizado, debe facilitar un nombre para la carpeta creada.
Previamente, basta con que seleccione la carpeta en la que desea crear el proyecto.
A menudo es necesario organizar una solución con carpeta cuando ya existen proyectos en
la solución.
En este caso hay que crear las carpetas y después arrastrar-soltar los proyectos a las
carpetas correspondientes.
Las soluciones contienen principalmente proyectos, aunque es posible tener en una solución
archivos gestionados de manera independiente de un proyecto particular, pero asociados a
la solución. Es el caso, por ejemplo, de un archivo icono que quiera utilizar en varios
proyectos de la solución. Estos archivos se llaman elementos de solución y se encuentran
en una carpeta específica de esta.
A veces puede querer visualizar el contenido de un archivo mientras está trabajando en una
solución, como por ejemplo el acta de una reunión. Este archivo no debe pertenecer a la
solución de manera permanente. Puede abrirlo con un editor externo y pasar de Visual
Studio a este editor externo, pero resulta más práctico visualizar el archivo directamente en
el entorno Visual Studio.
ShareVideos
Utilice la opción Abrir archivo del menú Archivo.
El cuadro de diálogo le permite elegir el archivo que desea abrir. En función del tipo de
archivo, se le asociará automáticamente un editor por defecto, para permitir su
modificación. A veces puede resultar útil elegir el editor asociado a un archivo. Para ello, el
botón Abrir del cuadro de diálogo dispone de un menú que propone la opción Abrir con,
que permite la elección del editor asociado al archivo.
Proyecto de inicio.
Dependencias del proyecto.
Parámetros de análisis del código.
Depurar archivos de código fuente.
Propiedades de configuración.
Esta página de propiedades de la solución determina, entre los proyectos disponibles, cuál o
cuáles son lanzados al arrancar la solución.
ShareVideos
Hay tres opciones disponibles:
Selección actual
Un combo propone la lista de los proyectos disponibles en la solución y entre los que se
debe elegir el que será ejecutado al iniciar la solución. El nombre de este proyecto se señala
en negrita en el explorador de soluciones. Esta selección también se puede hacer con el
menú contextual del explorador de soluciones eligiendo la opción Establecer como
proyecto de lanzamiento.
Una tabla presenta la lista de todos los proyectos disponibles en la solución. Para cada uno
de ellos, se debe indicar la acción que se va a ejecutar en el inicio de la aplicación. Las
opciones posibles son:
Ninguna.
Iniciar.
Iniciar sin depurar.
Si elige iniciar varios proyectos a la vez en el arranque de la solución, también debe indicar el
orden en el que se iniciarán estos proyectos. Este orden corresponde en realidad al orden de los
proyectos en la tabla. Los botones y permiten modificarlo.
En la lista de los proyectos, seleccione el proyecto para el cual desea configurar las
dependencias. Los otros proyectos de la solución aparecen en una lista con una casilla de
verificación para cada uno. A la hora de generar el proyecto, todos los proyectos de los que
depende serán automáticamente regenerados si han sido modificados desde la última
generación o si nunca han sido generados.
ShareVideos
Algunas dependencias no se pueden modificar; entonces, la casilla de verificación aparece
en gris.
En general, es el caso cuando un proyecto posee una referencia a otro proyecto o cuando,
añadiendo una dependencia, se puede crear un bucle. Por ejemplo, el proyecto1 depende del
proyecto2, e inversamente.
Esta página de propiedades permite configurar las reglas que se utilizan cuando se analiza
el código de los diferentes elementos de la solución.
Para cada proyecto de la solución, puede indicar la configuración que utilizarán las
herramientas de análisis.
La opción Todas las reglas de Microsoft es la más estricta y detecta la menor anomalía,
principalmente:
La lista Directorios que contienen código fuente muestra el nombre de los directorios que
serán revisados en búsqueda de código fuente durante la depuración de una aplicación. Se
puede gestionar esta lista gracias a la barra de herramientas, cuyos botones permiten:
ShareVideos
Suprimir el directorio seleccionado de la lista.
Desplazar el directorio hacia abajo en la lista.
Desplazar el directorio hacia arriba en la lista.
La lista No buscar los archivos de código fuente siguientes excluye algunos archivos de
la búsqueda.
e. Configuración
Las opciones de configuración permiten definir cómo se generan varias versiones de una
solución y de los proyectos que la componen. Por defecto, hay dos configuraciones
disponibles para una solución en Visual Studio: la configuración Debug y la configuración
Release.
Para cada uno de los proyectos presentes en la solución, las dos configuraciones también
estarán disponibles. A nivel del proyecto, las configuraciones permiten definir opciones de
compilación. Se utiliza la configuración Debug durante el desarrollo y las pruebas del
proyecto. Se utiliza la configuración Release para la generación final del proyecto.
Los proyectos
Los proyectos son los contenedores de segundo nivel en una aplicación. Se utilizan para
organizar lógicamente, gestionar, generar y depurar los componentes de una aplicación. La
generación de un proyecto suele producir un archivo ejecutable o una biblioteca dll. Un
proyecto puede ser muy sencillo y no contener más de dos elementos, un archivo fuente
(.vb) y el archivo de proyecto (.vbproj). En general, los proyectos contienen numerosos
archivos fuente, scripts de bases de datos, referencias hacia servicios Web, recursos
gráficos, etc.
Visual Studio propone por defecto un conjunto de plantillas de proyectos. Estas plantillas
representan un punto de partida para la mayoría de las necesidades en el desarrollo de una
aplicación. Para casos más específicos, puede crear sus propias plantillas de proyecto.
1. Creación de un proyecto
Para crear un proyecto, active el menú Archivo - Nuevo proyecto. Un cuadro de diálogo
le propone entonces elegir las características del nuevo proyecto.
ShareVideos
Elija primero la versión del Framework para la que desea desarrollar el proyecto. La
versión elegida influye en los tipos de proyectos que usted puede crear.
Elija luego el lenguaje con el que desea desarrollar el proyecto. Las opciones disponibles
dependen de los lenguajes instalados en Visual Studio. Por supuesto, en nuestro caso,
elegiremos Visual Basic.
Luego elija el tipo de proyecto que desea desarrollar. El cuadro de diálogo propone
entonces las diferentes plantillas de proyectos disponibles según el tipo de proyecto
elegido.
Después de haber elegido, indique un nombre para el proyecto, una ubicación para sus
archivos y un nombre para la solución. El asistente utiliza la plantilla seleccionada para
crear los elementos del proyecto.
Hay muchas plantillas de proyectos disponibles en Visual Studio. Estas plantillas facilitan
los elementos básicos necesarios para desarrollar cada tipo de proyecto. Siempre contienen
al menos el archivo del proyecto, más un ejemplar del elemento más utilizado para el tipo
de proyecto correspondiente. Por ejemplo, para un proyecto de biblioteca de clases, se crea
un archivo fuente que contiene un boceto de clases. Las plantillas proporcionan también
referencias e importaciones por defecto para las bibliotecas y los espacios de nombres más
útiles en función del tipo de proyecto.
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Deployment
System.Drawing
ShareVideos
System.Windows.Forms
System.Xml
System.Xml.Linq
Biblioteca de clases
Esta plantilla de proyecto se puede utilizar para crear clases y componentes que luego
podrán ser compartidos con otros proyectos. Los siguientes elementos se añaden
automáticamente al proyecto:
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Xml
System.Xml.Linq
Como la plantilla anterior, este tipo de proyecto permite crear una biblioteca de clases
utilizable en otros proyectos. Esta biblioteca es más específica, ya que está dedicada a la
creación de controles, utilizables luego en una aplicación Windows. Estos controles
amplían el cuadro de herramientas disponible en las aplicaciones Windows. Los siguientes
elementos se añaden automáticamente al proyecto:
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Drawing
System.Windows.Forms
System.Xml
ShareVideos
System.Xml.Linq
Aplicación de consola
Este tipo de aplicación está destinado a ser ejecutado a partir de la línea de comando de una
ventana de línea de comandos. Por supuesto, está diseñada sin interfaz gráfica, las
entradas/salidas se hacen desde la línea de comando y hacia la consola.
Este tipo de aplicación es muy práctico para realizar pruebas con Visual Basic, ya que
permite concentrarse en un punto especial, sin tener que preocuparse por el aspecto de la
presentación de la aplicación.
Muchos ejemplos de este libro se basan en una aplicación de consola. Sin embargo, hay que
admitir que, a pesar de su sencillez de creación, este tipo de aplicación ha quedado
obsoleto.
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Deployment
System.Xml
System.Xml.Linq
Servicio de Windows
Se diseña este tipo de proyecto para la creación de aplicaciones que se ejecutan como tarea
en segundo plano en el sistema. El lanzamiento de este tipo se puede efectuar
automáticamente al iniciar el sistema y no necesita que una sesión de usuario esté abierta
para poder ejecutarse.
ShareVideos
Una clase de base con el esqueleto de los procedimientos OnStart y OnStop
llamados automáticamente al iniciar y al parar el servicio.
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Deployment
System.ServiceProcess
System.Xml
System.Xml.Linq
Aplicación WPF
Esta plantilla de proyecto permite beneficiarse del nuevo sistema de visualización gráfica
de Windows, utilizado en Windows Vista y en las versiones posteriores.
PresentationCore
PresentationFramework
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Xaml
System.Xml
System.Xml.Linq
WindowsBase
ShareVideos
Al igual que la librería de controles Windows, este tipo de proyecto permite extender el
cuadro de herramientas ya disponible en las aplicaciones WPF. Se añaden los siguientes
elementos al proyecto:
PresentationCore
PresentationFramework
System
System.Core
System.Data
System.Data.DataSetExtensions
System.Xaml
System.Xml
System.Xml.Linq
WindowsBase
Este tipo de proyecto también tiene por objetivo extender el cuadro de herramientas
disponible para las aplicaciones WPF. A diferencia del tipo de proyecto anterior, los
controles no han sido creados completamente, ya que están basados en controles existentes
cuyas características extienden.
Proyecto vacío
Debe utilizar esta plantilla cuando desee crear su propio tipo de proyecto. Solo el archivo
proyecto está creado. A cambio, no se añade ningún otro elemento automáticamente y no se
crea ni importa ninguna referencia.
Puede crear su propia plantilla de proyecto según sus costumbres de desarrollo y hacerlo de
tal manera que aparezca entre las plantillas predefinidas.
ShareVideos
para la asignación de propiedades por defecto al proyecto. Estos datos están
contenidos en un archivo XML con la extensión .vstemplate.
Un archivo para el proyecto (.vbproj).
Los archivos fuente y recursos incluidos por defecto durante la creación de un
proyecto a partir de esta plantilla.
Estos archivos deben ser comprimidos en un archivo zip. El archivo zip debe contener los
archivos individualmente, y no la carpeta en la que están ubicados.
<VSTemplate Version="3.0.0"
xmlns="http://schemas.microsoft.com/developer/vstemplate/2005"
Type="Project">
<TemplateData>
<Name>ApliPerso</Name>
<Description>creación de un proyecto con una configuración
personalizada
</Description>
<ProjectType>VisualBasic</ProjectType>
<DefaultName>ApliPerso</DefaultName>
</TemplateData>
<TemplateContent>
<Project File="ApliPerso.vbproj">
<ProjectItem>AssemblyInfo.vb</ProjectItem>
<ProjectItem>Hoja1.vb</ProjectItem>
<ProjectItem>Hoja1.Designer.vb</ProjectItem>
<ProjectItem>Hoja1.resx</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>
En la sección Name
En la sección Description
En la sección ProjectType
En la sección DefaultName
ShareVideos
El nombre utilizado por defecto para todos los proyectos creados desde esta plantilla. Se
completa este nombre con un sufijo numérico en la creación del proyecto.
El nombre del archivo de proyecto asociado a la plantilla. Este archivo debe estar presente
en el archivo zip de la plantilla.
Los elementos que forman parte del proyecto. Estos elementos también deben estar
disponibles en el archivo zip.
La modificación de una plantilla consiste en utilizar un archivo zip existente que contiene
los elementos necesarios para el proyecto y añadir elementos adicionales. Si se añaden
archivos a la plantilla, se deben ubicar en el archivo zip y también referenciarlos en el
archivo .vstemplate. Las plantillas predefinidas de Visual Studio se colocan en el directorio
C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\
ProjectTemplates\VisualBasic. Para que se tengan en cuenta las modificaciones, se debe
actualizar la caché utilizada por Visual Studio. Para ello:
Introduzca el comando devenv /setup. Sea paciente, ya que este comando tarda bastante en
ejecutarse. Después de la ejecución del comando, sus modificaciones están disponibles en
la plantilla de proyecto.
Puede que sea la solución más sencilla para construir una plantilla de proyecto.
Una vez finalizado su proyecto, expórtelo como plantilla. El menú Archivo - Exportar
plantilla lanza un asistente para guiarle durante la creación de la plantilla.
Este primer cuadro de diálogo le propone elegir el proyecto que quiere exportar, junto con
la sección del cuadro de diálogo de creación de proyecto en la que se colocará la futura
plantilla.
ShareVideos
Este segundo cuadro de diálogo le invita a elegir un icono para su plantilla de proyecto, un
nombre para la plantilla y una descripción. Dos opciones adicionales le permiten tener en
cuenta inmediatamente la nueva plantilla en Visual Studio y presentar el resultado de la
generación al mostrarle el contenido del archivo zip creado. Después de validar este último
cuadro de diálogo, la nueva plantilla de proyecto está disponible en Visual Studio.
Este método es muy sencillo para construir una nueva plantilla de proyecto y evita darle
vueltas a la sintaxis del archivo .vstemplate.
Configure el entorno Visual Studio para permitirle acceder a las plantillas. Esta
modificación se efectúa gracias al cuadro de diálogo disponible desde la opción del menú
Herramientas - Opciones.
2. Modificación de un proyecto
Las plantillas de proyectos son muy útiles para crear rápidamente las bases de una
aplicación, pero a menudo necesitarán la inclusión de nuevos elementos al proyecto. Estas
inclusiones se hacen por medio del menú contextual del explorador de proyectos.
Active la opción Agregar - Nuevo elemento para elegir el tipo de elemento que desea
añadir al proyecto. El cuadro de diálogo propone un número impresionante de elementos
que se pueden añadir a un proyecto.
ShareVideos
del explorador de proyectos. Un cuadro de diálogo le propone la selección del archivo que
desea incluir en el proyecto.
El botón Agregar de este cuadro de diálogo dispone de un menú que permite añadir el
archivo normalmente (se lleva a cabo en ese momento una copia local del archivo) o crear
un vínculo en el archivo (se utiliza el archivo original). Hay que ser prudente con esta
posibilidad, ya que el archivo «no pertenece» realmente a la aplicación, y se puede
compartir entre varias aplicaciones. Si se suprime el archivo del disco, no se podrá compilar
las aplicaciones que lo utilizan.
Para quitar un elemento de un proyecto, hay dos opciones accesibles a través del menú
contextual del explorador de soluciones:
Los proyectos son elementos fundamentales en la creación de una aplicación con Visual
Basic. Poseen muchas propiedades que permiten modificar sus comportamientos en el
momento del diseño o de la ejecución de la aplicación. El conjunto de las propiedades está
accesible a través de un cuadro de diálogo que presenta, mediante pestañas, las diferentes
secciones de configuración de un proyecto.
Active este cuadro de diálogo con la opción Propiedades del menú contextual del
explorador de soluciones o con el botón de la barra de herramientas del explorador de
proyecto.
ShareVideos
a. Propiedades de aplicación
Esta propiedad indica la versión del Framework necesaria para ejecutar la aplicación. De
manera predeterminada, este valor es igual al seleccionado durante la creación del proyecto.
Tipo de aplicación
Esta propiedad determina el tipo de aplicación generada por la compilación del proyecto.
La plantilla elegida en el momento de la creación del proyecto suele determinar esta
propiedad, que se modifica pocas veces, ya que depende mucho del código de su proyecto
(si diseñó su aplicación como una aplicación Windows y desea considerarla como una
aplicación para consola, ¡se arriesga a tener mucho código inútil!).
Formulario de inicio
Todos los elementos del proyecto, accesibles desde otro proyecto, pertenecen al espacio de
nombres definido por esta propiedad. Esta viene a añadirse a los posibles espacios de
nombres definidos a nivel del propio código. Por defecto, esta propiedad corresponde al
nombre del proyecto, pero se puede modificar de manera independiente a este. Incluso
puede estar vacía, lo que le permite generar espacios de nombres directamente en el código.
Icono
ShareVideos
Esta propiedad configura el icono asociado al archivo compilado del proyecto cuando se
visualiza en el explorador de Windows o cuando la aplicación aparece en la barra de tareas
de Windows.
Información de ensamblado
Esta opción permite facilitar datos sobre el código generado por la compilación del
proyecto. Un cuadro de diálogo permite rellenar diferentes secciones relativas a la
descripción del proyecto.
El usuario de su código podrá consultar estos datos visualizando las propiedades del
archivo compilado en el explorador de Windows.
Esta opción le permite determinar el nivel de ejecución requerido por la aplicación. Dicha
información es utilizada por el mecanismo User Account Control (UAC) de Windows.
Indica bajo qué identidad correrá el código de la aplicación. Hay tres valores posibles:
Esta opción determina si quiere activar una interacción más desarrollada entre la aplicación
y el sistema operativo. Si esta opción está activa, el elemento de inicio de la aplicación debe
ser una hoja. El uso de esta opción hace que las siguientes propiedades pasen a estar
disponibles.
Por defecto, puede lanzar todas las instancias de una misma aplicación que quiera en una
única máquina. Sin embargo, a veces puede ser útil autorizar el funcionamiento de una sola
instancia de la aplicación en un determinado momento (problema de licencia de usuario,
conservación de los recursos de la máquina...). La activación de esta opción garantiza que
ShareVideos
no haya más de una instancia de la aplicación en ejecución en la máquina. Si se lanza una
nueva instancia cuando ya hay otra en el sistema operativo, el foco se pasa directamente a
la instancia existente. A nivel de la aplicación, el evento StartupNextInstance también se
desencadenará.
Modo de autenticación
Por defecto, las aplicaciones Visual Basic utilizan la autenticación de Windows para
identificar el usuario de la aplicación. Si quiere gestionar usted mismo esta identificación,
debe utilizar la opción Definido para la aplicación.
Modo de apagado
Pantalla de presentación
Esta opción permite acceder a los gestores de eventos del objeto de la aplicación. Los
gestores de eventos permiten reaccionar frente a diferentes situaciones:
Startup
La aplicación arranca.
StartUpNextInstance
Shutdown
ShareVideos
La aplicación se cierra.
UnHandledException
NetworkAvailabilityChanged
Para poder utilizar elementos externos disponibles en un ensamblado, tiene que añadir una
referencia a este ensamblado.
Esta lista se puede actualizar con los botones Agregar, Quitar y Actualizar, que permiten
respectivamente añadir una referencia local o una referencia Web, eliminar una referencia o
actualizar una referencia Web.
El botón Rutas de acceso de referencia permite indicar los directorios adicionales que
contienen ensamblados disponibles. Estos directorios se analizan al abrir el cuadro de
diálogo para añadir referencias, y los eventuales ensamblados que contienen se añaden a la
lista de ensamblados disponibles. Cuando se añade una referencia a un ensamblado, en la
primera ejecución de la aplicación se utiliza el archivo original. Puede utilizar la creación
automática de una copia local de este archivo en el directorio de la aplicación. Para ello:
El botón Referencias sin utilizar muestra la lista de todas las referencias no utilizadas en
el código y le propone eliminarlas del proyecto.
Los elementos disponibles en los ensamblados referenciados son, sin duda, parte de un
namespace. Para poderlos utilizar fácilmente, es posible importar automáticamente algunos
espacios de nombres. La lista Espacios de nombres importados recoge los espacios de
nombre importados automáticamente en todos los códigos del proyecto. Puede completar
esta lista eligiendo en el cuadro de texto el nombre del espacio de nombres importado y
validando con el botón Agregar importación del usuario.
ShareVideos
c. Propiedades de depuración
Acción de inicio
Proyecto de inicio indica que el propio proyecto debe ser ejecutado. Solo se puede
utilizar para los proyectos de aplicación Windows o para los proyectos de aplicación
de consola.
Programa externo de inicio permite provocar la ejecución de una aplicación
externa que se va a encargar de realizar llamadas al código de nuestro proyecto. Se
utiliza esta opción para la depuración de las librerías de clases.
Iniciar explorador con la dirección URL es idéntica a la opción anterior, excepto
que la aplicación iniciada es una aplicación Web.
Opciones de inicio
Usar máquina remota autoriza la depuración de una aplicación que se ejecuta en otra
máquina. En este caso, se debe indicar el nombre de la máquina remota en la cual se va a
ejecutar el código.
Habilitar depuradores
Estas opciones determinan los diferentes tipos de depuradores activos, como complemento
del depurador de código gestionado de Visual Studio.
d. Propiedades de compilación
ShareVideos
Ruta de acceso de los resultados de la compilación
Option Explicit
Esta opción permite exigir o no que se declare cualquier variable antes de su utilización. Se
aplica a todos los archivos fuente de un proyecto. Es posible, sin embargo, modificar esta
opción para un archivo en concreto, añadiendo la directiva Option Explicit On u Option
Explicit Off al principio de un archivo.
Option Strict
Esta opción permite controlar las conversiones realizadas. Si se intenta realizar una
conversión restrictiva, el compilador genera un error. Como la anterior opción, esta se
aplica a todos los archivos fuente de un proyecto y se puede modificar para un archivo en
concreto con el comando Option Strict On u Option Strict Off.
Option Compare
Option infer
Esta opción indica si la inferencia de tipos de variables locales está activa. Con cada
opción, el mismo compilador determina el tipo de variable de acuerdo con el tipo que se le
asigna.
CPU de destino
Esta opción especifica el procesador para el que se debe generar el código. Hay tres
opciones disponibles:
Preferencia de 32 bits
ShareVideos
Esta opción indica que la aplicación siempre se ejecutará como una aplicación de 32 bits,
incluso en un sistema de 64 bits. Solo está disponible si la unidad central de destino está
definida como AnyCPU.
Configuración de advertencias
Puede también deshabilitar todas las advertencias utilizando la opción Deshabilitar todas
las advertencias o, al revés, tratarlas todas como errores con la opción Considerar todas
las advertencias como errores.
Con esta opción el compilador busca en el código los comentarios especiales colocados
gracias a los caracteres ’’’ y los utiliza para generar el archivo de documentación. Este
archivo se crea dentro del directorio en el que se genera el archivo compilado.
Eventos de compilación
Cada uno de los comandos se puede introducir en la zona de texto correspondiente. Los
botones Edición anterior a la compilación y Edición posterior a la compilación abren
una ventana de edición que facilita la introducción del comando.
También este cuadro de diálogo propone una lista de macros que permite la recuperación y
el uso por su comando de ciertos parámetros del proyecto. El ejemplo presentado en la
figura anterior efectúa una copia completa del directorio de la aplicación en el directorio
C:\copia de seguridad, antes de cada generación.
La ejecución del comando después de la generación puede ser condicional y ocurrir solo en
caso de generación exitosa o si la generación actualizó la salida del proyecto.
ShareVideos
Si un comando debe ejecutar un archivo .bat después de la generación, la llamada de este
debe venir precedida de la palabra clave call.
Esta opción abre un cuadro de diálogo que permite la configuración avanzada del
compilador.
e. Recursos de un proyecto
Se utilizan los recursos para externalizar ciertos elementos de una aplicación. Permiten
realizar rápidamente modificaciones sencillas en una aplicación sin tener que buscar entre
miles de líneas de código. La utilización más clásica consiste en separar del código las
constantes cadena de caracteres. También puede crear recursos de iconos, imágenes,
archivos de texto o audio. Este cuadro de diálogo gestiona todos los recursos.
Para cada recurso, indique un nombre y un valor. Por supuesto, el nombre será utilizado en
el código para poder recuperar el valor.
En función del tipo de recurso, tiene a su disposición un editor adaptado para modificarlo.
Los recursos pueden ser relacionados o vinculados, en función de su tipo. Un recurso
relacionado está almacenado en su propio archivo y el archivo Resources.resx contiene
simplemente un vínculo hacia el archivo original. Un recurso vinculado está almacenado
directamente en el archivo Resources.resx de la aplicación. En todos los casos, se
compilarán los recursos en el ejecutable de la aplicación.
Veamos ahora cómo acceder a los recursos a partir del código de la aplicación. Todos los
recursos son accesibles a través de la propiedad Resources del objeto My. El ejemplo
siguiente utiliza:
ShareVideos
Un archivo de sonido (Musica).
f. Parámetros d
Veamos las reglas que se deben respetar para nombrar las variables:
Al especificar un tipo para una variable, indicamos qué datos vamos a poder almacenar en
esta variable.
ShareVideos
Los tipos por referencia: la variable contiene la dirección de memoria donde se
almacena la información.
Los diferentes tipos de variables disponibles están definidos a nivel del propio
Framework. Puede utilizar igualmente los alias definidos a nivel de VB, posiblemente más
explícitos. El tipo System.Int32 definido a nivel del Framework puede ser sustituido por el
tipo integer en Visual Basic.
El ahorro de memoria parece irrisorio para una variable única, pero se vuelve interesante en
el caso de usar matrices de gran dimensión.
4
Single -3.40282347E+38 3.40282347E+38
bytes
ShareVideos
8 Se
Double -1.7976931348623157E+308 1.7976931348623157E+308
bytes deben
tener en
-79.228.162.514.264.337.593. 79.228.162.514.264.337.593. 16
Decimal cuenta
543.950.335 543.950.335 bytes
las
mismas consideraciones de optimización que para las variables enteras. En este caso, la
velocidad de ejecución máxima se obtiene con el tipo Double. El tipo Decimal es más
recomendable para cálculos financieros, en los cuales se prohíben los errores de redondeo,
en detrimento de la velocidad de ejecución del código.
El tipo Char (carácter) se utiliza para almacenar un único carácter. Una variable de tipo
Char utiliza dos bytes para almacenar el código Unicode del carácter. En el juego de
caracteres Unicode, los primeros 128 caracteres son idénticos al juego de caracteres ASCII,
los caracteres siguientes hasta 255 corresponden a los caracteres especiales del alfabeto
latino (por ejemplo, los caracteres acentuados) el resto se utiliza para símbolos o para los
caracteres de otros alfabetos.
Para poder almacenar cadenas de caracteres, conviene utilizar el tipo String, que representa
una serie de cero a 2.147.483.648 caracteres. Las cadenas de caracteres son invariables ya
que, durante la asignación de un valor a una cadena de caracteres, se reserva algo de
espacio en memoria para el almacenamiento. Si esta variable recibe luego un nuevo valor,
el sistema le asigna una nueva ubicación en memoria. Afortunadamente, este mecanismo es
transparente para nosotros y la variable siempre hará referencia de forma automática al
valor que le está asignado. Con este mecanismo, las cadenas de caracteres pueden tener un
tamaño variable. El espacio ocupado en memoria se ajusta automáticamente a la longitud
de la cadena de caracteres.
Para asignar una cadena de caracteres a una variable, el contenido de la cadena se debe
introducir entre " ", como en el ejemplo siguiente:
Ejemplo
NombreDelCapitan = "Garfio"
Hay muchas funciones que permiten manipular las cadenas de caracteres y serán detalladas
más adelante en este capítulo. Existe un tipo String en forma de clase que también permite
la manipulación de cadenas de caracteres. En este caso, la manipulación se hará mediante
los métodos disponibles en la clase String. Estos también se detallarán más adelante en este
capítulo.
El tipo Booleano
El tipo Booleano permite utilizar una variable que puede tener dos estados: verdadero/falso,
sí/no, on/off.
ShareVideos
Su asignación se realiza directamente con los valores True o False, como en el ejemplo
siguiente:
Disponible=True
Modificable=False
También es posible asignar un valor numérico a una variable de tipo Booleano. En este
caso, un valor igual a cero se considera como un booleano False y cualquier otro valor
positivo o negativo será considerado como un booleano True.
El tipo Date
Su asignación se realiza poniendo los valores entre los signos #, como en el ejemplo
siguiente:
Hoy=#02/28/2011 14:58:23#
El formato utilizado para asignar un valor a una variable de tipo Date será siempre
#mes/día/año horas:minutos:segundos# independientemente del formato de fecha
configurado en su sistema operativo. Las horas se pueden especificar en formato de 12
horas o 24 horas. De todas formas, el entorno de desarrollo valida la recogida de datos y
transformará siempre la fecha al formato 12 horas. El ejemplo precedente será modificado
por el entorno de desarrollo de la siguiente manera:
Si asigna a una variable de tipo Date un valor con solo la hora, Visual Basic considerará
que se trata del 1 de enero del año 1 a la hora que habrá indicado.
Ejemplo
Día=#12:35:30#
Inversamente, ¡si asigna a una variable de tipo Date un valor con solo la fecha, Visual Basic
considerará que se trata del día que ha indicado, a medianoche!
El tipo Object
Este puede ser el tipo más universal de Visual Basic. En una variable de tipo Object, se
puede almacenar cualquier cosa. En realidad, este tipo de variable no almacena nada. La
variable no contendrá el propio valor, sino la dirección, en la memoria de la máquina,
donde se podrá encontrar el valor de la variable. Tranquilícese, todo este mecanismo es
transparente, y nunca tendrá que manipular las direcciones de memoria directamente.
ShareVideos
Una variable de tipo Object podrá hacer referencia, por tanto, a cualquier otro de tipo de
valor, incluidos tipos numéricos simples. Sin embargo, el código será menos rápido en
razón del uso de una referencia.
A veces ocurre que en algunas circunstancias una variable no tiene un valor bien definido.
Es, por ejemplo, el caso durante la recuperación de información procedente de una base de
datos si, para algunos campos, no se ha asignado ningún valor en la base. ¿Cómo
representar esta situación utilizando las variables de Visual Basic? Una solución consiste en
utilizar un valor que no tiene ningún significado para la aplicación. Por ejemplo, para una
variable numérica que representa un código postal en la aplicación, se puede considerar
asignar a esta variable un valor negativo en caso de que el código no esté indicado. El resto
del código debe, por supuesto, tener en cuenta esta convención. Para cierto tipo de datos,
esta solución no se puede considerar. Pongamos el caso de una variable del tipo Booleano
en la cual solo hay 2 valores permitidos, «true» o «false». ¿Cómo representar que el valor
de la variable no ha sido asignado?
Para encarar este problema, Visual Basic propone los tipos Nullables, que permiten que las
variables de tipo valor no contengan ninguna información. Para activar esta funcionalidad
en una variable solo hace falta utilizar el carácter ’?’ a continuación del nombre de la
variable o al final de la declaración del tipo, como muestra el ejemplo siguiente.
En cambio, hay que ser prudente durante la utilización de una variable de este tipo y
verificar antes de usarla si contiene realmente un valor. Para ello, puede consultar la
propiedad HasValue de la misma variable con objeto de determinarlo. Si es el caso, este
valor está disponible gracias a la propiedad Value de la variable. Esta propiedad es de solo
lectura, ya que la asignación de un valor se hace directamente en la variable.
CodigoPostal = 17000
If CodigoPostal.HasValue Then
Console.WriteLine(CodigoPostal)
Else
Console.WriteLine(”Código postal vacío”)
End If
ShareVideos
Una variable que contiene un valor puede pasar al estado ’no asignada’ si se le asigna el
valor nothing.
El uso de variables del tipo booleano nullable con los operadores lógicos ’and’ y ’or’ es
complicado. A continuación, se muestra la tabla de verdad de estos dos operadores con
variables nullables.
B1 B2 B1 and B2 B1 or B2 Por
último,
nothing nothing nothing nothing cabe
nothing true nothing true aclarar
nothing false false nothing el uso
de un
true nothing nothing true boolean
true true true true o
true false false true nullable
en una
false nothing false nothing
estructu
false true false true ra
false false false false condici
onal.
Observe el código siguiente:
c. Conversiones de tipos
Las conversiones de tipos consisten en transformar una variable de un tipo a otro tipo. Las
conversiones se pueden efectuar hacia un tipo superior o inferior.
Si se utiliza una conversión hacia un tipo inferior, hay riesgo de pérdida de información.
Por ejemplo, la conversión de un tipo Double hacia un tipo Long causará la pérdida de la
parte decimal del valor.
Ejemplo
ShareVideos
Dim x As Double
Dim y As Long
x = 21.123456789012344
y = x
Console.WriteLine("valor de x: " & x)
Console.WriteLine("valor de y: " & y)
Se muestra:
valor de x: 21,1234567890123
valor de y: 21
Una opción del compilador permite verificar la existencia de este tipo de conversión.
Pueden también ser implícitas o explícitas según el código utilizado. Las conversiones
implícitas se realizan simplemente asignando una variable de un tipo a una variable de otro
tipo. Las conversiones explícitas necesitan el uso de palabras claves concretas, que suele
tener el formato Cxxx o xxx, y que corresponde al tipo en el que se convertirá el valor.
ShareVideos
CUShort UShort Otro operador (CType) permite la
conversión hacia un tipo estándar de
lenguaje, pero sobre todo hacia un tipo personalizado, como por ejemplo una clase.
Las conversiones desde cadenas de caracteres y hacia cadenas de caracteres son más
específicas.
Currency
Formato monetario tal como está definido en las opciones regionales y de idioma del panel
de control del sistema.
Ejemplo: format(12.35,"Currency")
Resultado: 12,35 €
Fixed
Utiliza al menos un carácter para la parte entera y al menos dos caracteres para la parte
decimal de un número. El separador decimal aparece tal como está definido en las opciones
regionales y de idioma del panel de control del sistema.
Ejemplo: format(.2,"Fixed")
Resultado: 0,20
ShareVideos
Percent
Ejemplo: format(.2,"Percent")
Resultado: 20,00%
Standard
Formato numérico tal como está definido en las opciones regionales y de idioma del panel
de control del sistema.
Ejemplo: format(245813.5862,"Standard")
Resultado: 245.813,59
Scientific
Ejemplo: format(245813.58,"Scientific")
Resultado: 2,46E+05
Ejemplo: format(245813.5862,"E")
Resultado: 2,458136E+005
Ejemplo: format(245813,"X")
Resultado: 3C035
Yes/No
True/False
On/Off
ShareVideos
Devuelve No, False, Off si el valor es igual a cero; si no, devuelve Yes, True, On para el
resto de los valores.
Reserva una ubicación para un carácter numérico. Los ceros no significativos se visualizan.
Ejemplo: format(245813.12,"00000000000.0000")
Resultado: 00000245813,1200
Ejemplo: format(245813.12,"###########.####")
Resultado: 245813,12
Permite utilizar un carácter con un significado especial como carácter ordinario en una
cadena de formateo. En el siguiente ejemplo, el carácter \ hace que el carácter # pierda su
significado especial.
ShareVideos
Formato de Fecha corto y formato de Hora tal y como está definido en las opciones
regionales y de idioma del panel de control del sistema.
Formato de Fecha largo tal y como está definido en las opciones regionales y de idioma del
panel de control del sistema.
Formato de Fecha corto tal y como está definido en las opciones regionales y de idioma del
panel de control del sistema.
Resultado 17/10/05
Formato de Hora tal y como está definido en las opciones regionales y de idioma del panel
de control del sistema.
Resultado 11:45:30
Formato ’ordenable’.
Resultado: 2005-10-17T11:47:30
ShareVideos
ddd Nombre del día de la semana abreviado
y Año en una cifra. Si es el único carácter de la cadena de formateo, en este caso se debe
utilizar %y
La función Val permite la conversión de una cadena de caracteres a valor numérico. Lee la
cadena como parámetro hasta que encuentra un carácter que no sea una cifra, un espacio,
una tabulación o un punto. Transforma después esta porción de cadena en valor numérico,
teniendo en cuenta los eventuales parámetros de formateo definidos a nivel del sistema,
como por ejemplo el separador de millares. Los caracteres «&H» o «&O» colocados al
principio de la cadena indican que el valor se expresa en hexadecimal o en octal.
ShareVideos
Ejemplo: val ("&H7FFF")
devuelve
32767.0
Por defecto, el compilador Visual Basic considera que toda variable que aparece en una
aplicación debe haber sido declarada. Puede modificar esta opción del compilador
añadiendo la línea siguiente al código:
Esta opción debe ser la primera línea del archivo fuente, y será aplicada a todo el código del
archivo.
Con esta opción, ya no existe la obligación de declarar una variable antes de utilizarla.
Aunque parezca cómoda, esta solución puede producir errores en el código difíciles de
encontrar. Observe el código siguiente:
Ningún problema al compilar, y sin embargo la función nos devuelve siempre un valor
igual a cero. Si nos fijamos mejor en el código, nos damos cuenta de que hay un error en la
línea Return ValorTempor: faltan dos letras en el nombre de la variable ValorTemporal. A
la hora de compilar, Visual Basic considera que se trata de una nueva variable y por lo tanto
la inicializa a cero. Perdido entre cientos de líneas de código, este tipo de errores puede ser
muy difícil de encontrar. Dejando la opción de declaración de variables como obligatoria,
habría detectado el error al compilar la aplicación.
Veamos cómo declarar las variables en Visual Basic. La instrucción básica para la
declaración de una variable es la instrucción Dim.
ShareVideos
Si se omite el valor inicial, la variable se inicializará a cero si corresponde a un tipo
numérico, a una cadena de caracteres vacía si es de tipo String, al valor Nothing si es de
tipo Object y a false si es un Booleano.
Si se especifican varios nombres, todas las variables correspondientes serán del tipo
indicado.
e. Inferencia de tipos
Hemos visto en las secciones precedentes que es recomendable declarar las variables antes
de su uso. Sin embargo, en algunos casos, se puede considerar dejar que el compilador
realice una parte del trabajo. Gracias a la inferencia de tipos, el compilador puede
determinar el tipo que se debe utilizar para una variable local declarada sin la cláusula as.
Para ello, se basa en el tipo de la expresión utilizada para inicializar la variable. En el
ejemplo siguiente la variable es considerada como una cadena de caracteres.
Para asegurarse de que esta variable es considerada realmente como una cadena de
caracteres, basta con pedir a IntelliSense qué nos propone para utilizar esta variable.
En efecto, aquí tenemos a nuestra disposición los métodos y propiedades del tipo String.
ShareVideos
Ámbito a nivel de bloque
Solamente el código del bloque podrá trabajar con la variable (por ejemplo, en un bucle for
next). Sin embargo, si el mismo bloque de código se ejecuta varias veces durante la
ejecución de un procedimiento o función, en caso de un bucle Do Loop por ejemplo, la
variable solo será creada la primera vez que se ejecuta el código, conservando su valor de
una pasada a otra. Para modificar este funcionamiento, basta con inicializar la variable en el
momento de su declaración. Solo puede utilizarse la palabra clave Dim para declarar una
variable dentro de un bloque de código.
Ejemplo
Dim i As Integer
For i = 0 To 5
Dim j As Integer
Dim k As Integer = 0
j = j + 1
k = k + 1
Console.WriteLine("valor de j:{0}", j)
Console.WriteLine("valor de k:{0}", k)
Next
Muestra:
valor de j:1
valor de k:1
valor de j:2
valor de k:1
valor de j:3
valor de k:1
valor de j:4
valor de k:1
valor de j:5
valor de k:1
valor de j:6
valor de k:1
ShareVideos
Ámbito a nivel de espacio de nombres
La variable se podrá utilizar en el código del espacio de nombres incluso si el código está
situado en distintos módulos. Si no declara explícitamente ningún espacio de nombres en su
código, siempre existirá el espacio de nombres por defecto, y se podrá hablar en ese caso de
ámbito de proyecto.
El nivel de acceso de una variable se combina con el alcance de la variable y determina qué
porción de código puede leer y escribir en la variable. Un conjunto de palabras claves
permite controlar el nivel de acceso. Se utilizan en el lugar de la palabra clave Dim a la
hora de la declaración de la variable.
Public
Los elementos declarados con la palabra clave Public serán accesibles desde cualquier parte
del código del proyecto en el que son declarados, y desde cualquier otro proyecto que
referencie el proyecto en el que se han declarado. La palabra clave Public no puede
utilizarse para declarar una variable dentro de un procedimiento o función.
Protected
Esta palabra clave solo se puede utilizar en el interior de una clase. Permite restringir el
acceso a la variable, al código de la clase y al código de todas las clases que heredan de
ella.
Friend
Los elementos declarados con esta palabra clave serán accesibles desde el ensamblado en el
que han sido declaradas. No puede utilizarse esta palabra clave en el interior de un
procedimiento o función.
Protected Friend
Este nivel de acceso es la unión de los niveles de acceso Protected y Friend. Hace visible la
variable al conjunto del ensamblado en el cual está declarada y a todas las clases que
heredan de aquella en la que está declarada.
Private
Los operadores
ShareVideos
Los operadores son palabras claves del lenguaje que permiten la ejecución de operaciones
sobre el contenido de ciertos elementos, en general variables, constantes, valores literales o
resultados de funciones. La combinación de uno o varios operadores y elementos en los
cuales los operadores van a apoyarse se llama una expresión. Estas expresiones se valoran
en el momento de su ejecución, en función de los operadores y valores que tienen
asociados.
ShareVideos
4. Los operadores de comparación
Hay que tener cuidado con las comparaciones de cadenas de caracteres, ya que los
resultados obtenidos pueden variar en función de las opciones elegidas en el compilador.
Las opciones del compilador pueden modificarse en el cuadro de diálogo de propiedades
del proyecto.
ShareVideos
Con la opción Text, el compilador no hará distinción entre minúsculas y
mayúsculas en una comparación.
La opción Binary exigirá una estricta igualdad para obtener como resultado true.
Para evitar todas estas cuestiones, utilice el operador &. Con este operador, si uno de los
dos operandos no es de tipo String, se transforma automáticamente a este tipo para poder
ser concatenado.
El inconveniente del operador & es que no es muy rápido. Si tiene que realizar muchas
concatenaciones en una cadena, es preferible utilizar la clase StringBuilder.
Ejemplo
ShareVideos
Console.WriteLine("duración para la liebre:
{0} segundos", duracion)
If liebre.Equals(tortuga) Then
Console.WriteLine("las dos cadenas son idénticas")
End If
Resultado de la carrera:
Cuando varios operadores se combinan en una expresión, son valorados en un orden muy
preciso. Las operaciones aritméticas se ejecutan primero, luego las operaciones de
comparación y finalmente los operadores lógicos.
ShareVideos
Los operadores aritméticos también tienen entre ellos un orden de evaluación en una
expresión. El orden de evaluación es el siguiente:
Potencia (ˆ)
Negación (-)
Multiplicación y división (*, /)
División entera (\)
Módulo (Mod)
Suma y resta (+, -), concatenación de cadenas (+)
Concatenación de cadenas (&)
Si necesita un orden de evaluación diferente para su expresión, coloque las porciones que
se deben evaluar primero entre paréntesis, como en la siguiente expresión:
X= (z * 4) ˆ (y * (a + 2))
Usted puede utilizar tantos niveles de paréntesis como desee en una expresión. Es
importante, sin embargo, que la expresión contenga tantos paréntesis de cierre como
paréntesis de inicio; de lo contrario el compilador generará un error.
1. Estructuras de decisión
a. Estructura If
Si la condición es cierta, la instrucción se ejecuta; en este caso, «condición» debe ser una
expresión que devuelve un booleano true o false. Con esta sintaxis, solo se ejecuta la
instrucción situada tras el then, siempre que la condición sea verdadera.
ShareVideos
Para poder ejecutar varias instrucciones en función de una condición, se debe utilizar la
siguiente sintaxis:
If condición then
Instrucción 1
...
Instrucción n
End if
También puede especificar una o varias instrucciones detrás del Else, que serán ejecutadas
si la condición es falsa.
If condición then
Instrucción 1
...
Instrucción n
Else
Instrucción 1
...
Instrucción n
End if
If condición1 then
Instrucción 1
...
Instrucción n
ElseIf Condición 2 then
Instrucción 1
...
Instrucción n
ElseIf Condición 3 then
Instrucción 1
...
Instrucción n
Else
Instrucción 1
...
Instrucción n
End if
ShareVideos
b. Estructura Select case
La estructura select case permite un funcionamiento equivalente, pero de una forma más
clara y sencilla. La sintaxis es la siguiente:
Si los dos valores son iguales, se ejecuta el bloque de código 1 y la ejecución del código
sigue tras el End select.
Si no, el valor obtenido se compara con el valor del case siguiente; si hay correspondencia,
el bloque de código se ejecuta y así sucesivamente hasta el último case.
Si ningún valor de los case concuerda con el obtenido inicialmente, se ejecuta el bloque de
código del case else.
El valor que debe comprobarse puede estar contenido en una variable, pero también puede
ser el resultado de un cálculo. En ese caso, el cálculo se efectúa solo una vez, al principio
del select case. El tipo del valor comprobado puede ser numérico o cadena de caracteres.
Por supuesto, el tipo de la variable comprobada debe corresponder al tipo de los valores en
los diferentes case.
Los valores que es preciso comprobar en los distintos case pueden agruparse como en el
siguiente ejemplo:
ShareVideos
Console.writeline("Mañana")
Case 14 to 17
Console.writeline("Mediodía")
Case 18 to 21
Console.writeline("Tarde")
Case is >=22
Console.writeline("Noche")
Case else
Console.writeline("hora inválida")
End select
También existen tres instrucciones equivalentes al if then else o al select case, pero en una
sola instrucción:
Ejemplo
Ejemplo
resultado=switch(respuesta="si","YES",respuesta="no","NO")
Ejemplo
Todas tienen como objetivo ejecutar un bloque de código un cierto número de veces en
función de una condición.
ShareVideos
a. Estructura While ... End While
While condición
Bloque de código
End While
Do While condición
Bloque de código
Loop
Do
Bloque de código
Loop While condición
Esta sintaxis nos permite garantizar que el bloque de código se ejecutará al menos una vez
ya que la condición será comprobada al final del bloque de código.
Las instrucciones anteriores realizan un bucle si una condición es verdadera. Las dos
sintaxis siguientes efectúan un bucle mientras la condición sigue siendo verdadera.
Do until condición
Bloque de código
Loop
En este caso, el bucle se ejecuta hasta que la condición deje de ser verdadera. Si es
verdadera desde el principio, el bloque de código no se ejecuta. Para garantizar al menos
una ejecución del bloque de código, conviene utilizar la siguiente sintaxis, que comprueba
la condición al final del bloque de código.
Do
Bloque de código
Loop until condición
ShareVideos
El bloque de código se ejecuta al menos una vez, después comprueba la condición, y vuelve
a empezar mientras la condición se cumpla. Como en el caso del bucle while, la instrucción
Exit Do provocará una salida anticipada e incondicional del bucle.
Al principio del bucle, la variable Contador se inicializa con el valor inicial, y se ejecuta el
código. La instrucción next incrementa la variable Contador y realiza la comparación del
valor obtenido con el valor Final del bucle. Si la variable contador es inferior o igual al
valor Final, el bloque de código se ejecuta de nuevo; si no, la ejecución sigue con la
instrucción siguiente a next.
Como en las otras estructuras, se puede salir inmediatamente del bucle for next utilizando
la instrucción exit for.
Otra sintaxis del bucle for next que permite ejecutar un bloque de código para cada
elemento de una matriz o colección. La sintaxis general de esta instrucción es la siguiente:
No hay contador en esta estructura, ya que ella misma efectúa las iteraciones para todos los
elementos de la matriz o colección.
La variable element sirve para extraer los elementos de la matriz o de la colección para que
el bloque pueda manipularlo. El tipo de la variable element debe ser compatible con el tipo
de elementos almacenados en la matriz o la colección. No debe preocuparse por el número
ShareVideos
de elementos, ya que la instrucción for each es capaz de gestionar el desplazamiento en la
matriz o en la colección. A continuación se muestra un ejemplo para aclarar la situación.
Como en el caso del bucle for next, puede provocar una salida del bucle antes de haber
recorrido toda la matriz utilizando la instrucción exit for.
e. Otras estructuras
Hay otras dos estructuras disponibles, destinadas más bien a simplificar el desarrollo:
Esta estructura engloba un bloque de código que utiliza un recurso externo, como por
ejemplo una conexión a un servidor de base de datos. Esta estructura se encarga
automáticamente de liberar el recurso al final del bloque de código. El recurso se puede
crear en la estructura o bien existir previamente y pasarse bajo el control de la estructura.
Al final de la estructura, el recurso se libera llamando al método Dispose.
Ejemplo
ShareVideos
Esta estructura permite ejecutar una serie de operaciones sobre un objeto sin tener que usar
cada vez su nombre. Facilita mucho la claridad del código y mejora también el rendimiento.
Basta especificar, con la ayuda de la palabra clave With, el nombre de la variable que
queremos usar, y hasta la palabra clave End With el nombre estará sobreentendido. Los
diferentes elementos del objeto están disponibles sin usar el nombre de la variable como
prefijo.
Ejemplo
Para que los procedimientos sean reutilizables más fácilmente, tiene la posibilidad de usar
parámetros. Los valores de estos parámetros se especificarán en el momento de la llamada
al procedimiento.
ShareVideos
Los procedimientos operador, utilizados para modificar el funcionamiento de un
operador cuando se aplica a una clase o una estructura.
1. Procedimiento Sub
El código de un procedimiento debe estar situado entre las palabras claves Sub y End Sub.
Se debe nombrar el procedimiento. Se utilizará este nombre durante la llamada. La sintaxis
general de declaración es la siguiente:
Sub MuestraResultado()
Instrucción 1
...
console.System.Writeline( "¡¡¡Funciona!!!") ")
...
Instrucción n
End Sub
Los paréntesis después del nombre se utilizan para especificar las características de los
parámetros que se pasarán durante la llamada. Los paréntesis son obligatorios en la
declaración incluso si no se requiere ningún parámetro para el procedimiento.
Call MuestraResultado()
2. Procedimiento de evento
ShareVideos
gestionado. Por ejemplo, el siguiente procedimiento se ejecutará cuando se
produzca el evento click en el botón BpOK.
La palabra clave Handles indica el objeto y el evento para los cuales se ejecutará el
procedimiento.
3. Función
Una función se declara según el mismo principio que un procedimiento: utilizando las
palabras claves Function y End Function. En cambio, se debe proporcionar un dato
adicional. Como la función debe devolver un valor al código que la llama, debe indicar el
tipo de este valor. La sintaxis de declaración es, por tanto, la siguiente:
En el código de su función, deberá especificar qué valor será devuelto por su función. Para
ello, hay dos opciones:
A continuación se puede utilizar una función en el código en lugar de un valor del mismo
tipo que el devuelto por la función. Puede igualmente utilizarse como un procedimiento
Sub; en ese caso simplemente ignoramos el valor devuelto.
Console.WriteLine(calculo())
calculo()
4. Procedimientos Property
Los procedimientos Property permiten agregar una propiedad a una clase, un módulo o una
estructura. Estos procedimientos se denominan, a veces, «accesores». Se utilizan cuando se
modifica (Set) o se utiliza (Get) la propiedad. Su uso parece similar al uso de una variable;
ShareVideos
se puede asignar un valor a una propiedad o leer el valor de una propiedad. Sin embargo,
existen diferencias abundantes e importantes entre las variables y las propiedades:
Las variables necesitan una sola línea de código para la declaración, mientras que
las propiedades requieren un bloque de código para la declaración.
El acceso a una variable se efectúa directamente, mientras que el acceso a una
propiedad implica la ejecución de un fragmento de código.
El contenido de una variable siempre se recupera tal cual, mientras que el contenido
de una propiedad se puede modificar con el código durante el acceso a la propiedad.
Set
...
End Set (...)
End Property
En esta declaración:
Como para cualquier otro elemento declarado en Visual Basic, puede indicar un nivel de
acceso para la propiedad. Se aplica tanto al bloque Get como al Set. También puede añadir
un modificador del nivel de acceso para cada uno de los bloques Get y Set. En este caso,
deben ser más restrictivos que el indicado a nivel de la propiedad.
Las propiedades también pueden ser de solo lectura o de solo escritura. Para ello, debe
añadir ReadOnly o WriteOnly delante del nombre de la propiedad, eliminando, claro está,
el bloque de Set en el caso de una propiedad de solo lectura, o el bloque Get en el caso de
una propiedad de solo escritura.
ShareVideos
5. Los procedimientos operador
Este tipo de procedimiento permite redefinir un operador estándar del lenguaje para
utilizarlo en tipos personalizados (clase o estructura). Tomemos un ejemplo con la
estructura cliente ya utilizada.
Para que este código funcione, debemos indicarle el procedimiento que es preciso seguir
para realizar esta operación. Por lo tanto, debemos redefinir el operador + para utilizarlo
con dos clientes.
325
cliente1cliente2
nombre1nombre2
Para que el código sea reutilizable más fácilmente, los valores manipulados por los
procedimientos y funciones pueden pasarse como parámetros en el momento de la llamada
del procedimiento o función. Durante la declaración del procedimiento, deberá especificar
la lista de los parámetros que se esperará. Esta lista se sitúa entre los paréntesis de la
ShareVideos
declaración del procedimiento. Debe indicar, para cada parámetro, su nombre y su tipo. Si
se esperan varios parámetros, conviene separarlos con una coma.
Cuando se llama al procedimiento, se deberá indicar un valor para cada uno de los
parámetros esperados. Tomemos un ejemplo de declaración y de utilización:
PBruto = 100
PNeto = CalculoPNeto (PBruto,8)
Console .Writeline (PNeto)
Para pasar una variable como parámetro a un procedimiento (el PBruto del ejemplo
anterior), existen dos posibilidades:
Aunque no sea necesario, la palabra clave ByVal también está disponible para
indicar un paso por valor.
ShareVideos
o Cuando se declara un parámetro opcional, todos los declarados a
continuación deben ser también opcionales. La declaración siguiente no es
válida, ya que el tercer parámetro debe ser opcional:
o Function CalculoPNeto(PBruto as double, Optional IVA as
double =
o 21 divisa as string) as double
La sintaxis es la siguiente:
Cuando se llama al procedimiento, hay dos posibilidades para indicar el valor utilizado por
cada parámetro:
El pase por posición: los valores de los parámetros deben aparecer en el mismo
orden que han sido declarados en el procedimiento. Si quiere omitir un valor para
un parámetro, debe reservar su sitio en la llamada del procedimiento.
Resultado=calculoPNeto(250,,"$")
El paso por nombre: en este caso, se debe indicar en la llamada el nombre de cada
parámetro y su valor. El orden de los parámetros no es importante, pero está
obligado a indicar un valor para los parámetros no opcionales.
Otra posibilidad permite crear un procedimiento que podrá recibir un número cualquiera de
parámetros. Indique la palabra clave ParamArray para declarar una matriz de parámetros.
En el siguiente ejemplo, vamos a crear una función que calcula la media de todos los
parámetros que recibe.
Resultado=media(1,6,23,45)
Resultado=media(12,78)
ShareVideos
7. Funciones asíncronas
Veamos algunos ejemplos prácticos. Partimos de una función que comprueba si un número
es primo o no:
Return False
End If
Dim i As Integer
i = 3
Do While (i * i <= nb)
If nb Mod i = 0 Then
Return False
Else
i = i + 1
End If
Loop
Return True
End Function
Esta función no tiene nada de especial, excepto que puede llegar a necesitar mucho tiempo
de ejecución si se le pasa como argumento un entero con un valor muy elevado. Este
fenómeno se amplificará, con toda seguridad, si se llama varias veces. Es lo que vamos a
resaltar con la siguiente aplicación, que permite buscar los números primos entre 0 y un
valor concreto.
ShareVideos
Vamos a añadir una nueva función que cuente cuántos números primos hay entre 0 y el
valor que recibe como argumento.
Para esto, podemos añadir en nuestro método Main un simple bucle Do While en el que
realizamos nuestro tratamiento y solicitamos al usuario que introduzca un carácter ’s’ para
terminar la aplicación.
ShareVideos
Loop While (respuesta <> "s")
End Sub
Durante la prueba no hay ninguna mejora. De hecho, las instrucciones presentes en el bucle
do while se ejecutan de manera secuencial y en este caso la instrucción respuesta =
Console.ReadKey().KeyChar solo se ejecutará después de haber mostrado el resultado, es
decir, la final del cálculo. La función contarPrimos sigue estando bloqueada, no hay nada
que se pueda ejecutar en la aplicación hasta que termine. La solución consiste en
transformar la función contarPrimos en una función asíncrona. Para ello, basta con añadir la
palabra clave async en su firma.
Por tanto, es necesario modificar la función para que devuelva un tipo Task(Of Integer).
Ahora nuestra función se puede convertir en una función asíncrona, pero todavía no lo es.
Esto es lo que nos indica Visual Studio.
La operación que hay que realizar en la función asíncrona se debe pasar como argumento,
como una expresión lambda, al método Run de la clase Task. Es el resultado de la
ejecución de esta expresión lambda la que se utiliza como valor de retorno de la función
asíncrona.
Dim i As Integer
Dim nb As Integer
nb = 0
For i = 0 To maxi
If esPrimo (i)
Then
nb = nb + 1
End If
Next
Return nb
End Function)
Return resultado
End Function
ShareVideos
La penúltima etapa consiste en usar esta función de manera asíncrona. Para esto vamos a
crear una función nueva que va a llamar a la función contarPrimos. Para que la función
contarPrimos se ejecute de manera asíncrona, tenemos que utilizar la palabra clave await
durante su llamada.
Visual Studio nos indica una anomalía durante la llamada de la función operación.
Visual Basic está concebido en torno al Framework .NET, lo que le permite beneficiarse de
numerosas ventajas, sobre todo en cuando a seguridad, en el momento de la ejecución y de
la gestión de memoria. Esta relación también permite asegurar la compatibilidad entre el
código escrito en los distintos lenguajes disponibles. Así es posible utilizar en Visual Basic
elementos creados en otros lenguajes (y al revés), de manera totalmente transparente, sin
tener que preocuparse del lenguaje con el que se ha desarrollado el elemento.
ShareVideos
Los ensamblados se almacenan en archivos .exe o .dll según el tipo. Se generan
simplemente al compilar el proyecto correspondiente.
Son autodescriptivos, ya que contienen los datos necesarios para su utilización en otro
proyecto. Estos datos están contenidos en el manifiesto del ensamblado. El manifiesto
contiene entre otras cosas:
Para poder utilizar un ensamblado en un proyecto, añada simplemente una referencia hacia
el ensamblado. Para ello, utilice el menú contextual de la carpeta de referencia del
proyecto.
El siguiente cuadro de diálogo permite entonces elegir las referencias que deseamos añadir
al proyecto.
Las diferentes opciones permiten elegir, según la categoría, el tipo de referencia que
queremos agregar al proyecto:
Ensamblados
Solución
COM
Examinar
Reciente
ShareVideos
Es posible añadir varias referencias de manera simultánea utilizando la tecla [Ctrl] durante
la selección en este cuadro de diálogo.
Después de haber realizado estas dos operaciones, los recursos presentes en el ensamblado
son accesibles directamente en el código del proyecto.
Ejemplo
Sin embargo, la utilización del nombre plenamente cualificado puede hacer pesada la
escritura del código. Se puede utilizar la palabra clave imports para aligerar el código.
Indica al compilador que ciertos espacios de nombres se sobreentienden.
Las instrucciones Imports deben ser las primeras líneas de código en un archivo fuente
Visual Basic.
ShareVideos
Imports ctrlWin = System.Windows.Forms
Imports ctrlWeb = System.Web.UI.WebControls
Module TestConta
Dim listaWindows As ctrlWin.ListBox
Dim listaWeb As ctrlWeb.ListBox
Esta solución autoriza la utilización de nombres de una longitud razonable evitando los
conflictos.
Cabe observar también que, según el tipo de proyecto en el que está trabajando, se realizan
referencias e importaciones por defecto.
Los espacios de nombres se declararán en el código con la ayuda de las palabras claves
Namespace y End Namespace.
Todos los elementos declarados entre estas dos palabras claves serán accesibles utilizando
el nombre del espacio de nombres como prefijo.
Namespace Facturacion
Public Class Tarificacion
Public Shared Function calculoPNeto(PBruto As Decimal, tasaIva As
Decimal)
As Decimal
Return PBruto * (1 + tasaIva / 100)
End Function
End Class
End Namespace
Sub Main()
precioNeto = Conta.Facturacion.Tarificacion.calculoPNeto(100, 8)
End Sub
ShareVideos
Utilice la misma técnica en el caso de un espacio de nombres anidados, como en el
siguiente ejemplo:
Namespace Gestion
Namespace Pago
Public Class Sueldo
....
End Class
End Namespace
Namespace Facturacion
Public Class Factura
....
End Class
End Namespace
End Namespace
3. Los atributos
Los atributos son marcas que puede colocar en su código con el fin de añadir datos
adicionales a los elementos de su aplicación.
Los atributos se sitúan en el código entre los símbolos < y >, como las etiquetas HTML. Si
se utilizan varios atributos, deben ir separados con comas. Los posibles parámetros de un
atributo estarán ubicados entre paréntesis.
El alcance de un atributo también puede extenderse con las palabras claves Assembly: o
Module: ubicadas antes del atributo. La sintaxis de utilización de un atributo es, por lo
tanto:
Entre los atributos disponibles, algunos se usan con mucha frecuencia en el desarrollo con
Visual Basic. Vamos a estudiar su utilización e ilustrarla con un ejemplo.
VBFixedStringAttribute
ShareVideos
Este atributo fuerza la creación de una variable de tipo cadena de caracteres de tamaño fijo.
Se utiliza en la declaración de una estructura, usada para guardar en un archivo líneas de
tamaño constante.
Ejemplo
Structure Cliente
<VBFixedString(15)> public nombre as String
<VBFixedString(15)> public apellidos as String
End Structure
ComClassAttribute
Este atributo pide al compilador la generación de código adicional para hacer compatible
una clase con el modelo COM. De esta manera, la clase será compatible con antiguos
lenguajes de programación incompatibles con la plataforma .NET.
Ejemplo
Para compilar este código, es necesario activar la opción a nivel de propiedades del
proyecto Registrar para Com Interop.
SerializableAttribute, NonSerializedAttribute
ShareVideos
miembros de la instancia de la clase se guarda en el archivo. Si algunos de ellos no deben
guardarse en el archivo, se deben marcar con el atributo NonSerializedAttribute.
El ejemplo siguiente define la clase Persona con dos miembros (Apellidos y Nombre) que
serán serializados y un miembro (Edad) que no será serializado. Se crea una instancia de la
clase y se guarda en un archivo de formato XML.
Ejemplo
Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Soap
<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:
xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-
ENC="http://schemas.xmlsoap.
org/soap/encoding/" xmlns:SOAP-
ENV="http://schemas.xmlsoap.org/soap/envelope
" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-
ENV:
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:Persona id="ref-1"
xmlns:a1="http://schemas.microsoft.com/clr/nsassem/
serializable/serializable%2C%20Version%3D1.0.0.0%2C%20Culture%
3Dneutral%2C%20
PublicKeyToken%3Dnull">
<Nombre id="ref-3">Pablo</Nombre>
<Apellidos id="ref-4">García</Apellidos>
</a1:Persona>
ShareVideos
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
Encontramos en el archivo nuestra instancia de la clase Persona con sus dos miembros,
Nombre y Apellidos, y, tal y como habíamos indicado en la definición de la clase, el
miembro Edad no se ha guardado.
DllImportAttribute
Se utiliza este atributo para indicar que una función se importa desde una biblioteca de
código no gestionado. Permite en particular la utilización de funciones definidas en una
biblioteca del sistema. En el siguiente ejemplo, la función MoveFile se puede utilizar como
una función clásica.
Ejemplo
Obsolete
Se puede utilizar este atributo para indicar que un elemento, clase, método o propiedad ya
no se utiliza. Si a pesar de todo se utiliza este elemento en una aplicación, el compilador
genera un aviso o un error en función de la configuración del atributo. Una cadena de
caracteres puede ser pasada como parámetro a este atributo para representar el mensaje
visualizado por el compilador. Un segundo parámetro de tipo booleano permite especificar
si la utilización del elemento marcado con este atributo genera un aviso o un error de
compilación.
ShareVideos
Si este atributo viene definido con un segundo parámetro igual a True, el compilador activa
un error cuando se utiliza el elemento.
Introducción
Con Visual Basic .NET, la noción de objeto es omnipresente y requiere un mínimo de
aprendizaje. Vamos a ver primero el principio de la programación orientada a objetos y el
vocabulario asociado, luego veremos cómo ponerlo en aplicación con Visual Basic.
Prosigamos nuestra analogía entre una clase y un plano de un edificio. Sabemos que es
posible construir varios edificios a partir del mismo plano. De la misma manera, varios
objetos pueden ser construidos a partir de la misma clase. Se puede utilizar una clase para
crear tantas instancias como sea necesario.
Los términos clase y objeto a menudo se confunden, pero se trata en realidad de elementos
muy distintos. Una clase representa la estructura de un elemento, mientras que el objeto es
un ejemplar creado a partir de la plantilla de esta estructura. La modificación de un
elemento en un objeto no cambia en absoluto los otros objetos creados a partir de la misma
plantilla (clase). En nuestro ejemplo de plano de un edificio, el hecho de añadir una nueva
habitación a un edificio existente no cambia para nada los otros edificios construidos según
el mismo plano. Por el contrario, la modificación del plano (de la clase) conlleva
modificaciones en todos los nuevos edificios (todos los nuevos objetos).
ShareVideos
Las clases están constituidas por campos, propiedades, métodos y eventos. Los campos y
las propiedades representan los datos contenidos en los objetos. Los campos se consideran
como variables, y es posible leer su contenido o directamente asignarles un valor. Por
ejemplo, si tiene una clase que representa un cliente, puede guardar su nombre en un
campo.
Las propiedades se manipulan de la misma manera que los campos, pero se activan desde
los procedimientos de propiedad Get y Set. Esto otorga más control sobre cómo leer o
asignar valores y permite la validación de los datos antes de su utilización.
Los métodos representan las acciones que un objeto puede asignar. Se aplican creando
procedimientos o funciones en una clase.
Los eventos son datos que un objeto recibe o transmite desde o hacia otro objeto o
aplicación. Los eventos permiten a los objetos ejecutar acciones cuando una situación
particular se verifica. Como Windows es un sistema operativo de eventos, los eventos
pueden proceder de otros objetos, del sistema o de las acciones del usuario sobre el ratón y
el teclado.
Esto es solo una faceta de la programación orientada a objetos. También son fundamentales
otros tres elementos:
La encapsulación.
La herencia.
El polimorfismo.
La herencia permite la creación de una nueva clase, basada en una clase existente. La clase
que sirve de plantilla para la creación de otra clase se llama clase base. La clase así creada
ShareVideos
hereda de los campos, propiedades, métodos y eventos de la clase base. La nueva clase
puede personalizarse al agregarle campos, propiedades, métodos y eventos. Las clases
creadas a partir de una clase base se llaman clases derivadas. Así se puede definir una clase
base y reutilizarla varias veces para crear clases derivadas.
Se utiliza la sobrecarga para diseñar propiedades o métodos que llevan el mismo nombre
pero que tienen un número de parámetros diferentes o tipos de parámetros diferentes.
La ocultación sirve para sustituir localmente, en una clase, un miembro de una clase.
Cualquier tipo de miembro puede ocultar otro miembro. Por ejemplo, una propiedad puede
ocultar un método heredado. La ocultación se hace únicamente a través del nombre. Los
miembros ocultados no son heredables.
Para realizar una analogía con un objeto corriente, vamos a tomar el ejemplo de un
destornillador. En función del tipo de tornillo que se vaya a utilizar, puede coger un
destornillador específico para este tipo de tornillo (plano, de cruz, de estrella, etc.). Una
técnica a menudo utilizada por un manitas experto consiste en adquirir un destornillador
universal, con múltiples cabezas. En función del tipo de tornillo, elige la cabeza adecuada.
El resultado final es el mismo que si dispone de varios destornilladores: puede atornillar y
desatornillar.
Cuando se utiliza un tipo genérico, se configura con un tipo de datos. Esto permite al
código adaptarse automáticamente y realizar la misma acción independientemente del tipo
ShareVideos
de datos. Una alternativa podría ser la utilización del tipo universal Object. La utilización
de los tipos genéricos presenta varias ventajas respeto a esta solución:
Los tipos genéricos pueden, sin embargo, imponer ciertas restricciones relativas al tipo de
datos utilizado. Por ejemplo, pueden imponer que el tipo utilizado implemente una o varias
interfaces, que sea un tipo de referencia o que posea un constructor por defecto.
El tipo genérico
El tipo parámetro
El tipo argumento
Las limitaciones
Son las condiciones que usted impone y que limitan el tipo argumento que puede facilitar.
El tipo construido
Una clase que espera un tipo de parámetro se llama clase genérica. Puede generar una clase
construida facilitando a la clase genérica un tipo argumento para cada uno de estos tipos
parámetro.
ShareVideos
a. Definición de una clase genérica
Puede definir una clase genérica, que facilita las mismas funcionalidades sobre diferentes
tipos de datos. Para ello, debe facilitar uno o varios tipos de parámetro en la definición de la
clase. Tomemos el ejemplo de una clase, capaz de gestionar una lista de elementos con las
siguientes funcionalidades:
Agregar un elemento.
Suprimir un elemento.
Desplazarse hasta el primer elemento.
Desplazarse hasta el último elemento.
Desplazarse hasta el elemento siguiente.
Desplazarse hasta el elemento anterior.
Obtener el número de elementos.
End Class
End Class
Si son necesarios varios tipos de parámetro, se deben separar con comas sin repetir la
palabra clave Of.
Si su código debe realizar operaciones que no sean asignaciones, debe añadir limitaciones
al tipo de parámetro. Para hacerlo, añada la palabra clave As seguida por la limitación.
structure
Esta restricción impone que el tipo parámetro sea un tipo por valor, y no un tipo referencia.
Además este tipo no debe ser Nullable.
End Class
ShareVideos
class
Esta limitación impone que el tipo parámetro sea un tipo referencia: clase, interfaz, matriz o
delegado.
End Class
New
End Class
Esta limitación exige que el tipo parámetro sea la clase indicada o una de sus subclases.
End Class
interfaz1, interfaz2...
Esta limitación exige que el tipo parámetro implemente la interfaz o las interfaces
indicadas.
End Class
En el código de la clase, cada miembro que deba ser del tipo de parámetro debe definirse
con la sintaxis As tipo, en nuestro caso. Veamos ahora el código completo de la clase.
ShareVideos
Private position = 0
’ puntero para agregar un nuevo elemento
Private elementoSiguiente = 0
’número de elementos de la lista
Private numElementos = 0
’ dimensión de la lista
Private tamaño As Integer
’ indica si la lista está llena
Private completa As Boolean = False
’ constructor con un parámetro que permita dimensionar la lista
Public Sub New(ByVal tamaño As Integer)
lista = New tipo(tamaño - 1) {}
MyClass.tamaño = tamaño
End Sub
Public Sub agregar(ByVal elemento As tipo)
’ verificamos si la lista está completa antes
’ de agregar un elemento
If Not completa Then
lista(elementoSiguiente) = elemento
numElementos = numElementos + 1
completa = (numElementos = tamaño)
’ si la lista no está completa, colocamos el puntero
’ para agregar el elemento siguiente
If Not completa Then
elementoSiguiente = elementoSiguiente + 1
End If
Else
Beep()
End If
End Sub
Public Sub suprime(ByVal índice As Integer)
Dim i As Integer
’ verificamos si el índice no es superior al número de elementos
’ si el índice no es inferior a 0
If índice >= numElementos OrElse índice < 0 Then
Beep()
Exit Sub
End If
’ desplazamos los elementos una posición hacia arriba
For i = indice To numElementos - 2
lista(i) = lista(i + 1)
Next
’ colocamos el puntero para agregar un nuevo elemento
elementoSiguiente = elementoSiguiente - 1
’ actualizamos el número de elementos
numElementos = numElementos - 1
End Sub
Public ReadOnly Property tamañoLista() As Integer
Get
Return numElementos
End Get
End Property
ShareVideos
’ desplazamos el puntero hacia el primer elemento
posicion = 0
Return lista(0)
End Function
Public Function último() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vacía")
End If
’ desplazamos el puntero hacia el último elemento
posicion = numElementos - 1
Return lista(position)
End Function
Public Function siguiente() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vacía")
End If
’ verificamos que no estamos al final de la lista
If posicion = numElementos - 1 Then
Beep()
Err.Raise(1000, , "ningún elemento siguiente")
Exit Function
End If
’ desplazamos el puntero hasta el elemento siguiente
posicion = posicion + 1
Return lista(posicion)
End Function
Public Function anterior() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vacía")
End If
’ verificamos que no estamos en el primer elemento
If posicion = 0 Then
Beep()
Err.Raise(1000, , "ningún elemento anterior")
Exit Function
End If
’ nos desplazamos hasta el elemento anterior
posicion = posicion - 1
Return lista(posicion)
End Function
End Class
Para poder utilizar una clase genérica, ante todo debe generar una clase construida que
proporcione un tipo argumento para cada uno de sus tipos parámetro. Entonces puede
instanciar la clase construida por uno de los constructores disponibles. Vamos a utilizar la
clase diseñada anteriormente para trabajar con una lista de enteros.
Esta declaración permite instanciar una lista de cinco enteros. Los métodos de la clase
entonces están disponibles.
ShareVideos
lista.Añadir(10)
lista.Añadir(11)
Module testGenerica
Dim lista As New ListaGenerica(Of Integer)(5)
Public Sub main()
lista.Añadir(10)
lista.Añadir(11)
lista.Añadir(12)
lista.Añadir(13)
lista.Añadir(14)
lista.Añadir(15)
menu()
End Sub
Public Sub menu()
Dim elige As Char
On Error GoTo gestionerror
Console.SetCursorPosition(1, 24)
Console.WriteLine("p (primero) < (anterior) >(siguiente) d
(ultimo) f
(fin)")
While elige <> "f"
elige = Console.ReadLine()
Console.Clear()
Console.SetCursorPosition(1, 1)
Select Case elige
Case "p"
Console.WriteLine("el primero {0}", lista.primero())
Case "<"
Console.WriteLine("el anterior {0}",
lista.anterior())
Case ">"
Console.WriteLine("el siguiente {0}",
lista.siguiente())
Case "d"
Console.WriteLine("el último {0}", lista.ultimo())
End Select
Console.SetCursorPosition(1, 24)
Console.WriteLine("p (primero) < (anterior) >(siguiente) d
(último) f (fin)")
End While
Exit Sub
gestionerror:
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine(Err.Description)
Console.ResetColor()
Resume Next
ShareVideos
End Sub
End Module
También podemos verificar que nuestra clase funciona sin problema si le pedimos trabajar
con cadenas de caracteres.
2. Interfaces genéricas
De manera totalmente similar a lo que acabamos de ver respecto a las clases genéricas,
también es posible diseñar interfaces genéricas. Utilizan las mismas técnicas de diseño que
las clases genéricas.
El tipo parámetro se puede utilizar en la firma de los métodos exigidos por la interfaz.
Como ocurre con una interfaz normal, una interfaz genérica debe ser implementada por una
clase. Durante la declaración de la clase, el tipo o los tipos parámetros deben ser sustituidos
por uno o varios tipos argumento.
End Class
El compilador exige ahora que el método o los métodos descritos en la interfaz estén
realmente disponibles en la clase.
ShareVideos
También hay que observar que el compilador haya tenido en cuenta el tipo argumento
utilizado para la declaración de la clase, ya que nos reclama la presencia de una función
llamada compare y espera como parámetro un objeto de tipo Persona (el tipo argumento
especificado en el momento de la declaración de la clase).
End Function
Los procedimientos o funciones genéricos son métodos definidos con al menos un tipo
parámetro. Esto permite al código que los llama especificar el tipo de datos que necesita en
cada llamada del procedimiento o función. Sin embargo, se puede utilizar este método sin
indicar información para el tipo argumento. En este caso, el compilador intenta determinar
el tipo en función de los argumentos pasados al método. Esta solución se debe utilizar con
precaución, ya que, si el compilador no puede determinar el tipo de los argumentos, genera
un error de compilación.
Vamos a crear una función genérica capaz de buscar un elemento particular en una matriz
de cualquier tipo. Esta función va a utilizar un tipo parámetro que indica la naturaleza de
los elementos presentes en la matriz. Para poder buscar un elemento en la matriz,
deberemos compararlo con los presentes en todas sus casillas. Para garantizar que esta
comparación será posible, añadimos una limitación en el tipo parámetro: debe implementar
la interfaz Icomparable con el fin de asegurar que el método CompareTo utilizado en la
función esté disponible para cada elemento de la matriz.
ShareVideos
Después de haber comprobado que la matriz contiene al menos un elemento, debemos
comparar el elemento buscado con aquel presente en cada casilla de la matriz Si hay
igualdad, la función devuelve el índice donde se ha encontrado el elemento; si no, la
función devuelve -1. Para efectuar la comparación, utilizaremos la función CompareTo de
cada elemento de la matriz.
ShareVideos
Delegados genéricos
Como cualquier otro elemento, un delegado puede definir unos tipos parámetro en su
declaración. Cuando se utiliza el delegado, hay que facilitar unos tipos argumento para cada
uno de sus tipos parámetro. El siguiente extracto de código declara un delegado genérico.
Para poder llamar esta función de ordenación, hay que facilitarle como primer parámetro
una matriz de clientes y una función que respete la firma del delegado como segundo
parámetro.
El compilador verifica que la firma de la función sea compatible con la definición del
delegado.
ShareVideos
Varianza
En programación orientada a objetos, la varianza designa el hecho de utilizar un tipo de
objetos que no se corresponde exactamente con el esperado. Sin embargo, hay una pequeña
restricción, ya que el tipo utilizado y el tipo esperado deben formar parte de la misma
jerarquía de clase. Así, el tipo utilizado puede ser un supertipo del tipo esperado o un
subtipo del tipo esperado. Si el tipo utilizado es un supertipo del tipo esperado (tipo menos
derivado), hablamos de contravarianza. Si el tipo utilizado es un subtipo del tipo esperado
(tipo menos derivado), hablamos de covarianza. Tomemos el ejemplo de una clase Persona
y una de sus subclases, la clase Cliente. La covarianza consiste en utilizar la clase Cliente
donde se espera la clase Persona. La contravarianza es el trámite inverso, ya que consiste en
utilizar la clase Persona donde se espera la clase Cliente. Las interfaces genéricas y los
delegados genéricos se encargan de estos dos mecanismos a continuación. Vamos a detallar
estas dos nociones.
Para ilustrar todo esto, utilizaremos las dos clases definidas a continuación:
ShareVideos
elApellido = value.ToUpper()
End Set
End Property
End Set
End Property
Public ReadOnly Property age As Integer
Get
Return DateTime.Now.Year - laFecha_naci.Year
End Get
End Property
Public WriteOnly Property contraseña As String
Set(ByVal value As String)
laContraseña = value
End Set
End Property
End Class
Public Class Cliente
Inherits Persona
Private elNumero As Integer
Public Property numero As Integer
Get
Return elNumero
End Get
Set(ByVal value As Integer)
elNumero = value
End Set
End Property
End Class
Las dos clases definidas anteriormente se completan ahora con la siguiente interfaz
genérica.
ShareVideos
Las clases que implementan esta interfaz deberán contener al menos el método compare.
Ahora vamos a crear dos clases capaces de comparar Personas o Clientes al implementar la
interfaz ComparadorGenerico con la clase Persona o Cliente como tipo argumento. La
comparación de las personas se hará según el apellido y la comparación de los clientes
según el número.
Nuestra última etapa consiste en crear un método utilizando nuestra interfaz genérica como
parámetro. Para ello, añadimos la siguiente función, que verifica la igualdad de dos clientes
en función del comparador que se le pasa como primer argumento.
End Sub
Solo nos queda probar esto al crear dos instancias de la clase Cliente y al intentar
compararlas con el número de cliente como criterio. Para ello, utilizaremos una instancia de
la clase ComparadorCliente.
ShareVideos
verifIgualdad(New ComparadorCliente(), c1, c2)
Si ahora queremos comparar nuestros dos clientes según su apellido, en lugar de hacerlo
según su número, podemos utilizar la clase ComparadorPersona, ya que el método
compare, definido en esta clase, espera como parámetros dos instancias de la clase Persona;
por tanto, si le facilitamos dos instancias de la clase Cliente, funcionará de la misma
manera: nuestras instancias de la clase Cliente disponen de un apellido debido a la relación
de herencia con la clase Persona. Sin embargo, el compilador no tiene la misma opinión
que nosotros y detecta un error.
Sin embargo, solo puede declarar un tipo como contravariante en una interfaz o un
delegado genérico, si se utiliza como tipo de argumento de método. En ningún caso se
puede utilizar como tipo de retorno de un método.
Para ilustrar la covarianza en las interfaces genéricas, vamos a crear una nueva interfaz que
defina el método creacionInstancia. Este método deberá devolver, en las clases que
implementarán esta interfaz, una instancia del tipo argumento utilizado durante la
implementación de la interfaz.
ShareVideos
End Interface
En esta clase, hay que observar que hemos añadido una restricción sobre el tipo parámetro
para estar seguros de que la clase utilizada como tipo argumento dispone correctamente de
un constructor por defecto.
Ahora podemos crear una instancia de esta clase y utilizarla para producir instancias de la
clase Persona.
Este código se compila sin error y nos permite obtener correctamente instancias de la clase
Persona. Si modificamos este código para crear un objeto Fabrica de Cliente, obtenemos un
error de compilación.
End Interface
Sin embargo, esta técnica comporta una limitación, ya que el tipo declarado covariante solo
se puede utilizar como tipo de retorno de una función. Si se utiliza como tipo para un
parámetro de método, el compilador activa un error.
ShareVideos
2. Varianza en los delegados genéricos
Para ilustrar la contravarianza en los delegados genéricos, vamos a utilizar el ejemplo usado
para los delegados genéricos:
Para efectuar nuestro test, añadimos una función que respete la firma del delegado y
permita realizar la comparación de dos Personas según su apellido.
Return p1.apellido.CompareTo(p2.apellido)
End Function
Ahora solo nos queda utilizar todo ello para ordenar una matriz de Clientes:
ShareVideos
ordenacion(matriz, fct)
Como para las interfaces genéricas, un tipo puede declararse contravariante únicamente si
se utiliza como tipo de argumentos de método. En ningún caso se puede utilizar como tipo
de retorno de un método.
Ahora podemos escribir dos funciones que respeten la firma del delegado.
End Function
End Function
ShareVideos
Ahora solo nos queda escribir la función que permite la creación de una matriz. Esta
función espera como primer parámetro el tamaño de la matriz, y como segundo parámetro,
el delegado encargado de crear las instancias de clase que sirven para rellenar la matriz.
Esta función devuelve la matriz rellenada.
For i = 0 To tamaño - 1
matriz(i) = cc.Invoke()
Next
Return matriz
End Function
Ahora podemos utilizar esto con las pocas líneas de código siguientes.
Dim cp Asconstruccion(OfPersona);
cp = AddressOf fabricacionPersona;
Dim matriz() As Persona
Ahora podemos intentar rellenar la matriz no con instancias de la clase Persona, sino con
instancias de la clase Cliente. Gracias a la relación de herencia entre estas dos clases, una
casilla de la matriz se puede utilizar para referenciar una instancia de la clase Persona, pero
también una instancia de cualquiera de estas subclases, y por lo tanto de la clase Cliente.
Para que el compilador acepte esta manipulación, hay que autorizarla añadiendo la palabra
clave out en la declaración del delegado.
ShareVideos
Como para la covarianza con las interfaces genéricas, se aplica una restricción, ya que el
tipo covariante solo se puede utilizar como tipo de retorno, y no como tipo para un
parámetro de método.
Las colecciones
Las aplicaciones necesitan a menudo manipular grandes cantidades de información. En
Visual Basic están disponibles muchas estructuras para facilitar la gestión de estos datos.
Están agrupadas bajo el término colección. Como en la vida corriente, hay diferentes tipos
de colección. Puede haber personas que coleccionan todo tipo de cosas, pero no siguen
ninguna organización especial al guardarlas; otras personas están especializadas en la
colección de ciertos tipos de objetos, y hay maníacos que toman todas las precauciones para
poder encontrar enseguida un objeto...
En Framework .NET existen clases que se corresponden con cada una de estas situaciones.
Las diferentes clases que permiten la gestión de las colecciones se reparten entre dos
espacios de nombres:
System.Collections
System.Collections.Generic
El primero contiene las clases normales, mientras que el segundo contiene las clases
genéricas equivalentes que permiten la creación de colecciones muy características. Estas
colecciones muy características están especializadas en la gestión de un tipo determinado
de datos. Aunque numerosas clases ofrecen funcionalidades diferentes, tienen muchos
puntos en común, ya que implementan las mismas interfaces. Por ejemplo, todas estas
clases pueden facilitar un objeto enumerator que permite recorrer el conjunto de la
colección. Es el objeto que utiliza la instrucción For Each de Visual Basic.
a. Array
ShareVideos
Length, que representa el número total de elementos en la matriz.
Rank, que contiene el número de dimensiones de la matriz.
Esta clase se usa poco para la creación de una matriz porque se prefiere utilizar la sintaxis
Visual Basic.
b. ArrayList y List
La clase ArrayList o su versión genérica List son evoluciones de la clase Array. Aportan
muchas mejoras respeto a esta última.
Por el contrario, en algunos puntos, la clase ArrayList es menos eficaz que una simple
matriz:
Como cualquier clase, un ArrayList debe ser instanciado antes de poder utilizarlo. Dos
constructores están disponibles. El primero es un constructor por defecto y crea un
ArrayList con una capacidad inicial de cero. Se dimensiona automáticamente a la hora de
añadir elementos. No se aconseja esta solución, ya que la ampliación del ArrayList
consume muchos recursos. Si tiene una estimación del número de elementos que es preciso
almacenar, es preferible utilizar el segundo constructor, que espera como parámetro la
capacidad inicial del ArrayList. Esto evita el dimensionamiento automático en el momento
de agregar elementos.
Luego se deben agregar los elementos llamando al método Add de la clase ArrayList o List
para cada uno de ellos.
Se pueden combinar estas dos etapas facilitando los valores que se deben almacenar en ella
en el momento de la instanciación del ArrayList o de la List.
Cuando el compilador analiza esta línea de código, en realidad efectúa las operaciones
siguientes :
ShareVideos
lst.Add(2)
lst.Add(3)
lst.Add(4)
lst.Add(5)
Incluso se puede mejorar evitando tener que crear las instancias de los objetos que se deben
almacenar en la lista. Para ello, es suficiente volver a definir el método Add de la lista con
la forma de un método de extensión para que el compilador pueda llamarlo al agregar
elementos y crear la instancia de cada uno de ellos.
<Extension()>
Sub add(ByVal lst As List(Of Client),
ByVal apellido As String,
ByVal nombre As String,
ByVal contraseña As String,
ByVal code As String)
lst.add(New Cliente With
{
.apellido = apellido,
.nombre = nombre,
.Contraseña = contraseña,
.codigo = codigo
})
End Sub
Ahora se puede utilizar la sintaxis siguiente para instanciar e inicializar una lista de
clientes.
Hay que resaltar que la dimensión indicada no es definitiva y el ArrayList podrá contener
más elementos que los previstos inicialmente.
ShareVideos
posición dada. La supresión de elementos se hace por el método RemoveAt o
RemoveRange; el primero espera como parámetro el índice del elemento que se debe
suprimir, el segundo exige además el número de elementos que se deben suprimir. El
método Clear es más radical y suprime todos los elementos.
ShareVideos
Console.WriteLine("número de elementos de la lista {0}",
lista.Count)
Console.ReadLine()
End Sub
c. Hashtable y Dictionary
Un Hashtable o su versión genérica Dictionary registra los datos en forma de parejas clave
valor. El Hashtable está constituido internamente por compartimentos que contienen los
elementos de la colección. Para cada elemento de la colección, se genera un código
mediante una función hash basada en la clave de cada elemento. Luego se utiliza el código
para identificar el compartimento en el que se almacena el elemento. Durante la búsqueda
de un elemento en la colección, se efectúa la operación inversa. El código hash se genera a
partir de la clave del elemento buscado. Esta clave sirve después para identificar el
ShareVideos
compartimento en el que se encuentra el elemento buscado. Para que una Hashtable pueda
almacenar un objeto, este debe ser capaz de facilitar su propio código hash.
d. Queue
Las colecciones de tipo Queue se adaptan, si necesitara acceder a los datos en el mismo
orden en que han sido almacenados en la colección. Este tipo de gestión se llama a veces
First In - First Out (FIFO). Las tres principales operaciones disponibles son:
e. Stack
Las colecciones de este tipo utilizan el mismo principio que las Queue: cuando se recupera
un elemento de la colección, se suprime de ella. La única distinción respeto a la clase
ShareVideos
Queue es el orden en el que se recuperan los elementos. Este tipo de colección utiliza la
técnica Last In - First Out (LIFO). El ejemplo clásico de este tipo de gestión es la pila de
platos de su cocina. Después de fregar los platos, se guardan en una estantería. Al día
siguiente, al poner la mesa, el primer plato disponible es el último, que guardó del día
anterior.
A continuación le damos unos consejos para elegir el tipo de colección que más se adapte a
sus necesidades.
ShareVideos
My.Settings Sí Sí Sí Sí Sí Según
el tipo
My.User Sí Sí Sí Sí Sí
de
My.WebServices Sí Sí Sí Sí Sí proyect
o en el
que se utilizan, algunas propiedades de estos objetos pueden no estar disponibles. Por
ejemplo, la propiedad MainForm del objeto Application solo se puede utilizar en los
proyectos de aplicaciones de Windows.
Este tipo de errores se produce en el momento de la compilación, cuando una palabra clave
del lenguaje está mal escrita. Eran muy frecuentes con las primeras herramientas de
desarrollo, en las que el editor de código y el compilador eran dos entidades separadas.
Ahora son cada vez más raros en los entornos similares a Visual Studio. La mayoría de
estos entornos ofrecen un análisis sintáctico mientras se escribe el código. Desde este punto
ShareVideos
de vista, Visual Studio proporciona muchas funcionalidades que nos permiten eliminar este
tipo de errores.
Así, por ejemplo, controla que cada instrucción If se acabe correctamente con un End If.
Si detecta un error de sintaxis, Visual Basic propone las posibles soluciones para corregirlo.
Se pueden ver haciendo clic en el icono asociado al error.
Por otra parte, los «errores de ortografía» en los nombres de propiedades o métodos se
eliminan fácilmente gracias a las funcionalidades IntelliSense. IntelliSense se encarga de:
ShareVideos
2. Los errores de ejecución
Afortunalmente, Visual Basic permite la recuperación de este tipo de error y evita así la
visualización de este inquietante cuadro de diálogo. Existen dos técnicas para la gestión de
este tipo de errores:
La gestión en línea.
Las excepciones.
Los peores enemigos de los desarrolladores. Todo se compila sin problema, todo se ejecuta
sin problema y, sin embargo, «¡no funciona!!»
La gestión en línea.
El tratamiento de la excepción.
1. La gestión en línea
La ejecución del código seguirá por la línea posterior a la que ha provocado el error.
ShareVideos
On error goto etiqueta
El código del gestor de errores debe determinar el comportamiento que hay que seguir en el
caso de error.
Tres soluciones:
Resume
resume next
ShareVideos
gestionErrores:
Dim respuesta As Integer
respuesta = MsgBox("no se puede leer el archivo",
MsgBoxStyle.AbortRetryIgnore)
Select Case respuesta
Case MsgBoxResult.Retry
Resume
Case MsgBoxResult.Ignore
Resume Next
Case MsgBoxResult.Abort
Exit Sub
End Select
End Sub
Nos queda todavía un problema por resolver: nuestro gestor de errores reaccionará
independientemente del error. Para poder determinar qué error se acaba de producir en la
aplicación, tenemos a nuestra disposición el objeto err, que nos proporciona información
sobre el último error que ha aparecido. Este objeto contiene, entre otras, dos propiedades,
number y description, que nos permiten obtener el código del error y su descripción.
Podemos modificar entonces nuestro código para que reaccione de manera diferente en
función del error.
ShareVideos
Se puede desactivar un gestor de errores utilizando la instrucción on error goto 0. Si se
produce un error después de esta instrucción, no se recupera y la aplicación se detiene.
De hecho, la aplicación no se para inmediatamente, sino que Visual Basic busca en las
funciones de llamada si hay un gestor de errores activo. Si encuentra uno, le encarga la
gestión del error.
En este ejemplo, procedimiento2 ejecutará una instrucción que activa un error (1 / x). Como
no existe un gestor de errores en este procedimiento, Visual Basic busca entre las llamadas
si existe un gestor activo. El primero que encuentra está en el procedimiento1; será este el
que se encargará de la gestión del error.
2. Las excepciones
a. Recuperación de excepciones
Try
...
Instrucciones peligrosas
...
catch excepcion1
...
código ejecutado si se produce una excepción de tipo Excepcion1
...
catch excepcion2
...
código ejecutado si se produce una excepción de tipo Excepcion2
ShareVideos
...
Finally
...
código ejecutado siempre antes de salir del bloque Try
...
End Try
Esta estructura tiene un funcionamiento muy parecido al Select case que ya hemos
estudiado. Cada tipo de error se asocia a un tipo de exceptión y, cuando se produce este
error, se crea una instancia de la clase Exception correspondiente. Podremos determinar,
para cada instrucción Catch, qué tipo de excepción debe tratar.
La clase de base es la clase Exception desde la que se crea una serie de subclases
especializadas, cada una para un tipo de error particular. A continuación, presentamos la
lista de las clases que derivan directamente de la clase Exception.
Microsoft.Build.BuildEngine.InternalLoggerException
Microsoft.Build.BuildEngine.InvalidProjectFileException
Microsoft.Build.Framework.LoggerException
Microsoft.JScript.CmdLineException
Microsoft.JScript.ParserException
Microsoft.VisualBasic.ApplicationServices
Microsoft.VisualBasic.ApplicationServices.NoStartupFormException
Microsoft.VisualBasic.CompilerServices.IncompleteInitialization
Microsoft.VisualBasic.CompilerServices.InternalErrorException
Microsoft.VisualBasic.FileIO.MalformedLineException
Microsoft.WindowsMobile.DirectX.DirectXException
System.ApplicationException
System.ComponentModel.Design.ExceptionCollection
System.Configuration.Provider.ProviderException
System.Configuration.SettingsPropertyCannotBeSetForAnonymousUserException
System.Configuration.SettingsPropertyIsReadOnlyException
System.Configuration.SettingsPropertyNotFoundException
System.Configuration.SettingsPropertyWrongTypeException
System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException
System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundExcepti
on
System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException
System.DirectoryServices.ActiveDirectory.ActiveDirectoryServerDownException
System.DirectoryServices.Protocols.DirectoryException
System.IO.IsolatedStorage.IsolatedStorageException
System.Net.Mail.SmtpException
System.Runtime.Remoting.MetadataServices.SUDSGeneratorException
System.Runtime.Remoting.MetadataServices.SUDSParserException
System.SystemException
System.Web.Security.MembershipCreateUserException
System.Web.Security.MembershipPasswordException
System.Web.UI.ViewStateException
ShareVideos
System.Windows.Forms.AxHost.InvalidActiveXStateException
Esta lista solo presenta el primer nivel de la jerarquía. Cada una de estas clases también
tiene muchos descendientes.
Estas excepciones se utilizan para indicar, en cada instrucción Catch, el tipo de excepción
que debe generar.
Si entre todas las Catch ninguna se corresponde con la excepción generada, la excepción se
propaga al código de los procedimientos o funciones de llamadas, a la búsqueda de una
instrucción Catch capaz de tomar en consideración esta excepción. Si no se encuentra
ningún bloque, se activa un error de ejecución.
Los bloques Catch también pueden ser condicionales, añadiendo la palabra When seguida
por una expresión que se pueda evaluar como un booleano.
Si el parámetro indicado en la instrucción Catch es una clase «de excepción general», esta
instrucción Catch será capaz de capturar todas las excepciones creadas a partir de esta clase
o de estas subclases. El siguiente código nos permite capturar todas las excepciones.
ShareVideos
Las diferentes clases disponen de las siguientes propiedades que nos permiten tener más
datos sobre el origen de la excepción.
Message
Source
StackTrace
Lista de todos los métodos por los que ha pasado la aplicación antes de la activación del
error.
TargetSite
InnerException
Las excepciones son, ante todo, clases. Por lo tanto, es posible crear nuestras propias
excepciones heredando una de las numerosas clases de excepción ya disponibles. Para
respetar las convenciones del Framework .NET, se aconseja conservar el término Exception
en el nombre de la clase. Podemos, por ejemplo, escribir el siguiente código:
End Sub
Public Sub New(ByVal mensaje As String)
MyBase.New(mensaje)
End Sub
Public Sub New(ByVal mensaje As String, ByVal inner As Exception)
MyBase.New(mensaje, inner)
End Sub
End Class
Luego se puede utilizar esta clase para activar una excepción personalizada. El siguiente
código activa una excepción personalizada en un bloque catch.
Catch ex As Exception
Throw New NoFuncionaException("error en la aplicación", ex)
ShareVideos
End Try
Según la configuración del entorno de Visual Studio, es posible que algunas herramientas
no estén disponibles. Puede volver a configurar Visual Studio para integrar estas
herramientas a través del menú Herramientas - Importar y exportar configuraciones.
Los diferentes cuadros de diálogo le proponen guardar su entorno actual antes de
modificarlo, y luego elegir un entorno tipo para importar.
Para las siguientes explicaciones de este capítulo, vamos a considerar que esta es la
configuración utilizada en Visual Studio.
1. Control de la ejecución
a. Inicio de la solución
En desarrollo.
ShareVideos
En ejecución.
En modo de parada (se interrumpió la ejecución).
Si la solución contiene varios proyectos, se debe configurar uno de ellos como proyecto de
lanzamiento para la solución. Este proyecto también debe tener un objeto de lanzamiento
configurado, y con su ejecución se iniciará la applicación.
b. Parar la solución
Se puede parar la aplicación cerrando todas las ventanas; para una aplicación de Windows,
en cuanto se cierra la última ventana, o a través de las teclas [Ctrl] C para una aplicación de
consola. La barra de herramientas o la combinación de teclas [Ctrl][Alt] [Pausa] también
permiten parar la aplicación.
c. Interrumpir la solución
Este método no es muy práctico, ya que hace falta tener mucha suerte para interrumpir la
ejecución en un lugar preciso. Más adelante veremos que los puntos de interrupción son
una solución mucho mejor para detener la ejecución del código.
d. Proseguir la ejecución
Una vez en modo parado, tenemos distintas formas de continuar con la ejecución de la
aplicación.
ShareVideos
La primera permite retomar la ejecución normal de la aplicación utilizando la misma
técnica que se usa para el inicio del programa (barra de herramientas o combinación de
teclas [F5]). Sin embargo, la técnica más corriente durante una depuración consiste en la
ejecución paso a paso.
El Paso a paso por instrucciones y el Paso a paso por procedimientos difieren simplemente
en su manera de gestionar las llamadas de procedimientos y funciones. Si estamos en modo
de parada en una línea de código que contiene una llamada a un procedimiento o una
función, el modo Paso a paso por instrucciones va a permitir entrar en el código de la
función y luego lanzar la ejecución de su código línea por línea. El modo Paso a paso por
procedimientos ejecutará el procedimiento o la función de una sola vez sin que podamos
ver lo que ocurre en el interior del procedimiento o función.
El Paso a paso para salir permite la ejecución del código hasta el final de un procedimiento
o función, sin descomponer línea por línea, y después vuelve al modo de parada en la línea
que sigue a la llamada de la función.
Existe una última solución que nos permite ejecutar fácilmente un bloque de código y luego
detenerse en una línea específica. Para ello, un menú contextual en la ventana de código
nos ofrece la posibilidad de volver a lanzar la ejecución hasta la ubicación del cursor, sin
parar en todas las instrucciones entre la línea actual y la posición del cursor (muy útil para
ejecutar rápidamente todas las iteraciones de un bucle).
Como nos indica Microsoft, se debe utilizar este comando con precaución. Hay que
recordar los siguientes puntos: las instrucciones colocadas entre el antiguo y el nuevo punto
ShareVideos
de ejecución no se ejecutarán; desplazar el punto de ejecución hacia atrás no anula las
instrucciones ya tratadas; el punto de ejecución solo puede desplazarse dentro de una
función o procedimiento.
Solo tenemos una solución para pasar a modo de parada y consiste en utilizar las teclas
[Ctrl][Alt][Pausa]. Esta solución presenta un gran inconveniente: la ejecución se para en
cualquier punto. Los puntos de interrupción nos facilitan una solución más elegante gracias
a la cual podemos elegir la ubicación donde tendrá lugar la interrupción de la ejecución.
Los puntos de interrupción pueden ser condicionales. Se tienen en cuenta diferentes tipos
de condiciones en su activación (condición, número de paso...).
Los TracePoint son prácticamente idénticos a los puntos de interrupción, excepto que para
un TracePoint se puede especificar la acción ejecutada cuando se alcanza el punto. Puede
ser el paso en modo de parada de la aplicación o la visualización de un mensaje. En el
entorno Visual Studio, los puntos de interrupción o los TracePoint se muestran mediante
una serie de iconos. Los iconos vacíos representan un elemento desactivado.
ShareVideos
Para todas estas soluciones, el código debe ser visible en el editor. La opción Interrumpir
la función del menú Depurar - Nuevo punto de interrupción permite ubicar un punto de
interrupción en un procedimiento o función solo con teclear su nombre.
Cuidado: el cuadro de diálogo le propone precisar en qué línea de la función desea ubicar
un punto de interrupción, pero esta funcionalidad no está disponible para los puntos de
interrupción en funciones.
Los puntos de interrupción que se ubican así son incondicionales. En cuanto la ejecución
llega a esta línea, la aplicación pasa a modo detenido. Se puede perfeccionar el
funcionamiento de los puntos de interrupción al añadirles condiciones, un número de paso o
al transformarlos en TracePoint. Para ello, conviene modificar las propiedades del punto de
interrupción a través del menú contextual disponible haciendo un clic derecho en la línea
correspondiente.
En este cuadro de diálogo, debemos introducir una expresión que será evaluada a cada paso
por el punto de interrupción. Entonces la ejecución se parará:
Los puntos de interrupción también pueden contar el número de veces que se les alcanza y
activarse para un número particular de pasos.
ShareVideos
Este cuadro de diálogo nos permite definir el número de pasos en el punto de interrupción
para que este pare efectivamente la aplicación. Están disponibles cuatro opciones para la
condición de interrupción en el número de pasos.
Filtrado
Transformación en TracePoint
ShareVideos
evita así tener que recorrer muchas líneas de código para eliminar el conjunto de los puntos
de interrupción.
Para facilitarnos la tarea durante la depuración de una aplicación, una ventana nos muestra
un resumen de todos los puntos de interrupción ubicados en su proyecto. Esta ventana es
accesible por medio del menú Depurar - Ventanas - Punto de interrupción, y propone un
menú contextual que permite realizar las principales acciones sobre un punto de
interrupción.
a. DataTips
Los DataTips ofrecen un medio rápido para visualizar el contenido de una variable. Solo
hay que desplazar el cursor del ratón sobre el nombre y, en un momento, se visualiza una
ventana que presenta el contenido de la variable. Si la variable es un tipo complejo, como
una instancia de clase por ejemplo, el DataTips propone un pequeño signo + que permite
bajar en la estructura de la variable. Los datos mostrados también se pueden modificar
directamente en el DataTips. El DataTips desaparece automáticamente cuando aleja el
ratón.
Un pequeño truco: si desea visualizar el código ocultado por el DataTips sin hacerlo
desaparecer, puede utilizar la tecla [Ctrl], que lo vuelve transparente.
ShareVideos
b. Ventana Automático
La ventana Automático muestra las variables utilizadas en la instrucción actual, en las tres
instrucciones anteriores y en las tres instrucciones siguientes. Esta ventana es accesible a
través del menú Depurar - Ventanas - Automático.
Esta ventana también permite modificar el contenido de una variable haciendo doble clic en
el valor, introduciendo el valor nuevo y aceptando el cambio mediante la tecla [Intro]. La
aplicación seguirá ejecutándose con ese valor nuevo en la variable.
En todas estas ventanas, no es posible controlar la lista de las variables que se muestran, ya
que el depurador determina la lista en función del contexto en el que se encuentra la
aplicación. A veces es más práctico configurar manualmente la lista de las variables y
expresiones que queremos controlar durante el funcionamiento de la aplicación.
La ventana Inspección permite mostrar las variables que parecen interesantes para la
depuración de la aplicación. Esta ventana, o mejor dicho, estas ventanas, ya que existen
cuatro ventanas Watch, se muestran desde el menú Depurar - Ventanas - Inspección y
luego Inspección 1 a Inspección 4. A continuación debemos configurar la ventana
añadiendo las variables y expresiones que deseamos visualizar. Al hacer doble clic en la
columna Nombre, podemos escribir lo que deseamos visualizar en la ventana. También
podemos efectuar un arrastrar-soltar desde la ventana de código. Si escribimos el nombre
de variable compleja (por ejemplo, una instancia de clase), se visualiza, en forma de árbol,
el conjunto de sus propiedades en la ventana.
Solo se muestra el contenido de las variables si la aplicación está en modo de parada en una
línea de código a partir de la cual se puede acceder a la variable. Por ejemplo, el contenido
de las variables locales de un procedimiento o función solo se muestra si el código se para
en este procedimiento o función.
ShareVideos
En el caso contrario, la ventana Inspección nos indica simplemente que esta variable no
está declarada en la parte de código donde nos encontramos, mostrándola en caracteres
grises.
Como para las otras ventanas, se puede modificar el contenido de la variable haciendo
doble clic en ella para pasar al modo de edición y validar la modificación con la tecla
[Intro].
Existen otras ventanas de depuración, pero algunas de ellas no son realmente útiles para el
desarrollo de aplicaciones Visual Basic. Se reservan más bien para la prueba de
aplicaciones desarrolladas con otros lenguajes, como C++, por ejemplo.
ShareVideos
Puede utilizar la compilación condicional para especificar fragmentos que código que serán
o no compilados en función del valor de una constante definida previamente. Por ejemplo,
puede probar varias soluciones para resolver un problema utilizando varios algoritmos y
verificar cuál es el más eficaz.
El fragmento de código sometido a la condición debe estar colocado entre las instrucciones
#if condicion Then y #endif. En función del valor de la condición, el fragmento de código
será compilado o no. Por supuesto, es necesario que la variable o las variable(s) utilizada(s)
en la condición sea(n) inicializada(s) antes de su aparición en una instrucción #if.
End Sub
Las constantes se pueden declarar con la declaración #const, como en el ejemplo siguiente,
o en las propiedades del proyecto.
Sin embargo, hay que tener cuidado, ya que las constantes declaradas con estos dos
métodos solo se pueden utilizar para la compilacion condicional y no son accesibles desde
el código.
La clase Debug dispone de muchos métodos estáticos, y por lo tanto utilizables sin tener
que crear instancias de la clase, que nos permiten insertar instrucciones en el código para
seguir el desarrollo de la aplicación.
Con el método assert, se afirma que, cuando se ejecute esta línea de código, la condición
especificada en el método será verdadera.
ShareVideos
Debug.Assert(y <> 5)
Si la condición es falsa, Visual Basic muestra un cuadro de diálogo que resume la situación.
El método Fail es más radical, ya que muestra el mismo cuadro de diálogo, pero sin
ninguna condición. Se puede utilizar, por ejemplo, en un bloque Try End Try.
Try
z = 1 / x
Catch ex As Exception
Debug.Fail("división por cero")
End Try
Los métodos Write y WriteLine permiten seguir la evolución de una expresión sin que la
aplicación pase al modo de parada. La instrucción mostrará en la ventana de salida el
resultado de la evaluación de la expresión.
ShareVideos
de la aplicación. Estos elementos se recogen frecuentemente bajo el término Tecnología
Windows Forms. Una aplicación basada en Windows Forms utiliza uno o más formularios
para construir la interfaz de usuario de la aplicación. En estos formularios (o ventanas),
colocaremos controles, para definir exactamente el aspecto de la interfaz de la aplicación.
Los formularios se crean a partir de clases del Framework .NET que se podrán especializar
añadiendo funcionalidades. El formulario así creado es en sí una clase y será posible
utilizarlo en otra aplicación añadiéndole funcionalidades adicionales mediante una relación
de herencia. Se pueden crear los Windows Forms directamente con el código, pero el
entorno de desarrollo Visual Studio proporciona una serie de herramientas gráficas para
facilitarnos la tarea. Utilizaremos principalmente esta técnica.
En una aplicación de Windows, existen tres estilos de presentación para sus ventanas.
Solo hay una ventana disponible en la aplicación. Para poder abrir un nuevo documento, es
necesario cerrar el documento activo de la aplicación. El bloc de notas de Windows es una
aplicación SDI.
La aplicación está constituida por una ventana principal (la ventana madre), en la que
aparecerán varias ventanas (ventanas hijas) que contienen los documentos en los que se va
a trabajar. Por regla general, este tipo de aplicación dispone de un menú que permite la
organización de las diferentes ventanas hijas. Este tipo de presentación se utiliza en la
mayoría de las aplicaciones ofimáticas.
Este estilo de interfaz se desarrolla cada vez más con respecto a las otras dos. En este caso,
se divide la ventana en dos zonas. La zona de la izquierda presenta en forma de árbol los
elementos que la aplicación puede manipular. La zona de la derecha presenta el elemento
seleccionado en el árbol y permite su modificación. Muchas herramientas administrativas
utilizan esta presentación.
ShareVideos
Cuando comience una nueva aplicación de Windows Forms, el entorno de desarrollo añade
automáticamente un formulario al proyecto. Este formulario sirve de punto de partida para la
aplicación. Puede lanzar inmediatamente la ejecución de la solución y todo funciona. Obviamente,
la aplicación no permite hacer mucho, pero tiene todas las funcionalidades de una aplicación de
Windows y todo ello sin escribir una sola línea de código. En realidad, existe algo de código que
corresponde a esta aplicación, pero ha sido generado automáticamente por Visual Studio. Puesto
que este código nunca se debe modificar manualmente, los archivos que lo contienen están
ocultos en el explorador de soluciones. Para mostrarlos, puede utilizar el botón de la barra de
herramientas del explorador de soluciones. Podrá constatar que ya existen muchos archivos en el
proyecto. Todos los archivos reservados de Visual Studio tienen la extensión .designer.vb. Por
supuesto, se puede visualizar el contenido de estos archivos.
’-------------------------------------------------
’ <auto-generated>
’ This code was generated by a tool.
’ Runtime Version:2.0.50727.1433
’
’ Changes to this file may cause incorrect behavior and will be
’ lost if the code is regenerated.
’ </auto-generated>
’--------------------------------------------------
Option Strict On
Option Explicit On
Namespace My
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Public Sub New()
MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.Authenticatio
n
Mode.Windows)
Me.IsSingleInstance = false
Me.EnableVisualStyles = true
Me.SaveMySettingsOnExit = true
Me.ShutDownStyle =
Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainFo
rm
Closes
End Sub
ShareVideos
<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = Global.WindowsApplication1.Form1
End Sub
End Class
End Namespace
Los comentarios colocados en este archivo son muy claros: ¡nunca modifique este archivo
manualmente! Se actualiza de forma automática después de cada modificación de las
propiedades del proyecto. El segundo archivo, actualizado automáticamente, se asocia a la
ventana de la aplicación. En nuestra primera aplicación, se denomina form1.designer.vb.
Contendrá la descripción de todas las acciones, traducidas al código VB, que se van a
realizar para personalizar las características de la ventana.
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form
ShareVideos
Visual Studio se encarga de generar, dentro del archivo form1.designer.vb, el
código correspondiente a la personalización del aspecto de la ventana.
El usuario es responsable del código, contenido en el archivo form1.vb, encargado
de la personalización del funcionamiento de la ventana.
Para que sea posible eliminar todos los objetos instanciados por la clase, se crea un método
Dispose. Este método comienza eliminando los objetos creados; luego llama al método
Dispose de la clase madre.
ShareVideos
1. Dimensión y posición de las ventanas
Las dimensiones de la ventana se pueden modificar con la propiedad size, que contiene dos
miembros Width y Height que indican la anchura y la altura de la ventana.
Las unidades son píxeles para todas las propiedades relativas a las dimensiones y
posiciones de objetos. Las propiedades Left, Top, Height y Width están disponibles en el
código, pero no en la ventana de propiedades. La correspondencia con las propiedades
Location y Size de estas propiedades se indica entre paréntesis en el esquema.
El ancho y el largo de la ventana pueden variar dentro de los límites fijados por las
propiedades MinimumSize y MaximumSize. Por defecto, estas dos propiedades se
inicializan a 0. En este caso, el 0 indica que no hay un límite fijo para el tamaño de la
ventana.
ShareVideos
mostrar la ventana. La
propied
CenterParent La ventana está centrada en la ventana madre.
ad
CenterScreen La ventana está centrada en la pantalla. Windo
El sistema coloca automáticamente las ventanas a partir wState
de la esquina superior izquierda de la pantalla. Las indica
WindowsDefaultLocation ventanas bajan hacia la derecha de la pantalla cada vez el
que se muestra una nueva ventana. Las dimensiones de estado
cada ventana se especifican en la propiedad Size. de la
ventana
Mismo principio que en el caso anterior, pero el
. Los
WindowsDefaultBounds sistema determina las dimensiones cuando se muestra
tres
la ventana.
valores
posibles son:
ShareVideos
Estoy en la posición X:-32000
Estoy en la posición Y:-32000
Mi anchura: 160
Mi altura: 24
¡Las posiciones X e Y de la ventana son valores negativos! En realidad, puede usar valores
que estén dentro del límite de los valores aceptables para un entero. Solo se verá la parte de
su ventana que está entre el cero y la anchura y altura de su pantalla. Puede utilizar el
método GetBounds del objeto Screen para obtener las dimensiones de la pantalla.
Este código nos permite conocer las dimensiones de la pantalla que muestra la aplicación.
Para que el usuario pueda desplazar o modificar las dimensiones de la ventana, debe
disponer de las herramientas necesarias:
Para poder restaurar la ventana, esta debe disponer de un borde «sizable» asignado a su
propiedad FormBorderStyle.
Para poder ser desplazada, una ventana debe tener una barra de título. Esta barra de título se
puede ocultar con la propiedad ControlBox colocada en Falso. En ese caso, no se muestra
ni siquiera el título de la ventana especificado por la propiedad Text. Si la barra de título es
visible, sus diferentes botones se pueden controlar con las siguientes propiedades:
ShareVideos
anteriores no son visibles.
Del mismo modo, puede especificar que un color se considere transparente en su ventana.
Para hacerlo, debe asignar a la propiedad TransparencyKey el valor de ese color.
Para explicar la utilización poco clara de esta propiedad, hemos indicado en la ventana
siguiente que el color blanco era transparente (se ve una parte de la ventana de propiedades
a través de la zona de texto).
ShareVideos
También puede modificar las características de la fuente con el cuadro de diálogo estándar para
elegir la fuente. Este se muestra utilizando el botón , desde la propiedad Font en la ventana de
propiedades.
En VB.NET, se utiliza la misma clase base para los dos tipos de ventana. En el primer caso,
se indica simplemente que la ventana es una ventana madre MDI colocando en True su
propiedad IsMdiContainer Para añadir después una ventana hija, conviene por supuesto
crear primero la ventana y después asociarla a una ventana madre a través de su propiedad
MdiParent.
Este es un código que crea tres ventanas y las convierte en ventanas hijas MDI:
Para obtener ventanas hijas bien colocadas en su ventana madre, puede utilizar el método
LayoutMdi pasándole como parámetro una de las constantes predefinidas de la
enumeración MdiLayout:
Me.LayoutMdi(MdiLayout.TileHorizontal)
Me.LayoutMdi(MdiLayout.TileVertical)
Me.LayoutMdi(MdiLayout.Cascade)
ShareVideos
Se suele llamar a estos diferentes métodos mediante un menú de la aplicación que
proporciona la lista de las ventanas abiertas en la aplicación. Veremos cómo hacerlo en la
sección dedicada a los menús.
Para ilustrar otras posibles acciones con las ventanas MDI, vamos a realizar una aplicación
del estilo explorador. Veamos a continuación el aspecto general de la aplicación.
Modifique la propiedad Dock del control TreeView en Left para que se ajuste al borde
izquierdo de la ventana.
Agregue los elementos al control TreeView con la ayuda del editor de nodos.
En nuestra aplicación, la propiedad Name de los nodos raíz se utiliza para determinar el
tipo de documento (tx para archivo texto, gr para archivo gráfico). En el resto de los nodos
del árbol, guarda el nombre del archivo respectivo.
ShareVideos
Agregue un control PictureBox.
Establezca la propiedad Dock de este control en Fill para que ocupe toda la superficie
disponible de la ventana.
Establezca la propiedad Dock de este control en Fill para que ocupe toda la superficie
disponible de la ventana.
Nos resta ahora escribir las líneas de código para mostrar la ventana correcta al efectuar una
selección sobre el control TreeView. A continuación presentamos dichas líneas de código:
ShareVideos
solicitado consultando la propiedad Name del nodo Padre del elemento seleccionado (gr o
tx). En función del resultado, creamos una instancia de la ventana acorde a la situación.
Establecemos el enlace de parentesco con la ventana principal (propiedad MdiParent). La
ventana mostrada ocupará toda la superficie libre de la ventana madre Mdi (propiedad
Dock=DockStyle.Fill). Por último, mostramos el documento con el control RichTextBox o
PictureBox, según corresponda.
Las posibilidades de acción del usuario en el teclado son limitadas: puede simplemente
pulsar una tecla del teclado.
KeyDown
KeyUp
KeyPress
Este evento se produce cuando se pulsa la tecla, pero solo si esta corresponde a un carácter
ASCII.
[Alt] indica el estado de la tecla [Alt] del teclado en el momento en que se produce
el evento.
[Ctrl] y [Mayús] proporcionan datos iguales para las teclas [Ctrl] y [Mayús].
KeyCode indica el número de la tecla en el teclado.
ShareVideos
El evento KeyDown se utiliza principalmente para trabajar con las teclas de función.
Podemos, por ejemplo, convertir en mayúsculas el texto de un control TextBox si el usuario
pulsa la combinación de teclas [Mayús][Ctrl][Alt][F8].
Otra solución sería utilizar la propiedad Modifiers, que recoge el estado de las teclas
[Mayús], [Ctrl] y [Alt].
ShareVideos
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As
System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If Not IsNumeric(e.KeyChar) Then
Beep()
e.Handled = True
End If
End Sub
Si muchos controles TextBox deben tener el mismo funcionamiento, puede copiar este
código en los eventos KeyPress de cada control. Una solución más elegante nos permite
centralizar el tratamiento en el evento KeyPress de la ventana. Para hacerlo, conviene
indicar a la propiedad KeyPreview de la ventana que recibirá los eventos de teclado antes
que el control de la ventana focalizada. Solo hace falta probar el control activo de la
ventana y verificar que «reciba» el tratamiento.
Estos eventos están relacionados con la utilización de los botones o de la rueda del ratón. El
evento Click es el evento de ratón más utilizado. Consiste en pulsar y luego soltar el botón
principal del ratón. Es necesario hablar de botón principal del ratón, ya que, en función de
la configuración del puesto de trabajo, este botón principal puede ser también el botón
derecho (configuración para zurdos). El evento DoubleClick no funciona con todos los
controles, así que, por ejemplo, los controles Button no son capaces de gestionar el doble
clic y de hecho generan dos eventos Click seguidos.
Para estos tres eventos, existe un parámetro de tipo MouseEventArgs. A través de las
propiedades disponibles en esta clase, se obtienen los siguientes datos:
ShareVideos
desplazamiento de una posición de la rueda aumenta o disminuye esta propiedad
con un valor de 120.
Las propiedades X e Y indican el emplazamiento en el control en el que el evento
de ratón se acaba de producir.
Como para los eventos relativos a los botones del ratón, se nos proporciona un parámetro
del tipo MouseEventArgs en estos eventos.
Un pequeño ejemplo para probarlo con una aplicación de diseño muy sencillo.
A cada desplazamiento del ratón, se dibuja un punto en la ventana con el color indicado por
las tres zonas de texto (rojo, verde, azul). Para modificar el color, es suficiente desplazar el
ratón encima de la zona de texto correspondiente (se focaliza automáticamente gracias al
evento MouseHover) y accionar la rueda del ratón para aumentar o disminuir el porcentaje.
ShareVideos
Private Sub txtVerde_MouseWheel(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles txtVerde.MouseWheel
verde += e.Delta / 120
If verde > 100 Then
verde = 100
txtVerde.Text = "100%"
ElseIf rojo < 0 Then
verde = 0
txtVerde.Text = "0%"
Else
txtVerde.Text = verde & "%"
End If
End Sub
El Drag and Drop es una funcionalidad muy útil en las aplicaciones de Windows. Permite
el desplazamiento de datos en una aplicación o entre aplicaciones, «pegando» un elemento
al cursor del ratón y dejándolo después encima de su destino.
Se puede pegar prácticamente cualquier elemento al cursor del ratón para luego desplazarlo
o copiarlo (texto, imagen, archivo...). Para guiar al usuario sobre esas posibilidades, el
cursor del ratón se modifica en función de los controles que se sobrevuelan con el ratón.
ShareVideos
Una operación de Drag and Drop se desarrolla en tres fases:
Vamos a ver en detalle el código necesario para realizar con éxito una operación de Drag
and Drop. Tomemos un ejemplo sencillo, realizando una copia entre dos zonas de texto
(TxtOrigen, TxtDestino).
Una operación de Drag and Drop se suele iniciar cuando el ratón se mueve encima de un
control y lo selecciona sin dejar de pulsar el botón del ratón. En este caso, el usuario acaba
de pegar el control al ratón.
En el código, esto se traduce simplemente con la llamada del método DoDragDrop del
control de partida. La llamada de este método necesita dos parámetros:
El elemento que pegamos al cursor del ratón (cadena de caracteres, una imagen de
bitmap o una imagen metafile).
Las operaciones autorizadas para el objeto seleccionado (copia, desplazamiento...).
Conviene antes que nada configurar los controles de destino para que acepten la recepción
de un elemento modificando la propiedad AllowDrop a true.
Después, debemos gestionar el evento DragEnter que se produce cuando el ratón entra en la
superficie del control con un elemento «pegado». En la gestión de este evento, se debe
determinar qué es lo que está pegado al cursor del ratón para saber si el control lo puede
ShareVideos
aceptar. Finalmente, hay que determinar si el usuario desea desplazar o hacer una copia del
elemento pegado al cursor del ratón.
AllowedEffect
Permite saber cuáles son las operaciones autorizadas por el control de origen del Drag and
Drop.
Data
Contiene los datos pegados al cursor del ratón. A través de esta propiedad, se puede obtener
el tipo de dato llamando al método GetDataPresent u obtener los datos llamando al método
GetData.
Effect
Indica la acción autorizada por el control de destino. Esta propiedad se utiliza para
controlar el aspecto del cursor del ratón.
KeyState
Indica el estado de las teclas [Mayús], [Ctrl], [Alt] que nos permiten saber si el usuario
desea realizar un desplazamiento o una copia.
X, Y
ShareVideos
c. Recuperación del elemento pegado
Cuando el usuario deja de pulsar el botón del ratón, se produce el evento DragDrop en el
control de destino. En este evento, hay que recuperar el elemento pegado y colocarlo en el
control de destino. Si se trata de un desplazamiento, también se debe eliminar la
información del control fuente. Problema: ¿quién es el control fuente? No tenemos
información sobre su identidad. La solución consiste en almacenar en una variable una
referencia hacia el control de origen de la operación de Drag and Drop al principio de la
operación.
1. El cuadro de recogida
El cuadro de recogida permite pedirle al usuario que introduzca una cadena de caracteres.
Se puede acceder a esta posibilidad por medio de la función InputBox. Esta función espera
tres parámetros:
ShareVideos
El texto mostrado en el cuadro (en general, la pregunta hecha al usuario).
El título del cuadro de diálogo.
Un valor predeterminado mostrado en la zona de introducción de texto.
La función devuelve una cadena de caracteres que corresponde al texto introducido por el
usuario, si este valida lo tecleado con el botón Aceptar. Por el contrario, devuelve una
cadena de caracteres vacía.
2. El cuadro de mensaje
Los cuadros de mensaje permiten mostrar una información al usuario y le dan la posibilidad
de contestar a través de botones de comando del cuadro de mensaje.
El cuadro de mensaje está disponible a través del método Show, en la clase MessageBox.
Este método acepta muchos parámetros para configurar el cuadro de diálogo. El primer
parámetro corresponde al mensaje mostrado. El parámetro siguiente especifica el título del
cuadro de mensaje. Los siguientes parámetros deben ser elegidos entre las constantes
predefinidas para indicar respectivamente:
Constante Significado P
ara la
MessageBoxButtons.OK Botón OK solo elecció
MessageBoxButtons.OKCancel Botones OK y Cancelar n de los
Botones Abandonar, Reintentar y iconos:
MessageBoxButtons.AbortRetryIgnore
Cancelar
P
MessageBoxButtons.YesNoCancel Botones Sí, No y Cancelar ara el
MessageBoxButtons.YesNo Botones Sí y No botón
MessageBoxButtons.RetryCancel Botones Reintentar y Cancelar por
defecto:
Constante Significado
MessageBoxIcon.IconInformation
MessageBoxIcon.IconExclamation
MessageBoxIcon.IconError
MessageBoxIcon.IconQuestion
ShareVideos
Constante Significado
MessageBoxDefaultButton.DefaultButton1 Primer
botón Para obtener el cuadro de mensaje
siguiente:
Segundo
MessageBoxDefaultButton.DefaultButton2
botón
Tercer
MessageBoxDefaultButton.DefaultButton3
botón utilizaremos el código siguiente:
Como le hacemos una pregunta al usuario, tenemos que recuperar su respuesta para decidir
qué hacer en la aplicación. Para ello, el método Show reenvía un valor que indica el botón
utilizado para cerrar el cuadro de mensaje. Aquí también se definen una serie de constantes
para identificar cada posible caso.
Muchos cuadros de diálogo ya están definidos a nivel del propio sistema operativo
Windows. Para poderlos utilizar en nuestras aplicaciones, tenemos a nuestra disposición
una serie de clases. Vamos a ver cómo configurarlas y utilizarlas en una aplicación.
Este cuadro de diálogo nos permite seleccionar uno o más nombres de archivo, con la
posibilidad de desplazarse en la estructura en árbol de la máquina. Se utiliza la clase
OpenFileDialog. Debemos entonces crear una instancia en nuestra aplicación.
ShareVideos
apertura. Es posible mostrar solo algunos archivos en los directorios que se verán. Para ello,
hay que configurar a través de la propiedad Filter las correspondencias entre la descripción
del contenido y la extensión asociada. La propiedad Filter almacena la información en
forma de cadena de caracteres. La descripción y la extensión se separan en la cadena con el
carácter | ([AltGr] 1). Si existen muchas extensiones disponibles para una misma
descripción, deben separarse con un punto y coma en la cadena. También puede indicar si
se debe agregar una extensión a los nombres de los archivos escritos manualmente, si estos
no la llevan.
dlgAbrir.InitialDirectory = "c:\dos"
dlgAbrir.Title = "seleccione el archivo que quiere abrir"
dlgAbrir.Filter ="Todos|*.*|Imagenes|*.bmp;*.gif;*.jpg|texto|*.txt"
dlgAbrir.DefaultExt = "txt"
dlgAbrir.AddExtension = True
dlgAbrir.CheckFileExists = False
dlgAbrir.Multiselect = True
dlgAbrir.ShowDialog()
Los nombres del archivo o de los archivos seleccionados están disponibles en la propiedad
FileName para una selección única o en la propiedad FileNames para las selecciones
múltiples. Esta propiedad FileNames es una matriz de cadenas de caracteres que contiene
en cada casilla el nombre completo de uno de los archivos seleccionados.
ShareVideos
utilizada es ciertamente la propiedad SelectedPath, que permite la recuperación de una ruta
de acceso al directorio seleccionado. El directorio raíz del cuadro de diálogo está indicado
por la propiedad RootFolder. Esta propiedad recibe uno de los valores de la enumeración
Environment.SpecialFolder, que representa los principales directorios característicos del
sistema, como por ejemplo el directorio Mis Documentos. Si se utiliza esta propiedad, la
selección deberá hacerse en un subdirectorio debajo del directorio raíz. Modificando la
propiedad ShowNewFolderButton, podemos agregar un botón que permita la creación de
un nuevo directorio. El método ShowDialog permite la visualización del cuadro de diálogo.
dlgSelecDirectorio.RootFolder = Environment.SpecialFolder.MyDocuments
dlgSelecDirectorio.ShowDialog()
MsgBox(dlgSelecDirectorio.SelectedPath, , ”Directorio Seleccionado”)
Nótese también que la ruta de acceso retornada por este cuadro de diálogo es una ruta
absoluta, como muestra el siguiente ejemplo:
Una versión «sencilla» en la que solo están disponibles los colores de base:
La visualización del cuadro de diálogo se realiza también con el método ShowDialog. Para
conservar una calidad de visualización correcta, también puede autorizar solo la utilización
de los colores puros (los colores obtenidos sobreponiendo diferentes píxeles se eliminarán
de las posibles opciones). Esta opción se debe usar si se tiene una tarjeta gráfica
configurada en 256 colores.
ShareVideos
dlgColor = New ColorDialog()
dlgColor.FullOpen = True
dlgColor.SolidColorOnly = True
dlgColor.Color = Me.BackColor
dlgColor.ShowDialog()
Me.BackColor = dlgColor.Color
La clase base utilizada para la selección de una fuente es la clase FontDialog. La propiedad
Font permite definir la fuente de caracteres utilizada para inicializar el cuadro de diálogo o,
después de cerrarlo, para recuperar la fuente seleccionada. También puede mostrar un
cuadro de diálogo simplificado sin la elección de color o de los efectos. Para hacerlo, las
propiedades ShowColor y ShowEffects controlan la visualización de estos parámetros en el
cuadro de diálogo. Para garantizar que los parámetros seleccionados correspondan a una
fuente existente en la máquina, puede utilizar la propiedad FontMustExist. Esta propiedad
obligará a que el cuadro de diálogo verifique la existencia de una fuente correspondiente en
el sistema operativo antes de cerrarse. Algunas fuentes contienen muchos juegos de
caracteres. Puede autorizar a los usuarios a elegir uno de esos juegos de caracteres
modificando la propiedad AllowScriptChange. La dimensión de la fuente seleccionada
puede limitarse con las propiedades MaxSize y MinSize.
Para inspeccionar el efecto de la fuente seleccionada, existe una vista previa de algunos
caracteres. Si esta vista previa no es suficiente, tiene la posibilidad de mostrar un botón
Aplicar en su cuadro de diálogo a través de la propiedad ShowApply. Este botón activa un
evento Apply en el cuadro de diálogo. En la gestión de este evento, puede utilizar la
propiedad Font del cuadro de diálogo para visualizar el efecto de la fuente actualmente
seleccionada en su texto. La variable que hace referencia al cuadro de diálogo debe
declararse con la palabra clave WithEvents; por lo tanto, fuera de un procedimiento.
ShareVideos
dlgFont.ShowDialog()
txtPrueba.Font = dlgFont.Font
End Sub
Private Sub dlgFont_Apply(ByVal sender As Object, ByVal e
As System.EventArgs)
Handles dlgFont.Apply
txtPrueba.Font = dlgFont.Font
End Sub
End Class
Este cuadro de diálogo se crea a partir de la clase PageSetupDialog. Para trabajar, esta clase
necesita dos clases auxiliares: la clase PageSettings sirve para almacenar la configuración
de la maquetación; la clase PrinterSettings almacena la configuración de la impresora
seleccionada. Hay que crear una instancia de estas dos clases y asociarlas a las propiedades
PageSettings y PrinterSettings del cuadro de diálogo. Debe importar el espacio de nombres
System.Drawing.Printing para poder utilizar estas dos clases.
Las elecciones del usuario se recuperarán después, usando las propiedades PageSettings y
PrinterSettings del cuadro de diálogo.
Imports System.Drawing.Printing
Public Class Form2
Inherits System.Windows.Forms.Form
ShareVideos
MessageBox.Show("ha elegido la impresora " _
& dlgPgSetup.PrinterSettings.PrinterName _
& " en papel " _
& dlgPgSetup.PageSettings.PaperSize.PaperName _
& " en formato " _
&(IIf(dlgPgSetup.PageSettings.Landscape, "horizontal", "vertical")))
End Sub
End Class
ShareVideos
& dlgprinter.PrinterSettings.FromPage & " a la página "
_
& dlgprinter.PrinterSettings.ToPage)
Case PrintRange.Selection
MessageBox.Show("ha pedido la impresión de la selección")
End Select
Después de este breve resumen sobre los cuadros de diálogo predefinidos, vamos a ver
cómo crear nuestros propios cuadros de diálogo. La base para la creación de un cuadro de
diálogo es una ventana clásica en la que se modifican las siguientes propiedades:
El estilo del borde, para obtener una ventana que no tenga un tamaño variable.
La propiedad ShowInTaskBar, que está colocada en False para que la ventana no
aparezca en la barra de tareas.
Es también necesario disponer de un botón de validación y un botón de anulación
para el cierre del cuadro de diálogo.
Ahora que sabemos cómo configurar y mostrar un cuadro de diálogo, nos queda lo más
difícil: crear la interfaz visual del cuadro de diálogo.
ShareVideos
Utilización de los controles
Los controles nos permitirán crear la interfaz entre la aplicación y su usuario. Es a través de
ellos que el usuario podrá actuar sobre el funcionamiento de la aplicación escogiendo el
texto, eligiendo las opciones, lanzando la ejecución de una parte específica de nuestra
aplicación, etc.
Los controles estarán disponibles en VB.NET a través de una serie de clases que deberemos
instanciar durante la ejecución de la aplicación.
Estas diferentes clases dependen de una jerarquía que comienza por la clase base Control.
Esta clase garantiza las funciones elementales de los controles (posiciones, dimensiones...)
y una clase derivada agrega funcionalidades adicionales, y así hasta la clase final de la
jerarquía.
1. Agregar controles
Los controles pueden agregarse a una ventana de dos maneras diferentes. La más sencilla y
rápida es la utilización del cuadro de herramientas. Existen tres posibilidades para agregar
controles:
Si quiere colocar muchos ejemplares del mismo control en su ventana, es posible bloquear
la selección en el cuadro de herramientas utilizando la tecla [Ctrl] cuando selecciona el
control en el cuadro de herramientas. Podrá colocar entonces diferentes ejemplares del
mismo control sin tener que volver a seleccionarlos en el cuadro de
herramientas manteniendo presionada la tecla [Ctrl].
ShareVideos
código de su aplicación será menos eficaz (se precisarán algunas operaciones adicionales
para acceder al control ActiveX).
Los controles agregados son nombrados automáticamente por Visual Studio, aunque estos
nombres no sean muy explícitos.
Button1.Enabled = False
TextBox1.Clear()
CheckBox1.Checked = True
RadioButton1.Checked = False
RadioButton2.Checked = True
Es primordial, para que el código sea legible, renombrar los controles preferentemente
durante su creación o más tarde, pero antes de ser utilizados en el código. Es suficiente con
cambiar la propiedad NAME de cada uno en la ventana de propiedades. No hay una regla
absoluta que sea preciso respetar a la hora de dar nombre a los controles. Una solución
frecuentemente utilizada consiste en asociar un prefijo representativo del tipo del control a
un nombre explicitado para la aplicación. Los prefijos no están normalizados, pero la regla
siguiente existe desde las primeras versiones de Visual Basic.
ShareVideos
las etiquetas de los controles. El control será efectivamente desplazado en el momento en
que se suelta el botón del ratón.
También es posible usar las flechas del teclado, que además aportan mayor precisión al
desplazamiento.
Finalmente, la última posibilidad es modificar con el código las propiedades Left y Top del
control. El siguiente fragmento de código permite desplazar el botón a una posición
aleatoria cada vez que haga clic encima de él.
Una funcionalidad más avanzada permite colocar los controles en función de la posición de
otros controles. Para poderlas utilizar, es necesario seleccionar varios controles en su
ventana. Para hacerlo, hay dos soluciones:
Las opciones del menú Formato de VB.NET ahora están disponibles y le proporcionan
muchas opciones para colocar los controles. El control que aparece en la selección con
puntos de selección blancos se considera como referencia para la alineación.
Existen muchas otras opciones para organizar la colocación de los controles en su ventana.
ShareVideos
dirección puede cambiar la dimensión del control. Luego hay que hacer clic en el cuadrado
correspondiente y desplazar el ratón hasta que el control haya adquirido las dimensiones
deseadas.
También puede utilizar las flechas del teclado en asociación con la tecla [Mayús] para
dimensionar los controles.
El cambio de dimensiones con el código utiliza el método SetBounds, que permite a la vez
fijar la posición y las dimensiones del control. El siguiente código disminuye las
dimensiones del botón cada vez que se hace clic encima.
Después de muchos esfuerzos para colocar y dimensionar los controles, sería una pena que
un error de manipulación lo estropeara todo. Para evitar que eso pase, es posible proteger
los controles en la ventana, a través del menú Formato - Bloquear controles. Este
comando bloquea el desplazamiento y el cambio de dimensiones de todos los controles
presentes en la ventana, así como el cambio de dimensiones de la propia ventana. Los
controles pueden desprotegerse después con la misma opción de menú. También puede
desproteger individualmente los controles con la propiedad Locked.
Si crea una aplicación en la que el usuario pueda cambiar el tamaño de la ventana durante
la ejecución, los controles deben seguir las modificaciones de dimensión de la ventana.
Para autorizar el cambio automático del tamaño de un control, puede utilizar la propiedad
Anchor del control. A través de ella, indica que la distancia entre los bordes del control y
las posiciones de anclaje se guardará durante el cambio del tamaño de la ventana. Cuando
se crean, los controles están anclados a los bordes superior e izquierdo de la ventana. La
modificación de esta propiedad se realiza con un pequeño asistente, disponible en la
ventana de propiedades.
Por ejemplo, para la siguiente ventana, los controles están anclados a la izquierda y a la
derecha.
ShareVideos
Si cambiamos el tamaño de la ventana, los controles siguen la maximización horizontal de
la ventana.
También puede indicar que un control debe adaptar una o más de sus dimensiones a las de
su contenedor. Para hacerlo, utilice la propiedad Dock del control, indicando en qué borde
de su contenedor debe adaptar el control una de sus dimensiones.
Por ejemplo, podemos colocar un control PictureBox pidiendo que se fije al borde inferior
de la ventana.
Cuando crea su aplicación, debe pensar en las personas a las que no les gusta usar el ratón,
pero que deben poder utilizar la aplicación. Conviene, por lo tanto, crear la aplicación de
manera que pueda funcionar utilizando solo el teclado (¡sin teclado ni ratón será mucho
más difícil!).
En una aplicación de Windows, se dice que un control tiene foco cuando está listo para que
el usuario lo utilice. El foco se puede mover de un control a otro utilizando la tecla [Tab].
Dos propiedades de los controles manejan el paso del foco con la tecla [Tab].
Por defecto, las propiedades TabIndex se numeran según el orden en el que los controles se
han creado.
Para modificar este orden, puede modificar directamente la propiedad TabIndex de cada
control o usar el menú Ver - Orden de tabulación. Los controles se muestran entonces con
el valor de su propiedad TabIndex en la esquina superior izquierda.
Después debe hacer clic en los controles, en el orden en que quiere que se pase el foco.
El siguiente orden parece mucho más lógico para este cuadro de diálogo.
ShareVideos
Después puede volver al modo normal utilizando otra vez el menú Ver - Orden de
tabulación o utilizando la tecla [Esc].
Algunos usuarios con prisa quieren poder situarse directamente en un control sin tener que
pasar por todos los que le preceden en el orden de las tabulaciones. Para ello, puede agregar
una tecla de acceso rápido que se activará a través de la tecla [Alt] más un carácter. Para
especificar el carácter que se debe utilizar para activar el control, hay que agregar en la
propiedad Text del control un carácter «&» delante del carácter utilizado para la tecla de
acceso rápido asociada al control. Esto hace que se active el atajo y se subraye el carácter
en el texto que aparece en el control.
Si quiere insertar un carácter & en la leyenda de su control, hay que repetirlo dos veces en
su propiedad Text.
Para algunos controles (botones, check box, botones de opción...) la utilización del atajo de
teclado equivale a un clic del ratón y lanza la acción correspondiente. Para otros, el atajo de
teclado coloca simplemente el foco en el control correspondiente.
Para los controles que no tienen leyenda, habrá que utilizar un control LABEL, que les
servirá de leyenda y que activará también el atajo de teclado. Veremos todo esto más
adelante en este capítulo.
Ahora que sabemos utilizar los controles en una aplicación, vamos a analizar
detalladamente los más usados.
ShareVideos
1. La clase Control
a. Dimensiones y posición
Las propiedades Left, Top, Width, Height permiten colocar los controles. Estas propiedades
pueden ser modificadas individualmente y aceptan valores del tipo Integer.
TextBoxNombre.Left = 100
TextBoxNombre.Top = 50
TextBoxNombre.Width = 150
TextBoxNombre.Height = 50
Otras dos propiedades permiten trabajar con la posición y las dimensiones de un control: la
propiedad Location acepta un objeto del tipo Point, gracias al que podemos especificar la
posición de nuestro control; del mismo modo, la propiedad Size, que acepta un objeto del
tipo Size, gestiona las dimensiones del control. Las líneas anteriores se pueden reemplazar
con:
En las que construiremos una instancia de Point y de Size, antes de asociarlas a las
propiedades correspondientes.
Una tercera posibilidad nos permite manipular a la vez la posición y las dimensiones de los
controles: la propiedad Bounds espera una instancia de la clase Rectangulo para definir las
características del control. Nuestro código se resume entonces en una sola línea:
El método SetBounds permite modificar las posiciones y dimensiones de los controles sin
tener que crear una nueva instancia de la clase Rectangulo, pero modificando la que ya está
asociada al control.
ShareVideos
Hasta ahora, las posiciones con las que hemos trabajado eran posiciones expresadas con
relación a la esquina superior izquierda del contenedor del control. En algunos casos, puede
ser útil obtener las coordenadas de un punto del control no con relación a la esquina
superior izquierda del control, sino con relación a la esquina superior izquierda de la
pantalla. El método PointToScreen permite esta conversión.
Espera, como parámetro, una instancia de la clase Point con las coordenadas expresadas
con relación al control y reenvía una nueva instancia de la clase Point con las coordenadas
expresadas con relación a la pantalla.
System.Console.Write("Control/ventana:")
System.Console.WriteLine(Button2.Location)
Dim p As Point
p = Button2.PointToScreen(Button2.Location)
System.Console.Write("Control/pantalla:")
System.Console.WriteLine(p)
Resultado:
Control/ventana:{X=107,Y=72}
Control/pantalla:{X=306,Y=255}
La operación contraria se puede realizar con el método PointToClient, que toma como
parámetro un punto en coordenadas de pantalla y reenvía un punto expresado en
coordenadas relativas al control. Si se realiza la operación contraria, es decir, partiendo de
las coordenadas de pantalla, se obtiene el mismo valor:
Resultado:
El color de fondo del control se puede modificar con la propiedad BackColor, mientras que
el color del texto del control se modifica con la propiedad ForeColor.
ShareVideos
TextBoxNombre.BackColor = System.Drawing.Color.Yellow
TextBoxNombre.BackColor=System.Drawing.SystemColors.InactiveCaptionText
La fuente se puede modificar con la propiedad Font del control. Se puede crear una nueva
instancia de la clase Font y asignarla al control. Existen trece constructores diferentes para
la clase Font, o sea trece maneras distintas de crear una fuente de letra. Nosotros vamos a
usar la más sencilla, indicando simplemente el tipo de fuente y las dimensiones.
Después de haber realizado las modificaciones de estas propiedades, es posible volver a una
configuración normal llamando a los métodos ResetBackColor, ResetForeColor, ResetFont.
Las correspondientes propiedades se reinician con los valores definidos por el contenedor
del control.
BtnValidar.BackgroundImage = Nothing
La propiedad Cursor permite elegir el aspecto del cursor cuando el ratón se encuentra en la
superficie del control. Muchos cursores están predefinidos en Windows.
ShareVideos
Estos cursores están en la colección Cursors y pueden utilizarse directamente
asignándolos a la propiedad Cursor del control.
BtnValidar.Cursor = Cursors.WaitCursor
Como para la fuente de caracteres, es posible restaurar el cursor por defecto llamando al
método ResetCursor.
Los controles colocados en una ventana se pueden ocultar modificando la propiedad Visible
o desactivar modificando la propiedad Enabled. En este caso, el control está siempre
visible, pero aparece con un aspecto gris para indicarle al usuario que este control está
inactivo por el momento.
BtnValidar.Enabled = False
Obviamente, los controles en este estado no pueden recibir el foco en la aplicación. Puede
verificarlo examinando la propiedad CanFocus, que reenvía un Booleano. Puede verificar
también si un control tiene el foco en un momento dado controlando la propiedad Focused
o la propiedad ContainsFocus. Esta última se tiene que utilizar con los controles
contenedores (es decir, los controles que pueden contener otros controles). En este caso,
esta propiedad se coloca en True si uno de los controles situados dentro del contenedor está
focalizado.
El foco puede colocarse en un control sin la intervención del usuario, llamando el método
Focus del control.
ShareVideos
BtnValidar.Focus()
Para controlar el paso del foco de un control a otro, existen cuatro eventos:
Por ejemplo, para destacar que un control está focalizado, se puede utilizar el siguiente
código, que modifica el color del texto cuando el control recibe o pierde el foco:
Cada control se puede configurar para permitir la verificación de estos datos modificando la
propiedad CausesValidation a True. Justo antes de que el control pierda el foco, el evento
Validating se activa para permitir la verificación de los datos introducidos por el usuario. Si
lo tecleado no es correcto (en función de los criterios que hemos establecido), podemos
bloquear el paso del foco hacia otro control modificando la propiedad Cancel del objeto
CancelEventArg que se pasa como parámetro. En este caso, el foco se queda en el control
correspondiente a los datos introducidos que no son correctos. Si los datos son correctos, el
evento Validated se activa en el control y el foco se desplaza al control siguiente.
Por ejemplo, para introducir un número de teléfono, podemos verificar que se han
introducido solo valores numéricos. En caso de error, generamos un beep, modificamos el
color del texto y bloqueamos el paso del foco a otro control.
ShareVideos
Private Sub TxtTel_Validated(ByVal sender As Object, ByVal e As
System.
EventArgs) Handles txtTel.Validated
txtTel.ResetForeColor()
End Sub
Dos propiedades son útiles cuando trabajamos con controles contenedor. La propiedad
HasChildren nos permite saber si hay controles colocados en nuestro contenedor. Si es el
caso, la colección Controls contiene la lista de todos estos controles. Por ejemplo, podemos
modificar el color del texto de todos los controles de un contenedor cuando el foco está
colocado en uno de ellos.
Ahora que hemos explorado las propiedades comunes de los distintos controles disponibles,
vamos a estudiarlos uno por uno analizando sus particularidades.
ShareVideos
2. Los controles de visualización de información
a. El control Label
El control Label se usa para mostrar, en un formulario, un texto que el usuario no podrá
modificar. Sirve esencialmente para proporcionar una leyenda a los controles que no la
poseen (zonas de texto por ejemplo, lista desplegable...). En este caso, permitirá también
proporcionar un atajo de teclado para el control.
El texto mostrado por el control se indica con la propiedad Text. Esta propiedad puede, por
supuesto, modificarse con el código de la aplicación. Por lo tanto, hay que tener cuidado,
porque por defecto el control conserva las dimensiones que le han asignado en su creación.
Si la nueva cadena de caracteres asignada a la propiedad Text es más larga que la
especificada en el momento de la creación, solo se podrá ver el inicio. Para evitar este
problema, hay que pedirle al control Label que adapte su anchura en función del texto que
se va a mostrar, modificando la propiedad AutoSize en True.
Por defecto, el control Label no tiene borde. Puede añadirlo modificando la propiedad
BorderStyle, y utilizando uno de los tres valores disponibles.
Hay que resaltar que la propiedad TextAlign modificará la posición del texto solo si la
propiedad AutoSize está en False.
Los controles Label también pueden mostrar imágenes. Puede indicar la imagen que desea
mostrar utilizando la propiedad Image. Otra solución consiste en usar un control ImageList,
que servirá, de alguna manera, para almacenar las imágenes de la aplicación. En este caso,
indicamos con la propiedad ImageList en qué control vamos a buscar la imagen y con la
propiedad ImageIndex en qué lugar se encuentra en el control ImageList. Si utiliza un
control ImageList, la propiedad Image de su control se ignorará. Como para el texto, puede
modificar la posición de la imagen en el control gracias a la propiedad ImageAlign, con las
mismas constantes que para la propiedad TextAlign.
ShareVideos
Hemos indicado que el control Label se podía utilizar como atajo de teclado para otro
control. Para hacerlo, hay que tomar tres precauciones.
Como con los otros controles, agregar un & en la propiedad Text para el carácter
utilizado como tecla de acceso rápido.
Indicar al control Label su papel de gestor de atajo de teclado modificando la
propiedad UseMnemonic en True.
Verificar que el control que debe recibir la focalización está inmediatamente
después del control Label en el orden de las tabulaciones (propiedad TabIndex).
b. El control LinkLabel
El control LinkLabel hereda todas las características del control Label y solo agrega
funcionalidades de enlace de estilo Web. Las propiedades adicionales en relación con el
control Label gestionan los diferentes parámetros del enlace.
La propiedad LinkArea indica qué porción del texto activará el enlace. Esta propiedad se
puede modificar a través de la ventana de propiedades, con un pequeño asistente en el que
tiene que seleccionar la porción de texto que constituye el vínculo.
Los colores utilizados para el enlace se pueden modificar con tres propiedades:
Tiene también que modificar la propiedad LinkVisited colocándola en True, para indicar
que este enlace ya ha sido utilizado en la aplicación.
ShareVideos
La acción puede ser la apertura de una página de un sitio Web en el navegador por defecto,
como en el siguiente ejemplo:
c. El control StatusStrip
El control StatusStrip se usa normalmente para presentar información al usuario acerca del
funcionamiento de la aplicación. Puede mostrar la información en distintas zonas. Los datos
se pueden mostrar en forma de texto, de barra de progreso, de menú o de botón de comando
asociado a un menú. Un editor específico, accesible desde la propiedad Items del control,
permite su configuración.
d. El control ToolTip
Este control permite mostrar una etiqueta de ayuda asociada a un control. Este control no
tiene interfaz visible: se colocará en la zona situada por debajo de la ventana de diseño.
Realiza mucho trabajo sin ningún esfuerzo de programación. Controla siempre, por
ejemplo, dónde se encuentra el ratón. Si está encima de un control, verifica si existe una
sugerencia asociada al control y si es necesario muestra la sugerencia correspondiente a la
propiedad AutoPopDelay.
Para poder funcionar, el control ToolTip debe asociar una cadena de caracteres a cada uno
de los controles de la interfaz. Para hacerlo, cuando un control ToolTip está disponible en
ShareVideos
una ventana, se agrega una propiedad ToolTip a cada control, permitiendo así especificar el
texto de la sugerencia asociada al control.
Las cadenas de caracteres asociadas a cada control pueden indicarse con el código,
llamando el método SetToolTip e indicando como parámetros el nombre del control y la
cadena de caracteres a él asociada.
Esta técnica permite conservar leyendas relativamente breves para los controles, pero que a
la vez proporcionan la información suficiente sobre la utilización de la aplicación.
e. El control ErrorProvider
Este control permite indicar fácilmente al usuario los problemas relativos a los datos elegidos en
un formulario. En general, interviene en la fase de validación de los datos del formulario,
mostrando frente a cada control un pequeño icono para llamar la atención de este. Se puede
proporcionar información adicional con un mensaje asociado al control ErrorProvider.
Un mismo control ErrorProvider se puede utilizar para todos los controles de un formulario.
f. El control NotifyIcon
ShareVideos
del sistema operativo. La propiedad Icon del control determina el icono mostrado. La
propiedad Text representa la leyenda mostrada cuando el ratón pasa por encima del control.
Gestionando el evento DoubleClick del control, puede mostrar un cuadro de diálogo que
permita la configuración del proceso asociado al control.
g. El control HelpProvider
HelpKeyword
HelpNavigator
HelpString
ShareVideos
El siguiente ejemplo asocia al botón de comando CmdOk el menú de ayuda Visión de
conjunto de la tabla de caracteres del archivo charmap.chm y configura el sistema de
ayuda, para que este menú se muestre automáticamente cuando se utiliza la tecla [F1].
h. El control ProgressBar
Este control se utiliza para informar al usuario acerca del progreso de una acción lanzada en
la aplicación. Muestra esta información en forma de una zona rectangular, que se llenará
más o menos en función del estado de progreso de la acción ejecutada. Se controla el
aspecto de la ProgressBar con su propiedad Style. Existen tres valores:
Continuous
Blocks
Marquee
Modificar directamente la propiedad Value del control. Hay que notar, que en ese
caso, si el valor de esta propiedad supera los extremos, se activa una excepción.
Utilizar el método PerformStep, que aumenta a cada llamada la propiedad Value
con el valor contenido en la propiedad Step. El control verifica, en este caso, el
valor contenido en la propiedad Value y se asegura de que no supere los extremos.
Utilizar el método Increment indicando como parámetro el valor utilizado como
incremento para la propiedad Value. El valor de la propiedad Value se verifica
también durante la ejecución de este método.
Si la ProgressBar tiene el estilo Marquee, la propiedad Value no tiene ningún efecto en las
dimensiones de la barra de progreso y no conviene utilizar los métodos PerformStep e
Increment porque se genera una excepción.
ShareVideos
El ejemplo siguiente presenta un original reloj en el que la hora se muestra a través de tres
ProgressBar:
El control TextBox se utiliza para permitir al usuario introducir datos. Se puede configurar
el control para insertar texto en una o varias líneas. El tamaño máximo del texto varía de
2.000 a 32.000 caracteres, según la configuración del control (línea simple o líneas
múltiples). El control también es capaz de gestionar la selección de texto y las operaciones
con el portapapeles. Para trabajar con este control, hay disponibles muchas propiedades y
métodos. El texto mostrado en el control puede ser modificado o recuperado mediante la
propiedad Text. Es posible modificar el formato de visualización del texto mediante
distintas propiedades. La propiedad Autosize permite pedirle al control TextBox que
cambie su tamaño en función de las dimensiones de la fuente de caracteres. Esta propiedad
se sitúa casi siempre en True. La propiedad CharacterCasing autoriza a control para que
modifique todos los caracteres elegidos, tanto las minúsculas como las mayúsculas.
La propiedad Lines permite recuperar el texto introducido, línea a línea. Esta propiedad es
una matriz de cadenas de caracteres que contiene tantas casillas como líneas. Esta
propiedad solo tiene interés si el control está configurado para aceptar la introducción de
ShareVideos
datos en varias líneas con la propiedad Multiline en posición True. En este caso, también
hay que prever la posibilidad de poder desplazar el texto añadiendo barras de
desplazamiento con la propiedad ScrollBars. Las distintas posibilidades permitirán tener
una barra de deslizamiento horizontal, vertical o ambas. Cuidado, sin embargo, ya que la
barra de desplazamiento vertical solo será visible si la propiedad WordWrap está en False.
En caso contrario, el control gestiona por sí mismo el salto de línea cuando la longitud de la
línea supera la anchura del control. En este caso, los retornos de carro añadidos
automáticamente no se insertan en el texto.
En este ejemplo, la propiedad Lines contendrá dos elementos, porque el primer retorno de
carro se agrega simplemente con el control para su visualización.
La longitud máxima del texto del control se fija con la propiedad MaxLength. Hay que
tener en cuenta que, en el caso de un control de líneas múltiples, los caracteres de retorno
de carro y de salto de línea también cuentan. Se suele utilizan esta propiedad cuando se
hace uso del control TextBox para introducir una contraseña. En este caso, la propiedad
PasswordChar indica el carácter utilizado durante la visualización para ocultar la inserción
del usuario. Se suele utilizar el carácter * o #. Esta propiedad solo influye en la
visualización y los caracteres elegidos por el usuario se recuperan siempre en la propiedad
Text.
La sustitución de una porción de texto en el control TextBox se ejecuta en dos etapas. Ante
todo, hay que seleccionar el texto que se desea sustituir utilizando las propiedades
SelectionStart y SelectionLength; luego hay que indicar el texto sustitutivo con la
propiedad SelectedText. El texto sustituido y el de sustitución no tienen por qué tener el
mismo tamaño.
TextBox1.SelectionStart = 28
TextBox1.SelectionLength = 11
ShareVideos
TextBox1.SelectedText = "Mediterráneo"
También la selección de texto puede efectuarse con el método Select, indicando el carácter
de inicio de la selección y el número de caracteres de la selección.
TextBox1.Select(28,11)
TextBox1.SelectedText = "Mediterráneo"
La selección de la totalidad del texto se puede efectuar con el método SelectAll. Por
ejemplo, se puede forzar la selección de todo el texto cuando el control recibe el foco.
Para la gestión del portapapeles, el control TextBox dispone de un menú contextual que
permite realizar las operaciones habituales. Sin embargo, existe la posibilidad de llamar los
métodos Copy, Cut y Paste para gestionar las operaciones de copiar-pegar de otra manera,
por ejemplo un menú de la aplicación. Las operaciones cortar y pegar no serán posibles si
el control TextBox está configurado en solo lectura con la propiedad ReadOnly en True; la
modificación del texto por el usuario es imposible en este caso.
Como todo el mundo se puede equivocar, el control TextBox nos propone el método Undo,
que permite cancelar la última modificación de texto efectuada en el control. Este método
ya se puede utilizar con la opción cancelar del menú contextual del control TextBox o por
el atajo de teclado [Ctrl] Z. También se la puede llamar gracias a otro menú de su
aplicación. Solo existe un nivel de «Undo», ¡no podrá volver al texto que escribió hace dos
horas!
En este control también está disponible el evento TextChanged, que se produce cuando la
propiedad Text del control se ha modificado (con el código de la aplicación o porque lo
hace el usuario). No se debe modificar la propiedad Text de su control en el código de este
evento, so pena de generar un desbordamiento de pila en la ejecución de la aplicación,
como en el ejemplo siguiente.
ShareVideos
End Sub
b. El control MaskedTextBox
Este control es una mejora del control TextBox, porque permite verificar automáticamente
que la información elegida se corresponda con lo que la aplicación espera. La propiedad
Mask determina el formato de los datos que se pueden introducir en el control. El editor,
accesible desde la ventana de propiedades, permite elegir una máscara existente o
configurar su propia máscara.
La siguiente máscara puede utilizarse, por ejemplo, para la introducción de una dirección
IP :
ShareVideos
000\.000\.000\.000
c. El control RichTextBox
Los métodos LoadFile y SaveFile permiten la carga y el registro desde o hacia un archivo.
El único parámetro obligatorio para estas dos funciones representa la ruta de acceso
completa hacia el archivo que desea cargar o guardar. El formato de archivo utilizado por
defecto para estas dos funciones es el formato rtf (Rich Text Format). Si fuera necesario
utilizar otros formatos de archivo, deberemos especificarlo con un segundo parámetro que
es una constante de la enumeración RichTextBoxStreamType. En el caso de una lectura de
archivo, es importante que los datos contenidos en el archivo concuerden con la constante
utilizada.
Herencia de formularios
Quizá necesite alguna vez que un proyecto invoque a un formulario similar a otro que ya ha
creado para otro proyecto. También puede crear un formulario de base que contenga
parámetros como un fondo estático o una presentación particular de los controles que
piensa utilizar varias veces en un proyecto. Cada nueva versión del formulario contendrá
modificaciones respecto del modelo original. La herencia de formularios nos permite crear
un formulario base y heredar de él para personalizar las nuevas versiones así creadas.
ShareVideos
La propiedad Modifiers de cada control del formulario base determina las acciones posibles
de estos en el formulario heredado. Se aplican las reglas estándar de herencia, que se
resumen a continuación:
Por supuesto, se pueden agregar otros controles al formulario heredado para personalizar su
aspecto. Si se modifica el formulario base después de su utilización en una relación de
herencia, las modificaciones se propagarán a los formularios heredados durante la
compilación del formulario base.
Herencia de formularios
Quizá necesite alguna vez que un proyecto invoque a un formulario similar a otro que ya ha
creado para otro proyecto. También puede crear un formulario de base que contenga
parámetros como un fondo estático o una presentación particular de los controles que
piensa utilizar varias veces en un proyecto. Cada nueva versión del formulario contendrá
modificaciones respecto del modelo original. La herencia de formularios nos permite crear
un formulario base y heredar de él para personalizar las nuevas versiones así creadas.
ShareVideos
haga clic en el botón Examinar, seleccione el archivo (.exe o .dll) que contenga el
formulario base de su elección y confirme con el botón Aceptar. De esta forma, el nuevo
formulario será agregado a su proyecto. En este formulario, los controles procedentes de la
herencia están marcados con el símbolo .
La propiedad Modifiers de cada control del formulario base determina las acciones posibles
de estos en el formulario heredado. Se aplican las reglas estándar de herencia, que se
resumen a continuación:
Por supuesto, se pueden agregar otros controles al formulario heredado para personalizar su
aspecto. Si se modifica el formulario base después de su utilización en una relación de
herencia, las modificaciones se propagarán a los formularios heredados durante la
compilación del formulario base.
ShareVideos
1. Terminología
Una base de datos relacional es un tipo de base de datos que utiliza matrices para almacenar
información. Utiliza valores procedentes de dos matrices para asociar los datos de una tabla
con los de la otra. En general, en una base de datos relacional, los datos se almacenar una
sola vez.
Tabla
Una tabla es un componente de una base de datos que almacena los datos en registros (filas)
y campos (columnas). Los datos se agrupan, en general, en tablas en función de su
categoría. Por ejemplo, tenemos la tabla de Clientes, de Productos o de Pedidos.
Registro
El registro es el conjunto de datos relativos a un elemento de una tabla. A nivel lógico, los
registros son equivalentes a las filas de una tabla. Por ejemplo, un registro de la tabla
Clientes contiene las características de un cliente particular.
Campo
Clave primaria
Se utiliza una clave primaria para identificar de manera única cada fila de una tabla. La
clave primaria es un campo o una combinación de campos cuyo valor es único en la tabla.
Por ejemplo, el campo CodigoCliente es la clave primaria de la tabla Cliente. No puede
haber dos clientes con el mismo código.
Clave externa
Una clave externa representa uno o varios campos de una tabla que hacen referencia a los
campos de la clave primaria de otra tabla. Las claves externas indican la manera en que se
relacionan las matrices.
Relación
Una relación es una asociación establecida entre campos comunes en dos matrices. Una
relación puede ser de uno a uno, de uno a varios o de varios a varios. Gracias a las
ShareVideos
relaciones, los resultados de las consultas pueden contener datos procedentes de varias
matrices. Una relación de uno a varios entre la tabla Cliente y la tabla Pedido permite que
una consulta devuelva todos los pedidos correspondientes a un cliente.
2. El lenguaje SQL
Antes de poder escribir una aplicación en Visual Basic utilizando datos, debe conocer el
lenguaje SQL (Structured Query Language). Este lenguaje permite dialogar con la base de
datos. Existen diferentes versiones del lenguaje SQL según la base de datos utilizada. Sin
embargo, SQL también dispone de una sintaxis elemental, normalizada, independiente de
cualquier base de datos.
a. Búsqueda de datos
El lenguaje SQL permite especificar los registros que se han de extraer, así como el orden
en el que desea extraerlos. Puede crear una instrucción SQL que extrae información de
varias matrices simultáneamente, o crear una instrucción que extrae únicamente un registro
específico.
La siguiente instrucción devuelve la lista de los apellidos y nombres de todos los registros
de la tabla Cliente:
Puede utilizar el símbolo * en lugar de la lista de los campos cuyo valor desea recuperar:
Puede limitar el número de registros seleccionados utilizando uno o varios campos para
filtrar el resultado de la consulta. Hay diferentes cláusulas disponibles para ejecutar este
filtro.
Cláusula WHERE
Esta cláusula permite especificar la lista de las condiciones que deberán cumplir los
registros para formar parte de los resultados devueltos. El siguiente ejemplo permite
encontrar todos los clientes que viven en Barcelona:
ShareVideos
Clause WHERE ... IN
Puede utilizar la cláusula WHERE ... IN para devolver todos los registros que cumplen con
una lista de criterios. Por ejemplo, puede buscar todos los clientes que viven en Francia o
en España:
También puede devolver una selección de registros que se sitúan entre dos criterios
especificados. La siguiente consulta permite recuperar la lista de los pedidos pasados en el
mes de noviembre de 2005:
Puede utilizar la cláusula WHERE ... LIKE para devolver todos los registros en los que
existe una condición particular para un campo dado. Por ejemplo, la siguiente sintaxis
selecciona todos los clientes cuyo apellido empieza con una d:
Puede utilizar la cláusula ORDER BY para devolver los registros en un orden particular. La
opción ASC indica un orden creciente, la opción DESC indica un orden decreciente. Se
pueden especificar varios campos como criterio de ordenación. Se analizan de izquierda a
derecha. En caso de igualdad en el valor de un campo, se utiliza el siguiente campo:
Esta instrucción devuelve los clientes organizados por orden decreciente según el apellido
y, en caso de igualdad, por orden creciente según el nombre.
b. Inserción de datos
La creación de registros en una tabla se efectúa con el comando INSERT INTO. Hay que
indicar la tabla en la que desea insertar una fila, la lista de los campos para los cuales usted
especifica un valor y, finalmente, la lista de los valores correspondientes. Por lo tanto, la
sintaxis completa es la siguiente:
ShareVideos
INSERT INTO cliente (codigoCliente,nombre,apellido) VALUES (1000,
’Pedro’, ’García’)
Al insertar este nuevo cliente, solo el apellido y el nombre aparecen en la tabla. Los otros
campos tomarán el valor NULL. Si la lista de campos no está indicada, la instrucción
INSERT exige que se especifique un valor para cada campo de la tabla. Por tanto, está
obligado a utilizar la palabra clave NULL para indicar que, para un campo determinado, no
existen datos. Si la tabla Cliente está compuesta por cinco campos (codigoCliente, apellido,
nombre, dirección, país), la instrucción anterior se puede escribir con la siguiente sintaxis:
En este caso, las dos palabras clave NULL son obligatorias para los campos dirección y
país.
c. Actualización de datos
d. Eliminación de datos
La instrucción DELETE FROM permite eliminar uno o varios registros de una tabla. Como
mínimo, se debe facilitar el nombre de la tabla en la que se va a efectuar la eliminación. Si
no se indica nada más, todas las filas de la tabla serán eliminadas. En general, una cláusula
WHERE se añade para limitar la extensión de la eliminación. El siguiente comando borra
todos los registros de la tabla Cliente:
ShareVideos
DELETE FROM Cliente
Por supuesto, el lenguaje SQL es mucho más completo que lo que acabamos de ver y no se
puede limitar a estas cinco instrucciones. Sin embargo, estas son suficientes para la
manipulación de los datos a partir de Visual Basic. Si desea profundizar en el aprendizaje
del lenguaje SQL, consulte uno de los libros disponibles en esta colección que trate este
tema más detalladamente.
Presentación de ADO.NET
ADO.NET es un conjunto de clases, interfaces, estructuras y enumeraciones que permiten
la manipulación de los datos. Los diferentes componentes de ADO.NET permiten separar el
acceso a los datos de la manipulación de los datos. ADO.NET facilita también la utilización
del lenguaje XML, al permitir la conversión al formato XML de datos relacionales o la
importación de datos en formato XML en un modelo relacional. Hay dos modos de
funcionamiento disponibles en ADO.NET:
El modo conectado.
El modo no conectado.
1. Modo conectado
ShareVideos
Sin embargo, en ciertas situaciones, la utilización de un modo conectado es ineludible. Es
el caso, por ejemplo, de las aplicaciones que efectúan tratamientos en tiempo real.
2. Modo no conectado
Se utilizan las conexiones durante el tiempo más corto posible. De esta manera, un
pequeño número de conexiones disponibles en un servidor son suficientes para
muchos usuarios.
Un entorno desconectado mejora la escalabilidad y las prestaciones de una
aplicación al optimizar la disponibilidad de las conexiones.
3. Arquitectura de ADO.NET
ShareVideos
posibilidades son limitadas, ya que solo está disponible un acceso en modo de solo
lectura.
Las clases de manipulación de datos, independientes del tipo de base de datos,
utilizables incluso sin base de datos, permiten la manipulación local de los datos en
la aplicación.
Los proveedores de datos sirven de pasarela entre una aplicación y una base de datos. Se
utilizan para recuperar la información a partir de la base de datos, y transferir los cambios
efectuados en los datos por la aplicación hacia la base de datos. Hay cuatro proveedores de
datos disponibles en el Framework .NET:
Algunas clases están disponibles para, por ejemplo, la gestión de las transacciones o el paso
de parámetros a una instrucción SQL.
a. SQL Server
El proveedor de datos para SQL Server utiliza un protocolo nativo para dialogar con el
servidor de base de datos. Además, consume pocos recursos porque accede al servidor sin
utilizar capa lógicas adicionales como OLE DB u ODBC. Se puede utilizar con SQL Server
a partir de la versión 7. Todas las clases de este proveedor de datos están disponibles en el
espacio de nombres System.Data.SqlClient. En este espacio de nombres, el nombre de
cada clase contiene el prefijo Sql. Así, la clase que permite conectarse a un servidor SQL
Server se llama SqlConnection.
ShareVideos
b. OLE DB
El proveedor OLE DB utiliza la capa lógica OLE DB para comunicarse con el servidor de
base de datos. Puede utilizar este proveedor para dialogar con una base de datos para la que
no existen proveedores específicos, pero para la que está disponible el controlador OLE
DB. Con esta solución, el proveedor no contacta con el servidor directamente, sino que
pasa por el controlador OLE DB para comunicarse. Para que esta comunicación sea
posible, el controlador debe implementar algunas interfaces. Todas las clases están
disponibles en el espacio de nombres System.Data.OleDb. Los nombres de clase de este
espacio de nombres están precedidos por OleDb. Para poder funcionar correctamente, este
proveedor exige la instalación de MDAC 2.6 en la máquina (Microsoft Data Access
Components).
c. ODBC
El proveedor ODBC utiliza un controlador ODBC nativo para comunicarse con el servidor
de base de datos. El principio es idéntico al utilizado para el proveedor OLE DB. Todas las
clases están disponibles en el espacio de nombres System.Data.Odbc. Los nombres de
clases vienen precedidos por Odbc. Para poder funcionar correctamente, este proveedor
exige la instalación de MDAC 2.6 en la máquina (Microsoft Data Access Components).
d. Oracle
El proveedor Oracle permite la conexión a una fuente de datos Oracle, a través de las
herramientas cliente de Oracle. Estas herramientas deben instalarse en el sistema operativo
para poderse conectar a una base de datos Oracle. Es necesaria la versión 8.1.7 o una
superior. Las clases están en el espacio de nombres System.Data.OracleClient y utilizan
Oracle como prefijo de nombre. Para utilizar el proveedor para Oracle, deberá también
agregar una referencia hacia la biblioteca System.Data.OracleClient.dll.
Para asegurar el buen funcionamiento de una aplicación que utiliza un acceso a los datos,
los proveedores de datos deben estar disponibles en el puesto cliente. La clase
DbProviderFactories propone el método compartido GetFactoryClasses, que permite
enumerar los proveedores de datos disponibles en el cliente. El ejemplo siguiente de código
muestra el nombre, la descripción y el espacio de nombres raíz de cada proveedor instalado
en el equipo de trabajo.
Imports System.Data
Imports System.Data.Common
Module ListaProviders
Sub Main()
Dim resultado As DataTable
’recuperación de la lista de proveedores en un dataTable
resultado = DbProviderFactories.GetFactoryClasses()
Dim columna As DataColumn
Dim fila As DataRow
ShareVideos
’recorre las columnas del DataTable y muestra el nombre
For Each columna In resultado.Columns
Console.Write(columna.ColumnName & vbTab)
Next
Console.WriteLine()
’ recorre el DataTable y muestra cada fila
For Each fila In resultado.Rows
’ recorre cada fila y muestra cada campo
For Each columna In resultado.Columns
Console.Write(fila(columna.ColumnName) & vbTab)
Next
Console.WriteLine()
Next
Console.ReadLine()
Stop
End Sub
End Module
Module accesoBdPorInterfaces
Dim ctn As IDbConnection
Public Sub main()
’ es la única fila de código específica para un proveedor
ctn = New System.Data.SqlClient.SqlConnection("Data
Source=TG;Initial
Catalog=Northwind;Integrated Security=True")
Dim cmd As IDbCommand
cmd = ctn.CreateCommand
ctn.Open()
cmd.CommandText = "select * from products"
Dim lector As IDataReader
lector = cmd.ExecuteReader
Console.WriteLine("Lectura de datos en una base de datos SQL
Server")
Do While lector.Read
Console.WriteLine("número: {0} nombre producto: {1}",
lector.GetInt32(0), lector.GetString(1))
Loop
End Sub
End Module
ShareVideos
Lectura de datos en una base de datos SQL Server
número: 56 nombre producto: Gnocchi di nonna Alice
número: 57 nombre producto: Ravioli Angelo
número: 58 nombre producto: Caracoles de Lleida
número: 59 nombre producto: Raclette Courdavault
número: 60 nombre producto: Queso Roncal
número: 61 nombre producto: Sirope de fresa
número: 62 nombre producto: Tarta de azúcar
Si esta aplicación debe migrar después hacia otro tipo de base de datos, solo hay que
cambiar la línea relativa a la conexión. Si ahora los datos están disponibles en una base
Access, la creación de la conexión toma la siguiente forma:
Pero conviene ser prudente y no utilizar instrucciones SQL específicas para un tipo de base
de datos particular. Para facilitar la revisión del código, es preferible agrupar todas las
instrucciones SQL en forma de constantes de tipo cadena de caracteres al principio de cada
módulo. Con esta técnica, no tendrá que buscar instrucciones SQL en medio de centenares
de líneas de código Visual Basic. También conviene ser prudente durante la utilización de
parámetros en una instrucción SQL. El proveedor para SQL Server utiliza parámetros con
nombre; por lo tanto, el orden de creación de los parámetros no tiene importancia.
El proveedor para OLE DB utiliza la posición de los parámetros en la instrucción SQL para
la sustitución a la hora de la ejecución. El orden de la creación de los parámetros es pues,
en este caso, capital para el funcionamiento correcto de la instrucción.
ShareVideos
base de datos utilizada será la base Northwind que se crea por defecto cuando se instala el
servidor. Una parte de la estructura de la base está disponible en el esquema siguiente:
Para poder trabajar con un servidor de base de datos, una aplicación debe establecer una
conexión de red con el servidor. La clase SqlConnection es capaz de gestionar una
conexión hacia un servidor SQL Server versión 7.0 o posterior. Como para cualquier
objeto, en primer lugar debemos declarar una variable.
a. Cadena de conexión
El formato estándar de una cadena de conexión está constituido por una serie de pares
palabra clave/valor, separadas por puntos y comas. El signo = se usa para la asignación de
un valor a una palabra clave. El análisis de la cadena se efectúa durante la asignación de la
cadena a la propiedad ConnectionString. Los valores asociados a las palabras clave se
extraen y se asignan a las distintas propiedades de la conexión. Si se encuentra un error de
sintaxis, se genera una excepción inmediatamente y no se modifica ninguna propiedad. Por
el contrario, solo se podrá controlar algunas propiedades durante la apertura de la conexión.
En este momento se activará una excepción si la cadena de conexión contiene un error. solo
se puede modificar la cadena de conexión si la conexión está cerrada. Estas son las palabras
claves existentes para una cadena de conexión:
Connect Timeout
Duración en segundos durante la cual la aplicación esperará una respuesta del servidor a su
petición de conexión. Pasado este plazo, se activa una excepción.
Data Source
Nombre o dirección de red del servidor hacia el que se establece la conexión. El número del
puerto se puede especificar después del nombre o de la dirección de red. Si no está
indicado, el número de puerto es igual a 1433.
Initial Catalog
ShareVideos
Nombre de la base de datos en la que se debe efectuar la conexión.
Integrated Security
Si este valor se coloca en false, se debe facilitar un nombre de usuario y una contraseña en
la cadena de conexión. En caso contrario, se utiliza la cuenta Windows del usuario para la
autenticación.
Si se posiciona este valor en true, el nombre del usuario y su contraseña son accesibles por
la conexión. Por razones de seguridad, se debe colocar este valor en false. De hecho, es así
si no indica nada en la cadena de conexión.
Pwd
User ID
Connection LifeTime
Indica la duración de una conexión en un pool de conexiones. Un valor igual a cero indica
una duración ilimitada.
Connection Reset
Pooling
ShareVideos
ctn.ConnectionString = "Data Source=Minerve;Initial Catalog=Northwind;
Integrated
Security=true"
b. Pool de conexiones
Los pools de conexiones permiten mejorar las prestaciones de una aplicación al evitar la
creación de conexiones adicionales. Cuando una conexión está abierta, se crea un pool de
conexiones que se basa en un algoritmo basado, a su vez, en la cadena de conexión. Así
cada pool está asociado a una cadena de conexión particular. Si se abre una nueva conexión
y no hay pool que corresponda exactamente a su cadena de conexión, se crea un nuevo
pool. Los pools de conexiones así creados existirán hasta el final de la aplicación. Cuando
se crea un pool, se pueden crear otras conexiones automáticamente para satisfacer el valor
Min Pool Size indicado en la cadena de conexión. Se podrán añadir otras conexiones al
pool hasta alcanzar el valor Max Pool Size de la cadena de conexión. Cuando se requiere
una conexión, se puede obtener a partir de un pool de conexiones (si existe uno que
corresponde exactamente a las características de la conexión requerida). Por supuesto, es
necesario que el pool contenga una disponible y activa.
c. Eventos de conexión
La clase SQLConnection propone dos eventos que le permiten ser avisado cuando el estado
de la conexión cambia o cuando el servidor envía un mensaje de información. El evento
StateChanged se activa cuando cambia el estado de la conexión. El gestor de este evento
recibe un parámetro de tipo StateChangeEventArg, que permite obtener con la propiedad
CurrentState el estado actual de la conexión, y con la propiedad OriginalState, el estado de
la conexión antes de la desactivación del evento. Para probar el valor de estas dos
propiedades, puede utilizar la enumeración ConnectionState.
ShareVideos
Private Sub ctn_InfoMessage(ByVal sender As Object, ByVal e As
System.Data.
SqlClient.SqlInfoMessageEventArgs) Handles ctn.InfoMessage
Dim info As SqlClient.SqlError
For Each info In e.Errors
Console.WriteLine(info.Message)
Next
End Sub
2. Ejecución de un comando
Después de haber establecido una conexión hacia un servidor de base de datos, puede
transmitirle instrucciones SQL. Se utiliza la clase SqlCommand para pedir al servidor la
ejecución de un comando SQL. Esta clase contiene varios métodos que permiten la
ejecución de diferentes tipos de consultas SQL. La clase SqlCommand puede instanciarse
de manera clásica, utilizando uno de sus constructores, o se puede obtener una instancia por
el método CreateCommand de la conexión.
a. Creación de un comando
La primera posibilidad para crear una instancia de SqlCommand consiste en utilizar uno de
los constructores de la clase. El uso del constructor por defecto le obliga a utilizar
diferentes propiedades para facilitar la información relativa a la instrucción SQL que se va
a ejecutar.
ShareVideos
b. Lectura de datos
El caso de las instrucciones que devuelven varios registros es un poco más complejo.
Después de haber ejecutado la instrucción con el método ExecuteReader y de haber
recuperado el objeto DataReader, puede utilizar este último para recorrer los resultados
devueltos. El método Read de la clase DataReader permite el desplazamiento por el
conjunto de los registros devueltos. Este método devuelve un booleano que indica si queda
otro registro. El desplazamiento solo es posible desde el primero hasta el último registro.
Este tipo de desplazamiento se llama Forward Only. La información contenida en el
registro actual es accesible con uno de los métodos Get... de la clase DataReader. Estos
métodos permiten extraer los datos del registro y convertirlos en un tipo de datos .NET.
Existe una versión para cada tipo de datos del Framework .NET. Por supuesto, hace falta
que la información presente en el registro se pueda convertir en el tipo correspondiente. Si
la conversión es imposible, se activa una excepción. Los métodos Get... esperan, como
parámetro, el número del campo en el que deben recuperar la información. También puede
utilizar la propiedad por defecto Item del DataReader, indicando el nombre del campo. En
este caso, no hay conversión y el valor devuelto es de tipo Object.
Imports System.Data.SqlClient
Module TestExecuteReader
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader
ShareVideos
Do While lector.Read
Console.WriteLine("número de la categoría:{0}" & vbTab &
"Descripción:{1}", lector.GetInt32(0), lector("CategoryName"))
Loop
lector.Close()
ctn.Close()
End Sub
End Module
La modificación de los datos en una base de datos se efectúa principalmente con las
instrucciones SQL INSERT, UPDATE, DELETE. Estas instrucciones no devuelven
registros procedentes de la base de datos. Para utilizar estas instrucciones, debe crear un
SqlCommand, y luego pedir la ejecución de este comando través del método
ExecuteNonQuery. Este método devuelve el número de registros afectados por la ejecución
de la instrucción SQL contenida en el SqlCommand. Si la propiedad CommandText
contiene varias instrucciones SQL, el valor devuelto por el método ExecuteNonQuery
corresponde al número total de filas afectadas por todas las instrucciones SQL del
SqlCommand.
Imports System.Data.SqlClient
Module TestExecuteNonQuery
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Public Sub main()
ctn = New SqlClient.SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlClient.SqlCommand
cmd.Connection = ctn
cmd.CommandText = "Insert into shippers (companyname,phone)
values
(’DHL’,’91 123 56 87 43’)"
Console.WriteLine("{0} fila(s) añadidas(s) en la tabla",
cmd.ExecuteNonQuery)
ctn.Close()
End Sub
End Module
d. Utilización de parámetros
ShareVideos
El principio de funcionamiento es parecido a los procedimientos y funciones de Visual
Basic. Una alternativa a la utilización de parámetros podría ser la construcción dinámica de
instrucciones SQL por concatenación de cadenas de caracteres.
A continuación, un ejemplo que utiliza esta técnica y que permite la búsqueda de un cliente
por su código (luego veremos cómo mejorar este código al utilizar parámetros):
Imports System.Data.SqlClient
Module TestBuscarConcat
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader
Dim codCliente As String
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
Console.Write("introducir el código del cliente buscado:")
codCliente = Console.ReadLine()
cmd.CommandText = " SELECT * from Customers WHERE CustomerID =
’"
& codCliente & "’"
lector = cmd.ExecuteReader
Do While lector.Read
Console.WriteLine("nombre del cliente:{0}",
lector("ContactName"))
Loop
lector.Close()
ctn.Close()
Console.ReadLine()
End Sub
End Module
Olvidarse de un espacio.
Olvidarse de los caracteres " para enmarcar un valor del tipo cadena de caracteres.
Un número de carácter ’ impar.
Todos estos errores tienen el mismo efecto: la creación de una instrucción SQL inválida
que será rechazada durante la ejecución por el servidor.
ShareVideos
estará colocado, en el momento de la ejecución, un valor literal cadena de caracteres o
numérico. Los parámetros pueden ser nominales o anónimos. Un parámetro anónimo se
introduce en una consulta con el carácter ?. Los parámetros nominales se especifican con el
carácter @ seguido por el nombre del parámetro.
El SqlCommand debe tener una lista de valores utilizados para reemplazar los parámetros
en el momento de la ejecución. Esta lista se almacena en la colección Parameters del
SqlCommand. Antes de la ejecución del SqlCommand, es necesario crear los objetos
SqlParameter y añadirlos a la colección. Para cada SqlParameter, hay que proporcionar:
ShareVideos
de valor esperado por la instrucción SQL para saber si debemos enmarcarlo con caracteres
’. Si se utilizan parámetros en la salida de la instrucción SQL, solo estarán disponibles
después del cierre del DataReader. El siguiente ejemplo muestra, además del nombre del
cliente, el número de pedidos ya pasados:
Imports System.Data.SqlClient
Module TestBuscarConcat
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader
Dim codCliente As String
Dim paramCodCliente As SqlParameter
Dim paramNbComandos As SqlParameter
Los procedimientos almacenados son elementos de una base de datos que corresponden a
un conjunto de instrucciones SQL que pueden ser ejecutadas con una simple llamada a su
nombre. Son verdaderos programas SQL que pueden recibir parámetros y devolver valores.
Además, los procedimientos almacenados son registrados en el caché del servidor, con la
forma compilada, durante su primera ejecución, lo que aumenta sus prestaciones para las
siguientes ejecuciones. Otra ventaja de los procedimientos almacenados es centralizar en el
servidor de base de datos todos los códigos SQL de una aplicación. Si se deben aportar
ShareVideos
modificaciones en las instrucciones SQL, solo tendrá que hacerlo en el servidor sin que sea
preciso retomar el código de la aplicación, es decir, sin tener que volver a generar y
desplegar la aplicación.
A nivel del código Visual Basic, debemos indicar que se trata de la ejecución de un
procedimiento almacenado y agregar un parámetro para recuperar el valor de retorno de
dicho procedimiento. Este parámetro debe llamarse RETURN_VALUE.
Imports System.Data.SqlClient
Module TestProcedimientoAlmacenado
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim paramCodCliente As SqlParameter
Dim paramCantidad As SqlParameter
Dim codCliente As String
ShareVideos
paramCantidad.Direction = ParameterDirection.ReturnValue
cmd.Parameters.Add(paramCantidad)
cmd.ExecuteNonQuery()
Console.WriteLine("Este cliente ha pasado {0} euros de pedido",
paramCantidad.Value)
Console.ReadLine()
ctn.Close()
End Sub
End Module
DataSet
DataTable
DataRow
DataColumn
UniqueConstraint
ForeignKeyConstraint
DataRelation
ShareVideos
Ahora vamos a ver cómo crear y manipular todas estas clases.
Para poder trabajar localmente con los datos, debemos traerlos desde la base de datos a un
DataSet. Cada proveedor de datos facilita una clase DataAdapter, que asegura el diálogo
entre la base de datos y un DataSet. Todos los intercambios se hacen por medio de esta
clase, tanto desde la base de datos hacia el DataSet como del DataSet hacia la base de datos
para la actualización de los datos. El DataAdapter utilizará una conexión para contactar con
el servidor y uno o varios comandos para el tratamiento de los datos.
a. Utilización de un DataAdapter
Lo primero que hay que hacer es crear una instancia de la clase SQLDataAdapter. Luego
debemos configurar el DataAdapter con el fin de indicarle qué datos deseamos traer de la
base de datos. La propiedad SelectCommand debe referenciar un objeto Command, que
contiene la instrucción SQL encargada de seleccionar los datos. El objeto Command
utilizado también puede llamar a un procedimiento almacenado. La única restricción es que
la instrucción SQL ejecutada por el objeto Command sea una instrucción SELECT. La
clase DataAdapter también contiene las propiedades InsertCommand, DeleteCommand y
UpdateCommand, que hacen referencia a los objetos Command, utilizados durante la
actualización de la base de datos. Si no deseamos efectuar la actualización de la base, estas
propiedades son optativas. Las veremos más en detalle en el capítulo dedicado a la
actualización de la base de datos.
El método Fill de la clase DataAdapter se utiliza luego para rellenar el DataSet con el
resultado de la ejecución del comando SelectCommand. Este método espera como
parámetros el DataSet que debe rellenar y un objeto DataTable o una cadena de caracteres
utilizada para nombrar el DataTable en el DataSet. El DataAdapter utiliza, internamente, un
objeto DataReader para obtener el nombre y el tipo de los campos para crear el DataTable
en el Dataset y después rellenarlo con los datos. El DataTable y los DataColumn se crean
solo si no existen. En caso contrario, el método Fill utiliza la estructura existente. Si se crea
un DataTable, se añade a la colección Tables del DataSet. El tipo de datos de los
DataColumn se define en función de los mapeos previstos por el proveedor de datos, entre
los tipos de la base de datos y los tipos .NET. El siguiente ejemplo rellena un DataSet con
el código, apellido, dirección y ciudad de los clientes.
Imports System.Data.SqlClient
Module TestDataSet1
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
ShareVideos
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT CustomerId,ContactName,Address,
city from Customers"
ds = New DataSet
da = New SqlDataAdapter()
da.SelectCommand = cmd
da.Fill(ds, "Customers")
End Sub
End Module
Por supuesto, un DataSet puede contener varios DataTable creados a partir de DataAdapter
diferentes. Los datos pueden venir de bases de datos diferentes o de tipos de servidores
diferentes.
Si, para uno o más campos, no existe mapeo disponible, el nombre del campo en la base de
datos se usa como nombre para el DataColumn correspondiente. Por ejemplo, podemos
utilizar esta técnica para traducir los campos de la base Northwind.
Imports System.Data.SqlClient
Imports System.Data.Common
Module TestTableMapping
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim mapeo As DataTableMapping
Dim dc As DataColumn
ShareVideos
Catalog=Northwind; Integrated Security=true"
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT CustomerId,ContactName,Address,
city from Customers"
ds = New DataSet
da = New SqlDataAdapter()
da.SelectCommand = cmd
mapeo = New DataTableMapping("Customers", "Clientes")
mapeo.ColumnMappings.Add("CustomerId", "CodCliente")
mapeo.ColumnMappings.Add("ContactName", "Nombre")
mapeo.ColumnMappings.Add("Address", "Direccion")
mapeo.ColumnMappings.Add("city", "Ciudad")
da.TableMappings.Add(mapeo)
da.Fill(ds, "Customers")
For Each dc In ds.Tables("Clientes").Columns
Console.Write(dc.ColumnName & vbTab)
Next
Console.ReadLine()
End Sub
End Module
Obtenemos el resultado:
El método Fill transfiere hacia el DataSet los datos que proceden de la base. A menudo se
utilizan las restricciones de la clave principal en la base de datos y, por defecto, el método
Fill no las transfiere al DataSet. Para poder recuperar estas restricciones en el DataSet, hay
dos soluciones posibles:
da.MissingSchemaAction = MissingSchemaAction.AddWithKey
El segundo parámetro del método FillSchema indica si se debe tener en cuenta el mapeo o
si se utiliza la información procedente de la base.
ShareVideos
Si existen a nivel del DataSet, cuando el método Fill importa un registro desde la base de
datos, verifica si ya no existe una fila con el valor de clave primaria en el DataTable. Si es
el caso, solo actualiza los campos de la fila existente. Si, por el contrario, no hay una fila
con un valor de clave primaria idéntico, entonces se crea la fila en el DataTable.
Si no hay restricción de clave primaria en el DataTable, el método Fill añade todos los
registros procedentes de la base. En este caso, puede que haya duplicados en el DataTable.
Eso es particularmente importante cuando se debe llamar al método Fill varias veces para,
por ejemplo, obtener los datos modificados por otra persona en la base de datos.
No es necesario disponer de una base de datos para poder utilizar los DataSet. Pueden
servir como alternativa a la utilización de matrices para la gestión interna de los datos de
una aplicación. En este caso, todas las operaciones efectuadas automáticamente con el
DataAdapter deberán realizarse manualmente con el código. Esto incluye, en particular, la
creación de los DataTable con sus DataColumn. La primera operación que se debe realizar
consiste en crear una instancia de la clase DataTable. El constructor espera como parámetro
el nombre de la DataTable. Luego se utiliza este nombre para identificar el DataTable en la
colección Tables del DataSet. Tras su creación, el DataTable no contiene ninguna
estructura. Por tanto, debemos crear uno o varios DataColumn y agregarlos a la colección
Columns del DataTable.
table.Columns.Add("PNeto", Type.GetType("System.Decimal"),
"PBruto * (1 + (IVA /100))")
ShareVideos
contenido en este DataColumn se calcula automáticamente cuando se agrega una fila a un
DataTable en función de estas propiedades y filas ya existentes en el DataTable.
Este tipo de DataColumn se suele utilizar como clave primaria de un DataTable. Tiene la
posibilidad de definir la clave primaria de un DataTable al facilitar a la propiedad
PrimaryKey una tabla que contenga los diferentes DataColumn que deben componer la
clave primaria. Algunas propiedades de los DataColumn se modificarán automáticamente.
La propiedad Unique se situará en true y la propiedad AllowDBNull en false. Si la clave
primaria está constituida por varios DataColumn, solo se modificará la propiedad
AllowDBNull en estos DataColumn.
Sea cual sea el método utilizado para rellenar un DataSet, el objetivo de cualquier
aplicación consiste en manipular los datos presentes en el DataSet. La clase DataTable
contiene muchas propiedades y métodos que facilitan la manipulación de los datos.
La lectura de los datos es la operación más frecuente realizada en un DataSet. Primero hay
que obtener una referencia al DataTable que contiene los datos, luego podemos recorrer la
colección Rows del DataTable. Esta colección es una instancia de la clase
DataRowCollection. Por defecto, dispone de la propiedad Item, que permite el acceso a una
fila particular por un índice. La propiedad count permite conocer el número de filas
disponibles. Los que suelen usar ADO se perderán un poco al principio, porque en un
DataTable no existe la noción de puntero de registro, de registro actual, de métodos de
desplazamiento por los resultados. Si desea gestionar todas estas nociones, debe preverlo
explícitamente en su código. El método GetEnumerator pone a su disposición una instancia
de clase que implementa la interfaz IEnumerator. Gracias a esta instancia de clase, tenemos
acceso a los métodos MoveNext y Reset, así como a la propiedad Current. Estos tres
elementos permiten recorrer fácilmente todas las filas DataTable. Cada fila corresponde a
una instancia de la clase DataRow. Esta clase posee también una propiedad Item, por
defecto, que proporciona un acceso a los diferentes campos del DataRow. Se puede obtener
cada campo gracias a su nombre o su índice.
Imports System.Data.SqlClient
Module TestLecturaDataTable
ShareVideos
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim en As IEnumerator
Podemos utilizar limitaciones para poner en marcha restricciones en los datos presentes en
un DataTable. Las restricciones constituyen reglas que se aplican a un DataColumn o a sus
DataColumn relacionadas. Determinan las acciones efectuadas cuando se modifica el valor
contenido en una fila. Solo se tienen en cuenta para un DataSet si su propiedad
EnforceConstraints está en true.
UniqueConstraint
Este tipo de restricción garantiza que el valor o los valores presentes en un DataColumn o
un grupo de DataColumn sean únicos. La activación de una restricción única se efectúa
creando una instancia de la clase UniqueConstraint con la lista de los DataColumn
implicados en la restricción. Luego, esta UniqueConstraint se debe añadir a la colección
Constraints del DataTable.
ShareVideos
Si la restricción solo se refiere a un DataColumn, también es posible modificar
simplemente la propiedad Unique de este DataColumn a true, para crear una restricción de
tipo Unique. Hay que observar también que la creación de una clave primaria genera
automáticamente una restricción de tipo Unique. Lo contrario no es verdad. La violación de
la restricción al modificar una fila genera una excepción.
ForeignKeyConstraint
Cascade
SetNull
SetDefault
None
ShareVideos
c. Agregar relaciones entre los DataTables
En un DataSet que contiene varios DataTable, puede añadir relaciones entre los DataTable.
Estas relaciones permiten la navegación entre las filas de los diferentes DataTable. Se debe
crear una instancia de la clase DataRelation y agregar a la colección Relations del DataSet.
La creación se puede hacer directamente con el método Add de la colección DataRelations.
La información que se debe facilitar es:
El código siguiente añade una relación entre la tabla Customers y la tabla Orders:
ds.Relations.Add("Cliente_Pedidos", ds.Tables("Customers").
Columns ("CustomerId"),
ds.Tables("Orders").Columns("CustomerId"))
Hay que observar que las DataRelation funcionan en paralelo con las ForeignKeyConstaint
y las UniqueConstraint. Por defecto, la creación de la relación colocará una
UniqueConstraint en la tabla padre y una ForeignKeyConstraint en la tabla hijo. Si no desea
que estas restricciones se añadan automáticamente cuando no existen, usted debe agregar
un boleano false como cuarto parámetro al añadir la DataRelation.
Este método toma como parámetro el nombre de la DataRelation utilizada para seguir el
enlace. El siguiente ejemplo de código aplica todo ello, mostrando para cada cliente el
número y la fecha de sus pedidos:
Imports System.Data.SqlClient
Module TestRelaciones
Dim cmdCustomers, cmdOrders As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim daCustomers, daOrders As SqlDataAdapter
Dim filaCliente, filaPedidos As DataRow
ShareVideos
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmdCustomers = New SqlCommand
cmdCustomers.Connection = ctn
cmdCustomers.CommandText = " SELECT * from Customers"
daCustomers = New SqlDataAdapter()
daCustomers.SelectCommand = cmdCustomers
daCustomers.Fill(ds, "Customers")
cmdOrders = New SqlCommand
cmdOrders.Connection = ctn
cmdOrders.CommandText = " SELECT * from Orders"
daOrders = New SqlDataAdapter()
daOrders.SelectCommand = cmdOrders
daOrders.Fill(ds, "Orders")
ds.Relations.Add("Cliente_Pedidos", ds.Tables("Customers").
Columns ("CustomerId"), ds.Tables("Orders").Columns("CustomerId"))
For Each filaCliente In ds.Tables("Customers").Rows
Console.WriteLine(filaCliente("ContactName"))
For Each filaPedidos In
filaCliente.GetChildRows("Cliente_Pedidos")
Console.WriteLine(vbTab & "pedido N {0} del {1}",
filaPedidos ("OrderId"), filaPedidos("OrderDate"))
Next
Next
End Sub
End Module
La navegación de una fila hijo hacia una fila padre también es posible, utilizando el método
GetParentRow, que también espera como parámetro el nombre de la relación utilizada
como enlace.
El fragmento de código siguiente muestra el nombre del cliente que ha pasado cada pedido:
La clase DataRow es capaz de seguir las diferentes modificaciones aportadas a los datos
que contiene. La propiedad RowState permite controlar las modificaciones aportadas a la
fila.
Para esta propiedad existen cinco posibles valores definidos en una enumeración:
Unchanged
La fila no ha cambiado desde el llenado del DataSet con el método Fill o la validación de
las modificaciones con el método AcceptChanges.
ShareVideos
Added
Se ha añadido la fila, pero las modificaciones aún no han sido validadas por el método
AcceptChanges.
Modified
Deleted
Se ha borrado la fila, pero las modificaciones aún no han sido validadas por el método
AcceptChanges.
Detached
Las diferentes versiones de una fila también están disponibles. Cuando acceda a los valores
contenidos en una fila, puede especificar la versión que le interesa.
Current
Versión actual de la fila. Esta versión no existe para una fila cuyo estado es Deleted.
Default
Versión por defecto de la fila. Para una fila cuyo estado es Added, Modified, Unchanged,
es equivalente a la versión Current. Para una fila cuyo estado es Deleted, es equivalente a la
versión Original. Para una fila cuyo estado es Detached, es igual a la versión Proposed.
Original
Versión original de la fila. Para una fila cuyo estado es Added, no existe.
Proposed
Versión transitoria disponible durante una operación de modificación de la fila o para una
fila que no forma parte de la colección Rows de un DataTable.
ShareVideos
Durante la actualización de la base de datos se utilizarán estas distintas versiones para
gestionar los accesos concurrentes por ejemplo.
f. Agregar datos
No hay constructor disponible para la clase DataRow. No es un error de Visual Basic, sino
que simplemente no existe un constructor para esta clase. En efecto, cuando necesitamos
una nueva instancia de un DataRow, no queremos un DataRow cualquiera, sino un
DataRow específico para el esquema de nuestro DataTable. Por esta razón se le confía al
DataTable la tarea de crear la instancia que necesitamos por medio del método NewRow.
El estado de esta fila es, de momento, Detached. Luego podemos añadir datos a esta nueva
fila.
nuevaFila("ContactName") = "Alfonso"
Después, nos queda por añadir la fila de la colección Rows del DataTable.
ds.Tables("Customers").Rows.Add(nuevaFila)
g. Modificación de datos
La modificación de los datos contenidos en una fila se realiza simplemente al asignar a los
campos correspondientes los valores deseados. Estos valores están almacenados en la
versión Current de la fila. El estado de la fila es entonces Modified. Esta solución presenta
un pequeño inconveniente. Si hay que modificar varios campos de una fila, los estados
transitorios pueden violar varias restricciones colocadas en la DataTable. Es el caso, por
ejemplo, si existe en la DataTable una restricción de clave primaria colocada en dos
DataColumn. Esto tiene como efecto activar una excepción. Para paliar este problema,
podemos pedir temporalmente la suspensión de la verificación de las restricciones para esta
fila. El método BeginEdit pasa la fila a modo edición y suspende entonces la verificación
de las restricciones para esta fila. Los valores asignados a los campos no están almacenados
en la versión Current de la fila, sino en la versión Proposed. Cuando todas las
ShareVideos
modificaciones se han efectuado en la fila, las puede validar o cancelar llamando al método
EndEdit o al método CancelEdit.
También puede verificar los valores, gestionando el evento ColumnChanged del DataTable.
En el gestor de eventos, recibirá un argumento del tipo DataColumnChangeEventArg que
permite saber qué DataColumn se ha modificado (args.Column.ColumnName) y el valor
propuesto para este DataColumn (args.ProposedValue) permitiendo anular las
modificaciones (args.row.CancelEdit). En caso de validación con el método EndEdit, la
versión Proposed de la fila se vuelve a copiar en la versión Current y su estado se convierte
en Modified. Si por el contrario cancela las modificaciones con el método CancelEdit, la
versión Current no se modifica y el estado de la fila no cambia. En todos los casos, después
de la llamada de uno de estos dos métodos, se reactiva la verificación de las restricciones.
Imports System.Data.SqlClient
Module TestModificacionFila
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim codCliente As String
Dim codigoPostal As String
Dim paramCodCliente As SqlParameter
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim WithEvents tabla As DataTable
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial Catalog=
Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
Console.Write("escoger el código del cliente:")
codCliente = Console.ReadLine()
cmd.CommandText = " SELECT * from Customers WHERE CustomerID =
@Codigo"
paramcodCliente = New SqlParameter("@Codigo", codCliente)
paramCodigoCliente.Direction = ParameterDirection.Input
cmd.Parameters.Add(paramCodCliente)
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
tabla.Rows(0).BeginEdit()
Console.Write("introducir el nuevo código postal del cliente:")
codigoPostal = Console.ReadLine()
tabla.Rows(0)("PostalCode") = codigoPostal
tabla.Rows(0).EndEdit()
Console.WriteLine("el nuevo código postal es: {0}",
tabla.Rows(0) ("PostalCode"))
Console.ReadLine()
End Sub
ShareVideos
Private Sub table_ColumnChanged(ByVal sender As Object, ByVal e
As System. Data.DataColumnChangeEventArgs) Handles table.ColumnChanged
If e.Column.ColumnName = "PostalCode" Then
If Not IsNumeric(e.ProposedValue) Then
e.Row.CancelEdit()
End If
End If
End Sub
End Module
h. Eliminar datos
Hay dos soluciones disponibles. Puede borrar una fila o eliminarla. El matiz es sutil entre
estas dos soluciones:
La eliminación de una fila se hace con el método Remove, que retira definitivamente el
DataRow de la colección Rows del DataTable. Esta eliminación es definitiva.
El método Deleted solo marca la fila para eliminarla posteriormente. El estado de la fila
pasa a Deleted y solo en el momento de la validación de las modificaciones se eliminar
realmente la fila de la colección Rows del DataTable. Si se cancelan las modificaciones, la
fila se queda en la colección Rows.
’ borra la fila
table.Rows(1).Delete()
’ elimina la fila
table.Rows.Remove(table.Rows(1))
Hasta ahora, las modificaciones efectuadas en una fila son temporales; todavía es posible
volver a la versión anterior o, al contrario, validar de manera definitiva las modificaciones
en las filas (pero no en la base). Los métodos AcceptChanges o RejectChanges permiten
respectivamente la validación o la anulación de las modificaciones. Se pueden aplicar a un
DataRow individual, un DataTable o un DataSet entero. Cuando el método AcceptChanges
se ejecuta, se realizan las siguientes acciones:
ShareVideos
El método CancelEdit es llamado implícitamente para la fila.
Si el estado de la fila era Deleted o Modified, se convierte en Unchanged y la
versión Original se vuelve a copiar en la versión Current.
Si el estado de la fila era Added, se elimina la fila.
El primer constructor utilizable espera como parámetro el DataTable a partir del cual se
genera el DataView. En este caso, no hay ningún filtro ni tampoco ordenación efectuada en
los datos visibles por el DataView. Se obtiene un resultado equivalente al utilizar la
propiedad DefaultView de un DataTable.
RowFilter
Esta propiedad acepta una cadena de caracteres que representa la condición que se debe
cumplir para que una fila sea visible. Esta condición tiene una sintaxis muy parecida a las
condiciones de una cláusula WHERE. Los operadores And y Or pueden utilizarse para
asociar varias condiciones.
ShareVideos
Imports System.Data.SqlClient
Module TestDataView
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRowView
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers"
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
tabla.DefaultView.RowFilter = "Country=’España’ and
(contactTitle=’Sales Agent’ or contactTitle=’Sales Manager’)"
For Each fila In tabla.DefaultView
Console.WriteLine("nombre: {0}", fila("ContactName"))
Next
End Sub
End Module
Sort
Esta propiedad acepta también una cadena de caracteres que representa el criterio o los
criterios utilizados para la ordenación. La sintaxis es equivalente a la de la cláusula
ORDER BY.
El siguiente ejemplo muestra los clientes ordenados por país y, dentro del mismo país, por
nombre:
RowStateFilter
ShareVideos
Esta propiedad determina el estado de las filas y qué versión de la fila es visible en el
DataView. Existen ocho posibilidades:
CurrentRows
Added
Deleted
ModifiedCurrent
ModifiedOriginal
None
Ninguna fila.
OriginalRows
Unchanged
ShareVideos
k. Buscar datos
La búsqueda se puede realizar con los dos métodos Find y FindRows. Para que funcionen,
es obligatorio haber ordenado los datos con la propiedad Sort.
Find
Este método se usa a menudo para buscar una fila a partir de la clave primaria.
Imports System.Data.SqlClient
Module T
Introducción
Después de muchos años de evolución, los lenguajes orientados a objetos se han hecho
ineludibles en el desarrollo informático. De manera paralela, los sistemas de
almacenamiento también han evolucionado sobre dos ejes: las bases de datos y los archivos
XML. La cohabitación entre los objetos y los datos ha sido más o menos mejorada
añadiendo a los lenguajes orientados a objetos la capacidad para dialogar con los datos. Sin
embargo, esta solución no es del todo satisfactoria, ya que presenta las desventajas
siguientes:
El lenguaje utilizado para manipular los datos suele ser muy específico de un tipo de
fuente de datos.
Las palabras claves de este lenguaje son desconocidas para el lenguaje de
programación, que las considera como simples cadenas de caracteres; por tanto, no
hay una verificación sintáctica antes de la ejecución.
El cambio de tipo de fuente de datos conlleva importantes modificaciones del
código y un nuevo periodo de aprendizaje para el desarrollador.
Los tipos de datos a veces son incompatibles entre el lenguaje de programación y la
fuente de datos. En este caso, hacer las conversiones a menudo exige tiempo y, a
veces, se tornan peligrosas.
Con LINQ todo esto se convierte en malos recuerdos. Pero ¿qué se esconde detrás de estas
cuatro letras: Language Integrated Query o lenguaje de consulta integrado? Se trata de un
lenguaje de consulta que permite interrogar fuentes de datos, pero ¿que más ofrece con
respecto al bueno de SQL? La clave del misterio se sitúa en el término «integrado». En
efecto, a diferencia de otros métodos utilizados para interrogar fuentes de datos (SQL,
XPATH…), LINQ forma parte del lenguaje en el que se desarrolla la aplicación (VB,
ShareVideos
C#…). Otro punto muy importante relativo a LINQ reside en la propia sintaxis del
lenguaje. Esta será la misma, independientemente del tipo de fuente de datos consultado:
tabla, colección, base de datos, archivo XML, dataset... El último punto importante de esta
presentación de LINQ se refiere a los datos manipulados. La aplicación está desarrollada
con un lenguaje orientado a objetos, y resulta que LINQ también manipula objetos. Así, no
es necesario realizar manualmente las operaciones de conversión. Si son necesarias, LINQ
las realizará automáticamente. Después de este breve vistazo, veamos ahora la sintaxis de
LINQ.
Los datos utilizados para crear estas instancias de clase son extraídos de la base de datos
Northwind. Están ubicados en un archivo de texto que el código lee para crear las instancias
de clase en memoria. A continuación está el extracto de código que permite realizar estas
operaciones.
ShareVideos
End If
Loop Until fila Is Nothing
f.Close()
End Sub
En los siguientes ejemplos, supondremos que esta porción de código ya ha sido ejecutada
para rellenar las dos listas. Este boceto de proyecto está disponible para su descarga en el
sitio del editor.
El primer paso es muy sencillo: una clase debe implementar la interfaz genérica
IEnumerable(T) para ser utilizada como una fuente de datos. Es el caso de muchas clases
del Framework .NET que son directamente utilizables en consultas LINQ.
Para las fuentes de datos que no implementan esta interfaz, como por ejemplo un
documento XML, hay clases auxiliares que permiten hacerlas compatibles con LINQ.
La mayor parte del trabajo está constituido por la segunda etapa: la creación de la propia
consulta.
En la consulta, vamos a indicar qué datos deseamos obtener de la fuente de datos, cómo
serán ordenados, agrupados o estructurados.
ShareVideos
la consulta solo tiene lugar cuando uno se interesa por los datos que devuelve. En el
siguiente ejemplo se muestra cómo navegar por los resultados de un bucle For Each.
Este mecanismo permite ejecutar varias veces la misma consulta sin tener que volver a
definirla para cada ejecución.
También puede acceder a múltiples fuentes de datos utilizando la cláusula From. Para ello,
la palabra clave Join permite combinar los datos de diferentes fuentes. El siguiente ejemplo
busca los clientes cuyo apellido empieza por una A y recupera la fecha de todos los pedidos
de cada uno de ellos.
Los operadores que permiten la creación de consultas LINQ se pueden clasificar en ocho
categorías:
ShareVideos
Ordenar datos.
Operaciones sobre conjuntos de datos.
Filtrar datos.
Proyección.
Particiones.
Unión, agrupación de datos.
Cuantificadores.
Agregación.
Para escribir consultas LINQ eficaces, conviene conocer correctamente estos operadores.
Por lo tanto, vamos a verlos en detalle con muchos ejemplos.
a. Ordenar datos
Es muy fácil obtener los resultados de una consulta ordenados según uno o varios criterios.
Gracias al operador Order By, podemos indicar la propiedad por la que vamos a ordenar.
La siguiente consulta ordena los clientes según su número de pedidos.
Por defecto, el orden se aplica de manera ascendente. Para obtener los mejores clientes al
principio de la lista, es preferible utilizar la palabra clave Descending después del criterio
de ordenación.
Se pueden indicar varios criterios de ordenación para eliminar las ambigüedades cuando
dos propiedades tienen el mismo valor. Se deben separar con comas los criterios de
ordenación en la consulta. La consulta ordena los clientes según el número de pedidos en
orden descendente y luego según el apellido del cliente en orden ascendente, en caso de que
el número de pedidos sea el mismo.
ShareVideos
For Each unCliente In ConsultaOrdenada3
Console.WriteLine(unCliente.apellido & "num pedidos:"
& unCliente.Pedidos.Count)
Next
c. Filtrar datos
d. Proyección
ShareVideos
propiedad. En este caso, se utiliza el resultado de la función como valor para la propiedad
del objeto creado. También puede proyectar el objeto original sin modificarlo.
Las proyecciones también pueden realizarse indicando varias cláusulas From en la consulta.
En este caso, el resultado de la consulta hace que cada objeto de cada una de las fuentes de
datos se corresponda con todos los objetos de las otras fuentes.
e. Particiones
La partición consiste en dividir en dos partes un conjunto de datos y en devolver una de las
dos partes. El límite de la partición puede ser absoluto, y en este caso expresar la cantidad
de objetos, o condicional. Se utilizan dos cláusulas para la partición:
Skip indica que se desea obtener la segunda parte de la lista (en realidad se «salta»
los objetos ubicados al principio);
Take indica que se desea obtener el principio de la lista sin tener en cuenta los
registros del final de lista.
Veamos cómo utilizar estos dos operadores con la sintaxis absoluta y la sintaxis
condicional.
ShareVideos
La siguiente consulta permite obtener la lista de los diez peores clientes (basándose en el
número de pedidos).
Para ilustrar la sintaxis condicional, buscamos ahora todos los clientes que tienen un
número de pedidos inferior o igual a 5.
Para recompensar a nuestros clientes fieles, buscamos ahora los diez mejores entre ellos.
Para terminar, buscamos los clientes que han pasado al menos diez pedidos.
La unión de dos fuentes de datos corresponde a la asociación de una de las fuentes de datos
con los objetos de la otra fuente de datos con la que tienen una propiedad común. En
programación orientada a objetos, las uniones permiten reemplazar asociaciones
incompletas. En el ejemplo que utilizamos desde el principio de este capítulo, la clase
Cliente contiene una propiedad que permite obtener la lista de los pedidos de un cliente
(Pedidos) y la clase Pedido contiene un atributo que permite referenciar el cliente que ha
ShareVideos
pasado el pedido (Cliente). En nuestro caso, la asociación es bidireccional. Si por omisión
la propiedad Pedidos de la clase Cliente no existe, debemos recorrer la lista de pedidos y
evaluar cada uno de ellos para obtener todos los pedidos de un cliente específico. Le
corresponde a la unión realizar este trabajo. La siguiente consulta obtiene los pedidos de
cada cliente.
Para cada pedido se repiten los datos relativos al cliente. Una solución más eficaz consiste
en ejecutar la consulta para que añada a cada cliente la lista de sus pedidos. La cláusula
Group Join permite realizar esta agrupación. En este caso, es también necesario especificar
con la cláusula Into el nombre de la propiedad utilizada para acceder al reagrupamiento, en
nuestro caso la lista de pedidos del cliente. Cabe observar que para nosotros esta propiedad
se duplicará (con la que ya teníamos prevista en nuestra clase Cliente).
También se puede llevar a cabo una agrupación sin realizar la unión entre dos fuentes de
datos. Por ejemplo, podemos buscar para cada ciudad la lista de los clientes y residentes.
Para ello, la cláusula Group By Into es ideal. Solo es necesario indicar que deseamos
agrupar los clientes con su ciudad de residencia, como clave de agrupación, e indicar el
nombre de la propiedad que se generará para contener la agrupación. La consulta genera
entonces, durante su ejecución, una lista de instancias de clases que contiene dos
propiedades:
El nombre de la ciudad.
La lista de los clientes gracias a la propiedad indicada en la consulta.
ShareVideos
For Each c In r.ClientesPorCiudad
Console.WriteLine(vbTab & c.apellido)
Next
Next
g. Cuantificadores
Los cuantificadores se utilizan para controlar si en una lista al menos un elemento cumple
una condición, o si todos los elementos la cumplen. Proporcionan el resultado del control
en forma de un booleano que en general se utiliza en la cláusula Where. Como ejemplo,
buscaremos todos los clientes cuyos pedidos han sido realizados en 2007.
La segunda versión permite la búsqueda de clientes que hayan hecho al menos un pedido
durante 2008.
h. Agregación
Se utilizan las operaciones de agregación para el cálculo de un valor único desde valores
contenidos en una lista de elementos. Las operaciones más corrientes son:
El siguiente ejemplo aplica estos cuatro operadores sobre los gastos de envío de todos los
pedidos.
ShareVideos
Average(unPedido.envio)
Console.WriteLine("promedio de envío: " & promedioEnvio)
Dim maxiEnvio = Aggregate unPedido In listaPedidos Into
Max(unPedido.envio)
Console.WriteLine("envío máximo: " & maxiEnvio)
Dim miniEnvio = Aggregate unPedido In listaPedidos Into
Min(unPedido.envio)
Console.WriteLine("envío mínimo: " & miniEnvio)
Dim totalEnvio = Aggregate unPedido In listaPedidos Into
Sum(unPedido.envio)
Console.WriteLine("total envío: " & totalEnvio)
Este código también es un buen ejemplo de consulta de ejecución inmediata, ya que para
obtener el resultado se debe recorrer obligatoriamente la lista desde el primero hasta el
último elemento.
Después de haber estudiado la sintaxis del lenguaje, vamos a ver ahora cómo utilizarlo en
asociación con una base de datos.
Existen tres soluciones para generar las clases que representan los datos almacenados en la
base de datos:
ShareVideos
Utilizar el diseñador Objeto/Relacional en modo gráfico.
a. SQLMetal
Esta herramienta está disponible desde una ventana de comando del entorno Visual Studio.
Las opciones indicadas en la línea de comando permiten configurar el funcionamiento. Las
opciones disponibles tratan de:
La generación del código fuente de las clases y de los atributos de mapeo a partir de
una base de datos.
La generación de un archivo intermedio de mapeo (.dbml) a partir de una base de
datos.
La generación de las clases y de los atributos de mapeo a partir de un archivo de
mapeo.
Cada opción debe venir precedida por un carácter ’/’ y seguida por el carácter ’:’ y el valor
de la opción si es necesario.
Indica la cuenta de usuario con la que se abrirá la conexión hacia la base de datos. Si no se
especifica esta opción, se utilizará la autenticación de Windows.
/password: <contraseña>
Se puede utilizar en lugar de las cuatro opciones anteriores, para facilitar los datos relativos
a la conexión hacia el servidor de base de datos.
timeout: <segundos>
Indica la duración máxima durante la cual SQLMetal intenta establecer la conexión hacia la
base de datos. Un valor igual a cero indica una duración ilimitada.
ShareVideos
Las opciones de salida:
/lenguaje:< vb o csharp>
Indica el lenguaje en el que se generará el código. Las dos opciones válidas son vb para
Visual Basic y csharp para C#.
/namespace:<nombre>
Indica el espacio de nombres en el que se generarán las clases. Por defecto, no hay un
espacio de nombres.
/context:<nombre>
Especifica el nombre del datacontext generado. Por defecto, se deduce este nombre del
nombre de la base de datos.
/entitybase:<nombre>
Especifica la clase base de las clases generadas. Por defecto, las clases generadas no tienen
clase base.
Para terminar, la última información que se debe facilitar corresponde al nombre del
archivo de mapeo a partir del cual se realizará la generación de las clases. Esta información
es inútil si la generación se ejecuta directamente desde la base de datos.
Como el código generado es demasiado voluminoso para listarlo aquí (unas 3.500 líneas),
veamos el diagrama siguiente de las clases generadas.
ShareVideos
Tenemos la clase Northwind, que hereda de la clase DataContext y que rápidamente nos va
a servir para que LINQ pueda dialogar con la base de datos. También tenemos una clase
generada para cada una de las matrices de la base de datos. Trabajaremos con las instancias
de estas clases en nuestra aplicación.
Se puede modificar este archivo para, por ejemplo, cambiar el nombre de las clases y de las
propiedades asociadas a los datos que proceden de la base de datos. En el siguiente
ejemplo, hemos traducido los nombres.
ShareVideos
<Column Name="CustomerID" Member="CódigoCliente"
Storage="CustomerID"
Type="System.String" DbType="NChar(5) NOT NULL" IsPrimaryKey="true"
CanBeNull="false" />
<Column Name="CompanyName" Member="NombreEmpresa"
Storage="CompanyName"
Type="System.String" DbType="NVarChar(40) NOT NULL" CanBeNull="false" />
<Column Name="ContactName" Member="NombreContacto"
Storage="ContactName"
Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
<Column Name="ContactTitle" Member="Funcion"
Storage="ContactTitle"
Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
<Column Name="Address" Member=Direccion" Storage="Address"
Type="System.String" DbType="NVarChar(60)" CanBeNull="true" />
<Column Name="City" Member="Ciudad"
Storage="City"Type="System.String"
DbType="NVarChar(15)" CanBeNull="true" />
<Column Name="Region" Type="System.String" DbType="NVarChar(15)"
CanBeNull="true" />
<Column Name="PostalCode" Member="CódigoPostal"
Storage="PostalCode"
Type="System.String" DbType="NVarChar(10)" CanBeNull="true" />
<Column Name="Country" Member="Pais" Storage="Country"
Type="System.String" DbType="NVarChar(15)" CanBeNull="true" />
<Column Name="Phone" Member="Telefono" Storage="_Phone"
Type="System.String"
DbType="NVarChar(24)" CanBeNull="true" />
<Column Name="Fax" Type="System.String" DbType="NVarChar(24)"
CanBeNull="true" />
<Association Name="Cliente_CustomerCustomersDemo" Member=
"CustomerCustomerDemo" ThisKey="CodigoCliente" OtherKey="CustomerID"
Type="CustomerCustomerDemo" />
<Association Name="Cliente_Orders" Member="Orders"
ThisKey="CodigoCliente"
OtherKey= "CustomerID" Type="Orders" />
</Type>
</Table>
En este ejemplo, con objeto de poder utilizar nombres de propiedades diferentes de los
nombres de columnas en la base de datos, hemos añadido el atributo Member a cada
etiqueta <Column> para especificar el nombre de la propiedad y el atributo storage para
indicar el nombre de la variable interna de la clase que contendrá la información.
Ahora podemos generar el código a partir del archivo de mapeo modificado con el siguiente
comando:
Veamos la clase generada para comprobar que nuestras modificaciones se han tenido en
cuenta.
ShareVideos
Esta herramienta es muy fácil de utilizar, pero presenta el pequeño inconveniente de poder
generar las clases solo para la totalidad de una base de datos. Además, las modificaciones
se deben hacer manualmente, sea en el código fuente generado o en el archivo de mapeo
intermedio. Para la generación y la personalización de algunas clases, es preferible utilizar
el diseñador Objeto/Relacional integrado en Visual Studio.
b. Diseñador Objeto/Relacional
El diseñador Objeto/Relacional ofrece una solución muy práctica para crear el modelo
objeto de una aplicación que representa los datos disponibles en una base de datos.
También permite la creación de procedimientos y funciones que autorizan la utilización de
los procedimientos almacenados y funciones presentes en la base de datos. Sin embargo,
comporta algunas limitaciones:
Solo las bases de datos SQL Server 2000, SQL Server 2005, SQL Server Express y
SQL Server 2008 son compatibles.
El mapeo solo es posible entre una clase y una tabla, lo que significa que no se
puede crear una clase para representar el resultado de una unión entre varias tablas.
El diseñador funciona en «sentido único», ya que en el código generado solo se
plasman las modificaciones efectuadas en él. Si se modifica el código manualmente,
el diseñador no tiene en cuenta las modificaciones. Y lo que es peor, si se
introducen cambios en el diseñador después de haber hecho cambios manuales en el
código, estos cambios se pierden al en el momento de guardar el diseñador, ya que,
en ese caso, el código se regenera automáticamente. La solución consiste en crear
una clase parcial en un archivo independiente del que utiliza el diseñador.
Agregar clases
Puede crear las clases que representan las matrices de una base de datos arrastrando y
soltando una o varias matrices desde el explorador de servidores hacia la parte izquierda del
diseñador. El primer elemento agregado al diseñador Objeto/Relacional se usa para
configurar las propiedades de la conexión del DataContext. Cuando se añade otro elemento
procedente de otra base de datos, un cuadro de diálogo le pregunta si desea sustituir la
conexión existente. Si acepta la modificación, las clases ya presentes en el diseñador no se
podrán utilizar. La adición de una matriz genera el código necesario para que el
ShareVideos
DataContext inicialice las propiedades de una instancia de la clase a partir de la
información presente en una fila de la base de datos. También añade el código necesario
para que las modificaciones aportadas a las propiedades de la instancia se puedan volcar en
la base de datos. El diseñador se basa en la estructura de la tabla y en la clave primaria para
efectuar las actualizaciones.
Si lo desea, también puede indicar cómo deben efectuarse las actualizaciones. Para ello,
cada clase posee tres propiedades: Insert, Update, Delete. Por defecto se inicializan estas
propiedades con el valor Utilizar el runtime para indicar que el código encargado de las
actualizaciones se genera automáticamente. Para modificar este comportamiento, puede
asignar a estas propiedades procedimientos almacenados. Un cuadro de diálogo permite la
configuración de estas propiedades.
Agregar asociaciones
Después de haber arrastrado varias tablas al diseñador, es posible crear asociaciones entre
algunas de ellas. Las asociaciones son muy similares a las relaciones entre tablas en una
base de datos. De hecho, si existe en la base de datos una relación de clave exterior entre
dos tablas, se creará automáticamente una asociación cuando estas dos tablas se agreguen al
diseñador.
Para agregar manualmente una asociación, debe utilizar el menú contextual del diseñador
Objeto/Relacional.
ShareVideos
Cardinality: determina si la asociación es de tipo uno a varios (one-to-many) o de
tipo uno a uno (one-to-one).
Child Property: indica si una propiedad debe ser creada en la clase padre para
referenciar la información de la clase hijo. El tipo de esta propiedad viene
determinado por el tipo de la clase hijo y la cardinalidad. Si la cardinalidad es uno a
uno, la propiedad es una simple referencia hacia una instancia de la clase
correspondiente. Si la cardinalidad es uno a varios, la propiedad es una colección de
instancias de la clase correspondiente.
Las propiedades Name permiten identificar las propiedades creadas para realizar la
asociación.
Agregar métodos
En cambio, si se desplaza el elemento hacia una clase existente del diseñador, el tipo de
retorno corresponderá a esta clase siempre que la información devuelta por el
procedimiento almacenado sea compatible con esta clase. Vamos a hacer unas
manipulaciones con el procedimiento almacenado [Ten Most Expensive Products], cuyo
código es el siguiente:
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
Este procedimiento devuelve el nombre y el precio de los diez productos más caros. Si
intentamos añadir este procedimiento al DataContext arrastrándolo y soltando hasta la
superficie de la clase Product, obtenemos el siguiente mensaje.
ShareVideos
En efecto, los elementos devueltos por el procedimiento almacenado no son productos, sino
simplemente el nombre y el precio del producto.
Veamos la estructura.
Para que la clase Product pueda utilizarse como tipo de retorno para la función, estamos
obligados a modificar ligeramente el procedimiento almacenado para que devuelva
productos, y no solamente el nombre y el precio del producto.
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go
Ahora podemos volver a hacer la misma operación y obtener la siguiente función, que, esta
vez, devuelve una lista de productos.
Herencia de clases
ShareVideos
Como cualquier clase, las clases generadas por el Diseñador Objeto/Relacional pueden
utilizar la herencia. Por el contrario, para las bases de datos, es una noción desconocida.
Hay que recurrir a algunos trucos para simular esta técnica en una base de datos. La
solución que se suele utilizar consiste en crear una tabla única que contendrá a la vez los
datos de los objetos de la clase básica y los de la subclase. Se añade una columna adicional
a la tabla a modo de discriminador. En función del valor de esta columna, es fácil
determinar si se debe representar la fila con una instancia de la clase de base o una instancia
de la derivada. Vamos a modificar la tabla Products para poder aplicar esta técnica.
Añadimos a la tabla una columna llamada Perecedera de tipo entero. Esta columna nos va a
servir de discriminador. Si el valor que contiene es igual a 1, se trata de un producto no
perecedero. Si el valor es igual a 2, se trata de un producto perecedero. En este caso, la
segunda columna, llamada DLC, de tipo fecha, contiene la fecha límite de consumo del
producto. Para los productos no perecederos, esta columna no contiene ningún valor (null).
Modifique los datos de algunos productos para que se conviertan en productos perecederos
(Camenbert Pierrot, Caracoles de Borgoña, Mascarpone Fabioli…).
Ahora que la base de datos está lista, podemos añadir las clases al DataContext. La primera
etapa consiste en añadir la tabla que constituye la clase de base. Luego agregamos un
segundo ejemplar de esa tabla y cambiamos el nombre de la clase correspondiente, que se
convertirá en la clase derivada. A continuación agregamos, utilizando la caja de
herramientas, una relación de herencia entre las dos clases que dibujamos desde la clase
hija hacia la clase padre. En cada una de las clases eliminamos las propiedades inútiles,
manteniendo, por ejemplo, la propiedad DLC en la clase derivada y eliminándola en la
clase base. Una vez seleccionada la relación de herencia en el diagrama, debemos modificar
sus propiedades.
Ahora que nuestras clases están disponibles, veamos cómo utilizarlas mediante consultas
LINQ.
Las consultas LINQ a SQL utilizan de manera rigurosa la misma sintaxis que las que
hemos estudiado en la sección Sintaxis del lenguaje LINQ. La única pequeña diferencia
ShareVideos
radica en que los datos son extraídos, en este caso, de la base de datos y transformados en
instancias de clases a partir de los datos de mapeo. El diálogo con la base de datos está
enteramente a cargo del DataContext. Por lo tanto, tenemos que crear una instancia del
DataContext porque es por su intermediación que tendremos los datos disponibles para la
ejecución de la consulta LINQ. A continuación presentamos nuestra primera consulta LINQ
hacia la base de datos.
Dim dc As NorthWind
dc = New NorthWind
Dim consulta = From unCliente In dc.Customers _
Where unCliente.ContactName Like "A*" _
Select unCliente
En este código, la clase NorthWind corresponde al DataContext, que es el puente para que
los datos estén disponibles para la consulta LINQ. Pero ¿cómo se seleccionan los datos?
En realidad, el método más natural para obtener datos procedentes de una base de datos
consiste en pedir a esta que ejecute una consulta SQL. Efectivamente, esta solución es la
utilizada por LINQ. Para verificarlo, podemos pedirle al DataContext (NorthWind en
nuestro caso) que muestre en la consola el código SQL que genera automáticamente. Para
ello, simplemente inicialicemos la propiedad Log del DataContext con la salida de la
consola, antes de la creación de la consulta LINQ.
Dim dc As NorthWind
dc = New NorthWind
dc.Log = Console.Out
Dim consulta = From unCliente In dc.Customers _
Where unCliente.ContactName Like ”A*” _
Select unCliente
Ana Trujillo
Antonio Moreno
Ann Devon
ShareVideos
Aria Cruz
André Fonseca
Annette Roulet
Alexander Feuer
Alejandra Camino
Art Braunschweiger
Anabela Domingues
Efectivamente, contamos con una consulta SQL con parámetros, que ha sido creada
automáticamente por el DataContext. Esta consulta no es muy complicada y se hubiese
podido escribir de forma fácil utilizando directamente ADO.NET. Intentemos ejecutar otra
consulta que nos permita obtener las fechas de pedidos de cada uno de los clientes.
Esto empieza a complicarse de manera seria. Escribir directamente en SQL una consulta
como esta requeriría ciertamente el dominio de este lenguaje, mientras que, en cambio, la
sintaxis LINQ resulta muy sencilla. Aquí, justamente, es donde puede encontrarse la
potencia de LINQ a SQL.
Esta facilidad no se limita a la extracción de datos desde la base de datos, ya que LINQ a
SQL también es capaz de gestionar las actualizaciones de los datos hacia la base de datos.
ShareVideos
d. Actualización de datos
La primera etapa consiste en obtener los datos que se desea modificar ejecutando una
consulta de selección ordinaria. Una vez que los datos están disponibles en forma de
instancias de clases, podemos simplemente modificar las propiedades de estas instancias.
Para transferir las modificaciones hacia la base de datos, basta con pedirle al DataContext
que las propague hacia la base de datos. Vamos a probar esta técnica desplazando nuestros
clientes barceloneses a Valencia.
UPDATE [dbo].[Customers]
SET [City] = @p10, [PostalCode] = @p11
WHERE ([CustomerID] = @p0) AND ([CompanyName] = @p1) AND ([ContactName] =
@p2)
AND ([ContactTitle] = @p3) AND ([Address] = @p4) AND ([City] = @p5)
AND ([Region]IS NULL) AND ([PostalCode] = @p6) AND ([Country] = @p7)
AND ([Phone] = @p8) AND ([Fax] = @p9)
-- @p0: Input NChar (Size = 5; Prec = 0; Scale = 0) [FRANR]
-- @p1: Input NVarChar (Size = 19; Prec = 0; Scale = 0) [España
restauración]
-- @p2: Input NVarChar (Size = 14; Prec = 0; Scale = 0) [Carine Schmitt]
-- @p3: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Marketing
Manager]
-- @p4: Input NVarChar (Size = 13; Prec = 0; Scale = 0) [calle real 54]
-- @p5: Input NVarChar (Size = 9; Prec = 0; Scale = 0) [Barcelona]
-- @p6: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [08000]
-- @p7: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [España]
-- @p8: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [40.32.21.21]
-- @p9: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [40.32.21.20]
-- @p10: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Valencia]
-- @p11: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [46000]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build:
3.5.21022.8
ShareVideos
Eliminación de datos
Como para la modificación, debemos obtener previamente los elementos que deseamos
eliminar ejecutando una consulta de selección, y luego indicar cuáles de ellos deseamos
suprimir. Para ello, llamamos al método DeleteOnSubmit de la tabla a la que pertenece el
elemento, pasándole como parámetro el objeto que deseamos eliminar. Para confirmar las
eliminaciones, debemos invocar el método SubmitChanges del DataContext. Vamos a
probar esta técnica eliminando los clientes brasileños de la base de datos.
Esta solución es la que vamos a utilizar. Ya que nuestro modelo objeto está diseñado
correctamente, esta solución es muy fácil de poner en marcha. En efecto, en la clase
Customers, tenemos la colección Orders, que representa los pedidos del cliente. Del mismo
modo en la clase Orders, tenemos la colección Order_Details, que representa todas las filas
de un pedido. Solo hace falta ejecutar tres bucles anidados que van a suprimir las filas de
cada pedido, los pedidos de cada cliente y finalmente los propios clientes.
ShareVideos
Next
dc.SubmitChanges()
Con esta solución, ya no hay problemas y nuestros clientes brasileños están borrados
correctamente de la base de datos.
Agregar datos
La inclusión de datos se realiza en tres etapas. Primero es necesario crear una instancia de
la clase que representa los datos que deseamos insertar en la base de datos. Luego se
inicializan las propiedades de esta instancia con los valores que queremos agregar en la
base de datos. El objeto configurado debe insertarse en la tabla del DataContext.
Finalmente las modificaciones son transferidas hacia la base de datos. Para ilustrar estas
etapas, vamos a añadir un nuevo cliente a la base de datos.
Ocurre a menudo que varios usuarios trabajan simultáneamente con la misma base de datos.
Se pueden producir conflictos cuando los mismos registros de la base de datos son
actualizados por varios usuarios. LINQ propone un mecanismo que permite tratar este
problema. Este mecanismo se descompone en cuatro etapas:
Durante la creación de las clases con el diseñador Objeto/Relacional, podemos indicar, para
cada propiedad, si debe ser incluida en el mecanismo de detección de conflictos. Cada
miembro de la clase generada posee una propiedad Update Check a la que podemos asignar
tres valores diferentes:
ShareVideos
Siempre: la detección de conflictos está siempre activa para este elemento.
WhenChanged: activa la detección únicamente si el valor ha sido modificado.
Nunca: no tener en cuenta este elemento para la detección de conflictos.
Detección de conflictos
Los conflictos surgen durante el traslado de la información hacia la base de datos. Por lo
tanto, debemos intervenir a este nivel. Para ello, durante la invocación del método
SubmitChanges del DataContext, indicamos con un parámetro cómo debe comportarse el
mecanismo de detección de conflictos. Dos soluciones son posibles:
ShareVideos
Fusionar las propiedades del objeto con la información de la base de datos. Se
modifica la información de la base de datos solo si la propiedad correspondiente al
objeto ha sido modificada. En este caso, se debe llamar al método Resolve con la
constante KeepChanges.
Dim cl As Customer
Dim rqt = From unCliente In dc.Customers _
Where unCliente.CustomerID = "BOLID" _
Select unCliente
Presentación
El lenguaje XML (eXtensible Markup Language) es un lenguaje que sirve para representar
datos. Permite encapsular cualquier tipo de datos representándolos en forma de árbol. Los
datos se escriben en etiquetas o en forma de atributos. Este formato permite escribir datos,
pero no darles formato ni manipularlos. Se utiliza principalmente para hacer posible el
intercambio de datos entre aplicaciones e incluso entre sistemas diferentes. También se
utiliza a menudo como formato de almacenamiento para los parámetros de configuración de
una aplicación. Visual Studio y Windows lo utilizan habitualmente con este fin. Este
lenguaje ha sido diseñado por W3C (World Wide Web Consortium). Por lo tanto, es en el
sitio http://www.w3.org/XML donde podrá obtener el detalle de las especificaciones de este
lenguaje.
ShareVideos
El lenguaje XML se confunde a menudo con el lenguaje HTML. Aunque presentan
similitudes, estos dos lenguajes no tienen la misma finalidad. A continuación presentamos
los puntos comunes entre los lenguajes XML y HTML:
Para poder ser manipulados fácilmente, los datos XML se deben confiar a un procesador
XML.
Instrucción de tratamiento
ShareVideos
documento. Se utilizan estas instrucciones para facilitar una instrucción especial a una
aplicación que trabaja en el documento.
Comentarios
Los comentarios sirven para incluir en el documento información destinada a los usuarios
de este. El procesador XML o las aplicaciones que utilizan el documento los ignoran. No se
deben incorporar a una etiqueta.
<!--esto es un comentario-->
Caracteres reservados
Algunos caracteres están reservados para el lenguaje XML, como por ejemplo el carácter &
del siguiente ejemplo:
Para poder utilizar estos caracteres en un documento XML, debe sustituirlos por la
siguiente sintaxis:
ShareVideos
" " Por lo tanto, la sintaxis correcta es:
<![CDATA[{ Select * from postres where precio < 10} and calorías > 500]]>
Con esta sintaxis cualquier carácter se puede utilizar sin precaución particular.
Elementos XML
Un elemento XML es un contenedor que incluye datos y otros elementos. Está compuesto
por una etiqueta de principio y otra de fin. La sintaxis de un elemento XML es la siguiente:
<NombreElemento>contenido</NombreElemento>
Ejemplo
ShareVideos
<nombre>tetilla</nombre>
<nombre>cabrales</nombre>
</quesos>
<postres>
<nombre>helado</nombre>
<nombre>tarta</nombre>
<nombre>crema catalana</nombre>
</postres>
</menu>
</restaurante>
Atributos de elementos
Ejemplo
ShareVideos
Espacios de nombres
Veamos el siguiente ejemplo, que podría ser un archivo de configuración de una aplicación:
En este archivo, tenemos elementos ya definidos en otro archivo. Es obvio que los
elementos menu y entrantes no tienen el mismo significado que en el archivo utilizado
anteriormente. Para evitar cualquier ambigüedad, hay que agregar a cada archivo una
definición de espacio de nombres que haga que cada elemento sea único. La definición de
un espacio de nombres se efectúa con el atributo xmlns seguido por un prefijo y por el
identificador del espacio de nombres.
<restaurante xmlns:rest="http://www.eni-escuela.es/restaurante">
<application xmlns:appli="http://www.eni-escuela.es/configappli">
Es muy importante que los identificadores de espacio de nombres sean únicos si desea
intercambiar datos con otras personas. Por eso, es corriente utilizar el nombre del dominio
de la empresa en el identificador (se supone que este es único). Con esta modificación,
podemos utilizar en el mismo archivo elementos de menu y entrantes agregando ante el
prefijo el espacio de nombres en el que tienen un significado.
ShareVideos
2. Documento bien formado y documento válido
Un documento está bien formado si obedece a las reglas sintácticas del lenguaje XML.
Estas reglas son mucho menos estrictas que las reglas de validez. Gestionan las atribuciones
de nombres, las creaciones y los anidamientos de elementos. Para poder ser tratado por un
procesador XML, un documento debe estar bien formado. Si el procesador detecta un error,
detiene inmediatamente el tratamiento del documento.
b. Documento válido
<?xml version="1.0"?>
<restaurante>
<menu precio="10">
<entrantes>rábanos</entrantes>
<plato>fideuá</plato>
<postre>helado</postre>
</menu>
<vinos>
<tinto>rioja</tinto>
<blanco>moscatel</blanco>
</vinos>
</restaurante>
ShareVideos
En la estructura de un documento XML, cada círculo de esta ilustración representa un nodo,
llamado objeto XmlNode, que es el objeto básico del árbol DOM. La clase XmlDocument
se encarga de los métodos destinados a ejecutar operaciones en el documento en su
conjunto, por ejemplo para cargarlo en memoria o grabarlo en forma de archivo. Los
objetos XmlNode comportan un conjunto de métodos y de propiedades, así como
características básicas bien definidas. A continuación, presentamos algunas de estas
características:
Un nodo solo puede poseer un nodo padre, que es el nodo situado justo encima de
él.
El único nodo que no tiene padre es la raíz del documento, ya que se trata del nodo
de primer nivel que contiene el propio documento y los fragmentos de documento.
La mayoría de los nodos pueden comportar varios nodos hijos que son los nodos
situados directamente debajo de ellos.
Los nodos situados en el mismo nivel, representados en el diagrama por los nodos
menú y vinos, son nodos hermanos.
Una de las características del DOM es su manera de gestionar los atributos. Los atributos
no son nodos que forman parte de las relaciones padre-hijo y hermano. Se consideran como
una propiedad del nodo y están constituidos por un par, compuesto por un nombre y un
valor.
ShareVideos
<número calorías="125" frutas="manzanas">tarta</número>
<número calorías="200">crema catalana</número>
</postres>
</menu>
<menu type="economico">
<entrantes>
<número calorías="50">pan</número>
</entrantes>
<platos>
<número calorías="1700">jamón</número>
</platos>
<quesos>
<número calorías="240">manchego</número>
</quesos>
<postres>
<número calorías="340" sabor="sorbete">helado</número>
</postres>
</menu>
</restaurante>
1. Utilización de DOM
También es posible cargar datos XML a partir de una cadena de caracteres. En este caso,
debe utilizar el método LoadXML facilitándole la cadena de caracteres que contiene los
datos XML.
Una vez cargados los datos XML en el árbol, puede localizar nodos especiales con el fin de
manipularlos o modificarlos. El método GetElementsByTagName permite obtener un
objeto XmlNodeList, que contiene los nodos respectivos. Entonces puede obtener los
atributos del nodo utilizando la propiedad Attributes o comprobar si poseen nodos hijos con
la propiedad HasChildNodes. Si es el caso, tiene acceso a estos nodos gracias a la
propiedad ChildNodes en forma de un objeto XmlNodeList.
El siguiente ejemplo busca los nodos menú en el árbol y muestra el atributo tipo.
menus = doc.GetElementsByTagName("menu")
For Each unMenu In menus
Console.WriteLine(unMenu.Attributes("tipo").Value)
Next
También se pueden modificar las características de los nodos añadiéndoles un atributo. Los
nodos pueden, por ejemplo, recibir un atributo precio.
ShareVideos
menus = doc.GetElementsByTagName("menu")
Dim att As XmlAttribute
For Each unMenu In menus
If unMenu.Attributes("tipo").Value = "gastronomico" Then
att = doc.CreateAttribute("precio")
att.Value = "50 euros"
unMenu.Attributes.Append(att)
End If
If unMenu.Attributes("tipo").Value = "economico" Then
att = doc.CreateAttribute("precio")
att.Value = "15 euros"
unMenu.Attributes.Append(att)
End If
Next
También es posible añadir nodos hijos a nodos que existen en el árbol, creando instancias
de la clase XmlNode y uniéndolos a su nodo padre. El siguiente ejemplo añade un
digestivo al menú gastronomico.
menus = doc.GetElementsByTagName("menu")
Dim att As XmlAttribute
For Each unMenu In menus
If unMenu.Attributes("tipo").Value = "gastronomico" Then
Dim n1, n2, n3 As XmlNode
n1 = doc.CreateNode(XmlNodeType.Element, "digestivo", "")
n2 = doc.CreateNode(XmlNodeType.Element, "nombre", "")
n3 = doc.CreateNode(XmlNodeType.Text, "", "")
n3.Value = "Cognac"
n2.AppendChild(n3)
n1.AppendChild(n2)
unMenu.AppendChild(n1)
End If
Next
Después de la ejecución de los dos ejemplos anteriores, el documento XML debe tener la
siguiente forma:
ShareVideos
<postres>
<número calorías="340" sabor="chocolate">helado</número>
<número calorías="250" frutas="manzanas">tarta</número>
<número calorías="400">crema catalana</número>
</postres>
<digestivo>
<número>Cognac</número>
</digestivo>
</menu>
<menu tipo="economico" precio="15 €">
<entrantes>
<número calorías="50">pan</número>
</entrantes>
<platos>
<número calorías="1700">jamón</número>
</platos>
<quesos>
<número calorías="240">manchego</número>
</quesos>
<postres>
<número calorías="340" sabor="sorbete">helado</número>
</postres>
</menu>
</restaurante>
doc.Save("rest2.xml")
2. Utilización de XPath
Para buscar un elemento en un documento XML, la primera etapa consiste en crear una
instancia de la clase XPathNavigator. Esta instancia de clase debe conocer el documento en
el que deberá hacer las búsquedas. Por eso es el propio documento el que, mediante el
método CreateNavigator, va a facilitar esta instancia de clase.
ShareVideos
A partir de esta instancia, vamos a poder lanzar búsquedas en el documento con la ayuda
del método Select. Este método utiliza como parámetro una cadena de caracteres que
contiene la ruta XPath de búsqueda. Después de la ejecución, obtenemos un objeto
XPathNodeIterator, que permite recorrer la lista de los nodos encontrados.
<entrantes>
<número calorías="50">rábanos</número>
<número calorías="300">pasta</número>
<número calorías="350">salchichón</número>
</entrantes>
<entrantes>
<número calorías="50">pan</número>
</entrantes>
También es posible añadir a la consulta XPath unos criterios de selección sobre el valor de
ciertos atributos.
El siguiente ejemplo busca los postres del menú gastronomico con menos de 350 calorías.
ShareVideos
El siguiente ejemplo disminuye un 50 % las calorías de cada postre del menú
gastronomico.
While nodos.MoveNext()
nodos.Current.MoveToAttribute("calorías", "")
nodos.Current.SetValue(nodos.Current.Value * 0.5)
End While
documento.Save("rest.xml")
ShareVideos
</postres>
</menu>
</restaurante>
ShareVideos
</platos>
<quesos>
<número calorías="240">manchego</número>
</quesos>
<postres>
<número calorías="340" sabor="sorbete">helado</número>
</postres>
</menu>
</restaurante>
El uso de LINQ puede ser una alternativa a DOM y XPath para manejar documentos XML.
El principio de funcionamiento es prácticamente igual al de DOM, ya que, para poder
trabajar con un documento XML, en primer lugar es necesario cargarlo en memoria como
una arborescencia de objetos. Las clases necesarias para esta representación están
disponibles en la biblioteca System.Xml.Linq. Por tanto, es imprescindible añadir a su
proyecto una referencia a esta biblioteca.
Ahora el contenido del archivo está disponible en memoria en forma de instancias de las
clases XElement y XAttribute, relacionadas con la instancia de la clase XDocument que se
ha creado.
A las instancias se puede acceder con la propiedad Elements del objeto XDocument.
<restaurante>
<menu tipo="gastronomico">
<entrantes>
<número calorías="50">rábanos</número>
<número calorías="300">pasta</número>
<número calorías="350">salchichón</número>
</entrantes>
<platos>
ShareVideos
<número calorías="1000">paella</número>
<número calorías="2000">cocido</número>
<número calorías="1700">cuscús</número>
</platos>
<quesos>
<número calorías="240">manchego</número>
<número calorías="300">tetilla</número>
<número calorías="120">cabrales</número>
</quesos>
<postres>
<número calorías="340" sabor="chocolate">helado</número>
<número calorías="250" frutas="manzanas">tarta</número>
<número calorías="400">crema catalana</número>
</postres>
</menu>
<menu tipo="economico">
<entrantes>
<número calorías="50">pan</número>
</entrantes>
<platos>
<número calorías="1700">jamón</número>
</platos>
<quesos>
<número calorías="240">manchego</número>
</quesos>
<postres>
<número calorías="340" sabor="sorbete">helado</número>
</postres>
</menu>
</restaurante>
La raíz del documento forma parte de los elementos que se extraen del archivo.
En este caso, obtenemos un objeto XElement, que representa al elemento raíz. Su propiedad
Elements contiene los elementos hijo del contenido del archivo XML (sin elemento raíz).
<menu tipo="gastronomico">
<entrantes>
<número calorías="50">rábanos</número>
<número calorías="300">pasta</número>
<número calorías="350">salchichón</número>
</entrantes>
<platos>
<número calorías="1000">paella</número>
<número calorías="2000">cocido</número>
<número calorías="1700">cuscús</número>
ShareVideos
</platos>
<quesos>
<número calorías="240">manchego</número>
<número calorías="300">tetilla</número>
<número calorías="120">cabrales</número>
</quesos>
<postres>
<número calorías="340" sabor="chocolate">helado</número>
<número calorías="250" frutas="manzanas">tarta</número>
<número calorías="400">crema catalana</número>
</postres>
</menu>
<menu tipo="economico">
<entrantes>
<número calorías="50">pan</número>
</entrantes>
<platos>
<número calorías="1700">jamón</número>
</platos>
<quesos>
<número calorías="240">manchego</número>
</quesos>
<postres>
<número calorías="340" sabor="sorbete">helado</número>
</postres>
</menu>
El objetivo de LINQ era hacer consultas y extraer contenido de un documento XML. Por
este motivo, vamos a ver cómo escribir una consulta LINQ en un documento XML. Para
empezar, vamos a buscar las entrantes disponibles en los diferentes menús.
Después de cargar el archivo en un objeto XDocument, vamos a utilizar una consulta LINQ
para buscar la lista de los elementos cuyo número es entrantes.
Dim s As Xelement
For Each s In listaEntrantes
Console.WriteLine(s)
Next
<entrantes>
<número calorías="50">rábano</número>
<número calorías="300">pasta</número>
ShareVideos
<número calorías="350">salchichón</número>
</entrantes>
<entrantes>
<número calorías="50">pan</número>
</entrantes>
En el segundo ejemplo, vamos a buscar los alimentos con un número de calorías superior a
1.000.
Como en el ejemplo anterior, vamos a buscar los elementos por nombre y luego
aplicaremos una restricción sobre el atributo calorías.
<número calorías="2000">cocido</número>
<número calorías="1700">cuscús</número>
<número calorías="1700">jamón</número>
Introducción
Ahora que su aplicación está terminada, probada, depurada y, por lo tanto, funciona sin
problemas, es el momento de pensar en la manera de ponerla a disposición de los usuarios.
Hay dos soluciones posibles:
ShareVideos
todos los datos e instrucciones necesarios para la implementación de una aplicación.
Representa una evolución importante respecto a los procedimientos de instalación clásicos,
que consistían principalmente en facilitar el conjunto de los archivos necesarios para el
funcionamiento correcto de la aplicación y un script encargado de copiar esos archivos en
el disco duro de la máquina.
Con Windows Installer, el sistema conserva un rastro de todas las operaciones efectuadas
durante la instalación: directorios creados, archivos copiados, entradas del registro
modificadas, etc. Estos datos se utilizan durante la desinstalación de la aplicación,
momento en que Windows Installer efectúa las operaciones inversas. Sin embargo, se
realiza un control para garantizar que ninguna otra aplicación necesite un archivo, una clave
de registro o un componente que esté a punto de ser eliminado. Esta verificación permite
asegurar que la eliminación de una aplicación no conlleva problemas de funcionamiento en
otra aplicación.
El enlace Vaya al sitio web de descarga le permite acceder al sitio web de la empresa
FLEXERA Software, que garantiza la distribución del software. Debe rellenar el formulario
de inscripción antes de poder descargar el producto. Hay que proporcionar una dirección de
ShareVideos
correo electrónico válida porque se enviará un código a esta dirección para activar el
producto antes de usarlo por primera vez. Puede ejecutar la instalación directamente a partir
del sitio de descarga o copiar localmente el archivo y después ejecutar la instalación a partir
de la copia local. Esta última opción es mejor porque facilita la vuelta atrás en caso de
producirse un incidente, sin tener que descargar de nuevo el archivo. Es preferible que
Visual Studio esté cerrado durante el procedimiento de instalación. En caso contrario, será
necesario un reinicio. Lo primero que hace el programa de instalación es actualizar su
sistema para integrar los componentes que necesita InstallShield.
ShareVideos
Cada etapa cubre un aspecto concreto del funcionamiento del programa de instalación. Con esta
versión Limited Edition de InstallShield, algunas funcionalidades u opciones están bloqueadas.
Estas se identifican con el icono .
a. Información general
El nombre de su empresa.
El nombre de la aplicación.
El número de versión de la aplicación.
El sitio web donde está disponible la información adicional de la aplicación.
El icono asociado a la aplicación.
b. Requisitos previos
ShareVideos
La siguiente etapa no es configurable con la version Limited Edition de InstallShield. Por
tanto, pasamos a la etapa número cuatro, que es la más importante del asistente.
c. Archivos de la aplicación
Para que la aplicación pueda ejecutarse en el ordenador cliente, se debe seleccionar como
mínimo la opción Resultado principal. Por el contrario, la opción Archivos de código
fuente se utiliza raramente.
Para facilitar la ejecución de la aplicación por parte del usuario, es deseable proporcionar
accesos directos que eviten tener que buscar el ejecutable en el árbol del sistema de
archivos. Esto es lo que ofrece la siguiente pantalla del asistente.
Al menos es necesario definir un acceso directo hacia la aplicación en el menú Inicio. Esto
se representa mediante el elemento Launch de la lista. Para cada acceso directo nuevo,
puede elegir su emplazamiento, bien en el menú Inicio o en el Escritorio (o los dos).
Observe que, si se añade una carpeta con archivos ejecutables durante la etapa anterior,
estos accesos directos se crean automáticamente hacia esos ejecutables. Si se trata de
simples herramientas que necesita la aplicación, posiblemente sea mejor eliminarlos para
que no se pueda acceder directamente a ellas.
ShareVideos
e. Información del registro
Esta es la penúltima etapa y le permite especificar las modificaciones que se deben realizar
en el registro durante la instalación de la aplicación. Si no existe ninguna clave en el
registro de la máquina durante la implementación, se añade durante la instalación. Es
posible agregar claves debajo de cualquier clave de nivel superior en el editor del registro.
Para agregar una clave en el registro, previamente debe seleccionar un nodo de nivel
superior, o una subclave, y en el menú contextual escoger la opción New - Key. Se debe
volver a nombrar la clave.
Se puede eliminar una clave simplemente con la opción Delete del menú contextual. Sin
embargo, hay que ser prudente, ya que la supresión de una clave conlleva la supresión de
todas las subclaves y valores contenidos en ella. Se visualiza un mensaje de aviso para
alertarle de esta peligrosa situación y para pedirle que confirme su elección.
También es posible especificar valores para las nuevas claves o modificar los valores
existentes. Podrá añadir valores de tipo cadena, binario DWORD, Multi String y
expandable String. Durante la instalación, estos valores están escritos en el registro. Los
valores existentes son sustituidos por valores específicos en el programa de instalación.
En algunos casos, será necesario proporcionar un archivo externo con la información que se
debe visualizar en el cuadro de diálogo. Por ejemplo, este es el caso para la opción que
ShareVideos
controla la visualización del contrato de licencia de la aplicación, que necesita el archivo
con formato .rft que contiene el contrato de licencia.
Actualización de la aplicación
Con un método de despliegue clásico, cuando está disponible una nueva versión de la
aplicación, el usuario debe, en general, reinstalar la aplicación para aprovechar esa
actualización. La tecnología ClickOnce es capaz de facilitar las actualizaciones
automáticamente. En este caso, solo se descargan las partes de la aplicación que han
cambiado, y luego la aplicación completa y actualizada se reinstala automáticamente desde
una nueva carpeta.
Componentes compartidos
Autorización de seguridad
A veces, todas estas exigencias han conducido a los desarrolladores a elegir una tecnología
Web en lugar de aplicaciones Windows clásicas, simplemente para beneficiarse de las
facilidades de implementación de este tipo de aplicaciones. La contrapartida de esta
elección se encuentra en una reactividad menor de la aplicación y en una interfaz de usuario
menos elaborada. La tecnología ClickOnce hace que la implementación de aplicaciones
Windows sea tan sencilla como la implementación de aplicaciones Web. Cualquier
ShareVideos
aplicación de consola o de Windows Formes se puede publicar con ClickOnce. Hay tres
técnicas de publicación disponibles:
Un manifiesto de aplicación.
Un manifiesto de implementación.
ShareVideos
el archivo del manifiesto de implementación disponible en una página Web o en una
carpeta. El usuario solo verá un cuadro de diálogo que le pide confirmar la instalación.
Cuando crea una versión actualizada de la aplicación, también debe generar un nuevo
manifiesto de aplicación y copiar los archivos en la ubicación de la implementación, en
general una carpeta similar a la carpeta de la implementación original. También se debe
actualizar el manifiesto para que apunte hacia la ubicación de la nueva versión de la
aplicación.
Para implementar una aplicación ClickOnce, hay tres estrategias posibles. La estrategia que
elija depende principalmente del tipo de aplicación que va a implementar. Las tres
estrategias son las siguientes:
Esta estrategia permite implementar la aplicación en un servidor Web o una red compartida.
Cuando un usuario final desea instalar la aplicación, debe hacer clic en un icono de una
página Web o doble clic en un icono de archivos compartidos. Luego se descarga, instala y
arranca la aplicación en el ordenador del usuario. Algunos elementos se añaden al menú
Inicio y al grupo Agregar o quitar programas en el Panel de control.
Puesto que esta estrategia depende de la conexión de red, funciona de manera óptima para
las aplicaciones implementadas por usuarios con acceso a una red local o una conexión
rápida a Internet.
ShareVideos
será instalada, lanzada y algunos elementos se agregarán al menú Inicio y al grupo
Agregar o quitar programas en el Panel de control.
Esta estrategia es similar a la primera, excepto por que la aplicación actúa como una
aplicación Web. La aplicación se ejecuta cuando el usuario hace clic en un hipervínculo de
una página Web (o doble clic en un recurso compartido). Cuando los usuarios cierran la
aplicación, esta ya no está disponible en el ordenador local. Ningún elemento se añade al
menú Inicio o al grupo Agregar o quitar programas en el Panel de control.
Técnicamente, la aplicación se descarga e instala en un caché de la aplicación del
ordenador local, de la misma manera que una aplicación Web se descarga en el caché Web.
Como para el caché Web, los archivos son eliminados del caché de la aplicación al final de
la utilización. Sin embargo, el usuario tiene la impresión de que la aplicación se ejecuta
desde la Web o la red compartida.
ShareVideos
Por defecto, la aplicación intenta localizar y leer el archivo manifiesto de implementación
en segundo plano durante su ejecución. Si una actualización está disponible, se invitará al
usuario a descargar e instalar la actualización durante la próxima ejecución.
Esta estrategia se adapta particularmente a las conexiones de banda ancha restringida o a las
aplicaciones voluminosas que puedan necesitar descargas largas.
Esta estrategia se adapta bien a las conexiones de banda ancha. El plazo necesario para
iniciar la aplicación puede ser inaceptable en conexiones que no sean de banda ancha.
Actualizaciones obligatorias
Intervalos de actualización
También es posible hacer que su aplicación no se actualice nunca. Puede, por ejemplo,
implementar una aplicación sencilla que no necesite ser actualizada, pero utilizar la ventaja
que ofrece ClickOnce para su instalación.
ShareVideos
de la implementación no son gestionadas por este asistente y deben configurarse
manualmente a través el cuadro de diálogo de las propiedades del proyecto.
La primera etapa del asistente consiste en configurar la ubicación donde se debe hacer la
publicación.
Un directorio de la máquina.
Un directorio compartido en otra máquina indicando una ruta UNC de la siguiente
manera \\nombre de la máquina\nombre del directorio. Es necesario tener la
autorización de escribir sobre la partición para que la publicación se pueda realizar.
El servidor Web IIS de la máquina en el que previamente se habrá agregado un
directorio virtual para acoger los archivos.
Un servidor FTP cuya información de conexión debe facilitar usando el cuadro de
diálogo siguiente:
Debe indicar:
ShareVideos
Al final de la instalación, se abre una página HTML en la ubicación utilizada durante la
publicación que permite el arranque de la instalación o la ejecución de la aplicación.
El estado de la publicación de cada archivo se puede configurar con tres valores diferentes:
El botón Requisitos previos se utiliza para configurar los elementos necesarios para el
funcionamiento de la aplicación.
Puede optar por crear un programa de instalación para los componentes que requiere el
funcionamiento de la aplicación marcando la casilla Crear programa de instalación para
instalar los componentes necesarios. Se debe elegir los componentes correspondientes en
la lista presentada. También debe indicar desde qué ubicación se instalarán estos
componentes. Hay tres opciones posibles:
ShareVideos
La casilla La aplicación debe buscar actualizaciones especifica que la aplicación debe
verificar la disponibilidad de actualizaciones en el momento de su instalación. Si selecciona
esta opción, las otras opciones estarán disponibles. Permiten elegir el momento en el que
tendrá lugar la verificación de la disponibilidad de una actualización. La opción Antes de
que se inicie la aplicación indica que la aplicación debe verificar la disponibilidad de las
actualizaciones antes del arranque. Esto garantiza que los usuarios conectados a la red
siempre disponen de la versión más reciente de la aplicación. Esta opción puede ralentizar
el arranque de la aplicación en el caso de que existan actualizaciones disponibles. La
opción Después de que se inicie la aplicación planifica la ejecución de la actualización
durante el próximo arranque de la aplicación. La frecuencia de las actualizaciones también
se puede indicar en horas, días o semanas, o bien ejecutarse cada vez que arranca la
aplicación. También puede indicar la ubicación a partir de la cual están disponibles las
actualizaciones, si esta es diferente de la ubicación de instalación.
Idioma de publicación
Especifica el nombre del editor de la aplicación. Si esta zona está vacía, se usará el valor de
la propiedad RegisteredOrganization del ordenador. Si este valor es nulo, se utiliza el
nombre del proyecto utilizado.
Especifica el nombre del editor de la aplicación. Si esta zona está vacía, se utiliza el nombre
del ensamblado.
Especifica un sitio Web que contiene datos de soporte para la aplicación. La especificación
de esta URL es facultativa. Pero si se utiliza, esta URL aparece en la entrada Agregar o
quitar programas de la aplicación en el Panel de control de Windows.
Especifica un nombre para la página Web de implementación. El nombre del archivo por
defecto es Publish.htm.
ShareVideos
Generar automáticamente la página Web de implementación después de cada
publicación
Si esta opción está seleccionada, el proceso de publicación genera una página Web de
implementación en cada publicación. Esta opción solo está disponible si se especifica una
página Web de implementación.
.application
.manifest
.deploy
Por defecto, esta opción está desactivada. Si esta opción está activada, la aplicación será
capaz de acceder y tratar los datos de los parámetros de la URL.
Si esta opción está seleccionada, se añade un archivo Autorun.inf a la raíz del soporte para
las aplicaciones ClickOnce que se instalan desde un CD-Rom o DVD-Rom.
ShareVideos
Comprobar los archivos cargados en un servidor web
Si esta opción está activada, el proceso de publicación descarga cada archivo para verificar
que efectivamente se pueden descargar, y le informará de los archivos que no se pueden
descargar.
Cuando esta opción está seleccionada, puede firmar de nuevo el manifiesto de la aplicación
con la ayuda de un certificado que contiene sus propios datos.
ShareVideos