NET Con Visual Basic 2005 PDF
NET Con Visual Basic 2005 PDF
com
Cursos
www.depurando.com
Te recomendamos tambin que veas la aplicacin MSDN Video, que desarrollaremos al finalizar el curso y de la que podrs consultar su cdigo
fuente y videos explicativos.
www.depurando.com
Cursos
www.depurando.com
En realidad .NET es mucho ms que eso ya que ofrece un entorno gestionado de ejecucin de aplicaciones, nuevos lenguajes de programacin y compiladores, y permite el desarrollo de todo tipo de funcionalidades: desde
programas de consola o servicios Windows hasta aplicaciones para dispositivos mviles, pasando por desarrollos de escritorio o para Internet. Son estos ltimos de los que nos ocuparemos en este curso. Pero antes conviene
conocer los fundamentos en los que se basa cualquier aplicacin creada con
.NET, incluyendo las que nos interesan.
www.depurando.com
ms conocidos son Visual Basic .NET, C# o J#, pero existen implementaciones de todo tipo, incluso de COBOL!.
Lo mejor de todo es que cualquier componente creado con uno de estos lenguajes puede ser utilizado de forma transparente desde cualquier otro lenguaje .NET. Adems, como ya se ha comentado, es posible ejecutar el cdigo .NET en diferentes plataformas y sistemas operativos.
Cmo se consigue esta potente capacidad?
Dentro de la CLI, existe un lenguaje llamado IL (Intermdiate Language o
Lenguaje Intermedio) que est pensado de forma independiente al procesador en el que se vaya a ejecutar. Es algo parecido al cdigo ensamblador pero de ms alto nivel y creado para un hipottico procesador virtual que no
est atado a una arquitectura determinada.
Cuando se compila una aplicacin escrita en un lenguaje .NET cualquiera
(da igual que sea VB, C# u otro de los soportados), el compilador lo que
genera en realidad es un nuevo cdigo escrito en este lenguaje intermedio.
As, todos los lenguajes .NET se usan como capa de ms alto nivel para
producir cdigo IL.
Un elemento fundamental de la CLR es el compilador JIT (justa in time).
Su cometido es el de compilar bajo demanda y de manera transparente el
cdigo escrito en lenguaje intermedio a lenguaje nativo del procesador fsico que va a ejecutar el cdigo.
Al final, lo que se ejecuta es cdigo nativo que ofrece un elevado rendimiento. Esto es cierto tambin para las aplicaciones Web escritas con
ASP.NET y contrasta con las aplicaciones basadas en ASP clsico que eran
interpretadas, no compiladas, y que jams podran llegar al nivel de desempeo que ofrece ASP.NET.
La siguiente figura muestra el aspecto que tiene el cdigo intermedio de una
aplicacin sencilla y se puede obtener usando el desemsamblador que viene
con la plataforma .NET.
Cursos
www.depurando.com
www.depurando.com
Cursos
www.depurando.com
www.depurando.com
10
Cursos
www.depurando.com
Arquitectura de ADO.NET
11
www.depurando.com
te mdulo.
Existen dos capas fundamentales dentro de su arquitectura: la capa conectada y la desconectada.
Capa conectada
La primera de ellas contiene objetos especializados en la conexin con los
orgenes de datos. As, la clase genrica Connection se utiliza para establecer conexiones a los orgenes de datos. La clase Command se encarga de
enviar comandos de toda ndole al origen de datos. Por fin la clase DataReader est especializada en leer los resultados de los comandos mientras
se permanece conectado al origen de datos.
La clase DataAdapter hace uso de las tres anteriores para actuar de puente
entre la capa conectada y la desconectada.
Estas clases son abstractas, es decir, no tienen una implementacin real de
la que se pueda hacer uso directamente. Es en este punto en donde entran en
juego los proveedores de datos. Cada origen de datos tiene un modo especial de comunicarse con los programas que los utilizan, adems de otras
particularidades que se deben contemplar. Un proveedor de datos de
ADO.NET es una implementacin concreta de las clases conectadas abstractas que hemos visto, que hereda de stas y que tiene en cuenta ya todas
las particularidades del origen de datos en cuestin.
As, por ejemplo, las clases especficas para acceder a SQL Server se llaman
SqlConnection, SqlCommand, SqlDataReader y SqlDataAdapter y se encuentran bajo el espacio de nombres System.Data.SqlClient. Es decir, al
contrario que en ADO clsico no hay una nica clase Connection o Com
mand que se use en cada caso, si no que existen clases especializadas para
conectarse y recuperar informacin de cada tipo de origen de datos.
Nota.-
12
Cursos
www.depurando.com
Estos proveedores puente, si bien muy tiles en determinadas circunstancias, ofrecen un rendimiento menor debido a la capa intermedia que estn utilizando (ODBC u OLEDB). Un programador
novel puede sentir la tentacin de utilizar siempre el proveedor
puente para OLEDB y as escribir cdigo compatible con diversos
gestores de datos de forma muy sencilla. Se trata de un error y
siempre que sea posible es mejor utilizar un proveedor nativo.
Capa desconectada
Una vez que ya se han recuperado los datos desde cualquier origen de datos
que requiera una conexin sta ya no es necesaria. Sin embargo sigue siendo necesario trabajar con los datos obtenidos de una manera flexible. Es
aqu cuando la capa de datos desconectada entra en juego. Adems, en muchas ocasiones es necesario tratar con datos que no han sido obtenidos desde un origen de datos relacional con el que se requiera una conexin. A veces nicamente necesitamos un almacn de datos temporal pero que ofrezca
caractersticas avanzadas de gestin y acceso a la informacin.
Por otra parte las conexiones con las bases de datos son uno de los recursos
ms escasos con los que contamos al desarrollar. Su mala utilizacin es la
causa ms frecuente de cuellos de botella en las aplicaciones y de que stas
no escalen como es debido. Esta afirmacin es especialmente importante en
las aplicaciones Web en las que se pueden recibir muchas solicitudes simultneas de cualquier parte del mundo.
Finalmente otro motivo por el que es importante el uso de los datos desconectado de su origen es la transferencia de informacin entre capas de una
aplicacin. stas pueden encontrarse distribuidas por diferentes equipos, e
Visual Studio 2005
13
www.depurando.com
incluso en diferentes lugares del mundo gracias a Internet. Por ello es necesario disponer de algn modo genrico y eficiente de poder transportar los
datos entre diferentes lugares, utilizarlos en cualquiera de ellos y posteriormente tener la capacidad de conciliar los cambios realizados sobre ellos con
el origen de datos del que proceden.
Todo esto y mucho ms es lo que nos otorga el uso de los objetos DataSet.
Es obvio que no se trata de tareas triviales, pero los objetos DataSet estn
pensados y diseados con estos objetivos en mente. Como podremos comprobar ms adelante en este curso es bastante sencillo conseguir estas funcionalidades tan avanzadas y algunas otras simplemente usando de manera
adecuada este tipo de objetos.
Nota.- Otra interesante caracterstica de los DataSet es que permiten gestionar simultneamente diversas tablas (relaciones) de datos, cada
una de un origen diferente si es necesario, teniendo en cuenta las
restricciones y las relaciones existentes entre ellas.
Los DataSet, como cualquier otra clase no sellada de .NET, se pueden extender mediante herencia. Ello facilita una tcnica avanzada que consiste en
crear tipos nuevos de DataSet especializados en la gestin de una informacin concreta (por ejemplo un conjunto de tablas relacionadas). Estas nuevas tipos clases se denominan genricamente DataSet Tipados, y permiten
el acceso mucho ms cmodo a los datos que representan, verificando reglas de negocio, y validaciones de tipos de datos ms estrictas.
Cursos
www.depurando.com
Al contrario que en VB6, .NET proporciona control sobre todos los aspectos de las ventanas y controles, no dejando nada fuera del alcance del programador y otorgando por lo tanto la mxima flexibilidad. Los formularios
(ventanas) son clases que heredan de la clase base Form, y cuyos controles
son miembros de sta. De hecho se trata nicamente de cdigo y no es necesario (aunque s muy recomendable) emplear el diseador grfico de Visual Studio para crearlas.
Visual Studio 2005
15
www.depurando.com
Este es el aspecto que presenta parte del cdigo que genera la interfaz mostrada en la anterior figura:
Figura 1.5
16
Cursos
www.depurando.com
en .NET es necesario crear un objeto antes de poder hacer uso de los formularios:
Dim frm As New MiFormulario
frm.Show()
Todos los controles heredan de una clase Control por lo que conservan una
serie de funcionalidades comunes muy interesantes, como la capacidad de
gestionarlos en el diseador (movindolos, alinendolos...), de definir mrgenes entre ellos o hacer que se adapten al tamao de su contenedor.
17
www.depurando.com
Figura 1.6
Cdigo ASP sencillo que genera una lista de seleccin y saluda al presionar
un botn.
Obviamente se podra haber simplificado sin enviar el formulario al servidor usando JavaScript en el cliente para mostrar el saludo, pero la intencin
es ilustrar la mezcla de cdigo de cliente y de servidor que existe en este tipo de aplicaciones.
18
Cursos
www.depurando.com
No existe separacin entre el diseo y la lgica de las aplicaciones. Si queremos cambiar sustancialmente la apariencia de la
aplicacin Web lo tendremos bastante complicado puesto que el
cdigo del servidor est mezclado entre el HTML.
2.
3.
No disponemos de forma de detectar en el servidor que se ha realizado algo en el cliente. El cliente se encuentra desconectado
desde el momento en que se termina de devolver la pgina. Slo se
recibe informacin en el servidor cuando se solicita una nueva pgina o cuando se enva un formulario tal y como se hace en el
ejemplo, debindonos encargar nosotros de averiguar si la peticin
es la primera vez que se hace o no, y de dar la respuesta adecuada.
En cualquier caso es mucho menos intuitivo que el modelo de respuesta a eventos de una aplicacin de escritorio.
4.
19
www.depurando.com
5.
No existe el concepto de Propiedad de los controles. En una aplicacin Windows asignamos el texto de un campo usando una propiedad (por ejemplo Text1.Text = "Hola") y sta se asigna y permanece en la interfaz sin que tengamos que hacer nada. En una
aplicacin Web clsica tenemos que almacenarlas en algn sitio
(una variable de sesin o un campo oculto) para conservarlas entre
diferentes peticiones de una misma pgina.
6.
Diseadores grficos.
Eventos.
Estado.
Cursos
www.depurando.com
Introduccin
En esta primera leccin veremos los tipos de datos que .NET Framework
pone a nuestra disposicin y cmo tendremos que usarlos desde Visual Basic 2005.
A continuacin daremos un repaso a conceptos bsicos o elementales sobre
los tipos de datos, que si bien nos sern familiares, es importante que lo
veamos para poder comprender mejor cmo estn definidos y organizados
los tipos de datos en .NET.
21
www.depurando.com
Tipos primitivos
x
Variables y constantes
x
x
Arrays (matrices)
x
Declarar arrays
22
Cursos
www.depurando.com
Tipos primitivos
Veamos en la siguiente tabla los tipos de datos definidos en .NET Framework y los alias utilizados en Visual Basic 2005.
Tabla 2.1
Debemos tener en cuenta, al menos si el rendimiento es una de nuestra prioridades, que las cadenas en .NET son inmutables, es decir, una vez que se
han creado no se pueden modificar y en caso de que queramos cambiar el
contenido, .NET se encarga de desechar la anterior y crear una nueva cadena, por tanto si usamos las cadenas para realizar concatenaciones (unin de
cadenas para crear una nueva), el rendimiento ser muy bajo, si bien existe
una clase en .NET que es ideal para estos casos y cuyo rendimiento es superior al tipo String: la clase StringBuilder.
23
www.depurando.com
Las ltimas filas mostradas en la tabla son tipos especiales que si bien son
parte del sistema de tipos comunes (CTS) no forman parte de la Common
Language Specification (CLS), es decir la especificacin comn para los
lenguajes "compatibles" con .NET, por tanto, si queremos crear aplicaciones que puedan interoperar con todos los lenguajes de .NET, esos tipos no
debemos usarlos como valores de devolucin de funciones ni como tipo de
datos usado en los argumentos de las funciones, propiedades o procedimientos.
Los tipos mostrados en la tabla 2.1 son los tipos primitivos de .NET y por
extensin de Visual Basic 2005, es decir son tipos "elementales" para los
cuales cada lenguaje define su propia palabra clave equivalente con el tipo
definido en el CTS de .NET Framework. Todos estos tipos primitivos podemos usarlos tanto por medio de los tipos propios de Visual Basic, los tipos definidos en .NET o bien como literales. Por ejemplo, podemos definir
un nmero entero literal indicndolo con el sufijo I: 12345I o bien asignndolo a un valor de tipo Integer o a un tipo Sytem.Int32 de .NET. La nica
excepcin de los tipos mostrados en la tabla 1 es el tipo de datos Object, este es un caso especial del que nos ocuparemos en la prxima leccin.
Sufijos o caracteres y smbolos identificadores para los tipos
Cuando usamos valores literales numricos en Visual Basic 2005, el tipo de
datos que le asigna el compilador es el tipo Double, por tanto si nuestra intencin es indicar un tipo de datos diferente podemos indicarlos aadiendo
una letra como sufijo al tipo, esto es algo que los ms veteranos de VB6 ya
estarn acostumbrados, e incluso los ms noveles tambin, en Visual Basic
2005 algunos de ellos se siguen usando, pero el tipo asociado es el equivalente al de este nuevo lenguaje (tal como se muestra en la tabla 1), por
ejemplo para indicar un valor entero podemos usar la letra I o el signo %,
de igual forma, un valor de tipo entero largo (Long) lo podemos indicar
usando L o &, en la siguiente tabla podemos ver los caracteres o letra que
podemos usar como sufijo en un literal numrico para que el compilador lo
identifique sin ningn lugar a dudas.
El uso de estos caracteres nos puede resultar de utilidad particularmente para los tipos de datos que no se pueden convertir en un valor doble.
24
Cursos
www.depurando.com
Nota.- Los sufijos pueden indicarse en minsculas, maysculas o cualquier combinacin de mayscula y minscula.
Tabla 2.2
datos
Figura 2.1
25
www.depurando.com
Los tipos por valor son tipos de datos cuyo valor se almacena en la pila o en
la memoria "cercana", como los numricos que hemos visto. Podemos decir
que el acceso al valor contenido en uno de estos tipos es directo, es decir se
almacena directamente en la memoria reservada para ese tipo y cualquier
cambio que hagamos lo haremos directamente sobre dicho valor, de igual
forma cuando copiamos valores de un tipo por valor a otro, estaremos
haciendo copias independientes.
Por otro lado, los tipos por referencia se almacenan en el "monto" (heap) o
memoria "lejana", a diferencia de los tipos por valor, los tipos por referencia
lo nico que almacenan es una referencia (o puntero) al valor asignado. Si
hacemos copias de tipos por referencia, realmente lo que copiamos es la referencia propiamente dicha, pero no el contenido.
Estos dos casos los veremos en breve con ms detalle.
Ver vdeo n 4 Tipos de datos primitivos y vdeo n 5 Tipos por valor y por
referencia.
Variables y constantes
Disponer de todos estos tipos de datos no tendra ningn sentido si no los
pudiramos usar de alguna otra forma que de forma literal. Y aqu es donde
entran en juego las variables y constantes, no vamos a contarte qu son y
para que sirven, salvo en el caso de las constantes, ya que no todos los desarrolladores las utilizamos de la forma adecuada.
Consejo para usar las constantes
Siempre que tengamos que indicar un valor constante, ya sea para indicar el
mximo o mnimo permitido en un rango de valores o para comprobar el
trmino de un bucle, deberamos usar una constante en lugar de un valor literal, de esta forma si ese valor lo usamos en varias partes de nuestro cdigo, si en un futuro decidimos que dicho valor debe ser diferente, nos resultar ms fcil realizar un solo cambio que cambiarlo en todos los sitios en
26
Cursos
www.depurando.com
los que lo hemos usado, adems de que de esta forma nos aseguramos de
que el cambio se realiza adecuadamente y no tendremos que preocuparnos
de las consecuencias derivadas de no haber hecho el cambio en todos los sitios que deberamos.
Las constantes se definen utilizando la instruccin Const seguida del nombre, opcionalmente podemos indicar el tipo de datos y por ltimo una asignacin con el valor que tendr. Como veremos en la siguiente seccin, podemos obligar a VB2005 a que en todas las constantes (y variables) que declaremos, tengamos que indicar el tipo de datos.
Para declarar una constante lo haremos de la siguiente forma:
Const maximo As Integer = 12345678
Declarar variables
La declaracin de las variables en Visual Basic 2005 se hace por medio de
la instruccin Dim seguida del nombre de la constante y del tipo de datos
que esta contendr. Con una misma instruccin Dim podemos declarar ms
de una variable, incluso de tipos diferentes, tal como veremos a continuacin.
La siguiente lnea de cdigo declara una variable de tipo entero:
Dim i As Integer
Tal como hemos comentado, tambin podemos declarar en una misma lnea
ms de una variable:
Dim a, b, c, As Integer
En este caso, las tres variables las estamos definiendo del mismo tipo, que
es el indicado al final de la declaracin.
Nota.- Como hemos comentado, en Visual Basic 2005 se pueden declarar
las constantes y variables sin necesidad de indicar el tipo de datos
que contendrn, pero debido a que eso no es una buena prctica, a
Visual Studio 2005
27
www.depurando.com
lo largo de este curso siempre declararemos las variables y constantes con el tipo de datos adecuado a su uso.
Declarar variables y asignar el valor inicial
En Visual Basic 2005 tambin podemos inicializar una variable con un valor distinto al predeterminado, que en los tipos numricos es un cero, en las
fechas es el 1 de enero del ao 1 a las doce de la madrugada (#01/01/0001
12:00:00AM#) y en la cadenas es un valor nulo (Nothing), para hacerlo,
simplemente tenemos que indicar ese valor, tal como veremos es muy parecido a como se declaran las constantes. Por ejemplo:
Dim a As Integer = 10
En esa misma lnea podemos declarar y asignar ms variables, pero todas
deben estar indicadas con el tipo de datos:
Dim a As Integer = 10, b As Integer = 25
Por supuesto, el tipo de datos puede ser cualquiera de los tipos primitivos:
Dim a As Integer
10, b As Integer
25, s As String
"Hola"
Aunque para que el cdigo sea ms legible, y fcil de depurar, no deberamos mezclar en una misma instruccin Dim ms de un tipo de datos.
Nota.- Es importante saber que en las cadenas de Visual Basic 2005 el valor de una variable de tipo String no inicializada NO es una cadena
vaca, sino un valor nulo (Nothing).
El tipo de datos Char
En Visual Basic 2005 podemos declarar valores de tipo Char, este tipo de
datos es un carcter Unicode y podemos declararlo y asignarlo a un mismo
tiempo. El problema con el que nos podemos encontrar es a la hora de indicar un carcter literal.
28
Cursos
www.depurando.com
Podemos convertir un valor numrico en un carcter o bien podemos convertir un carcter en su correspondiente valor numrico.
Dim c As Char
c = Chr(65)
Dim n As Integer
n = Asc(c)
En Visual Basic 2005 los tipos Char se pueden asignar a variables de tipo
String y se har una conversin automtica sin necesidad de utilizar funciones de conversin.
Si nuestra intencin es asignar un valor Char a una variable, adems de la
funcin Chr, podemos hacerlo con un literal, ese valor literal estar encerrado entre comillas dobles, (al igual que una cadena), aunque para que
realmente sea un carcter debemos agregarle una c justo despus del cierre
de las comillas dobles:
Dim c As Char = Ac
Obligar a declarar las variables con el tipo de datos
Visual Basic 2005 nos permite, (lamentablemente de forma predeterminada), utilizar las variables y constantes sin necesidad de indicar el tipo de datos de estas, pero, como comentbamos al principio, podemos obligar a que
nos avise cuando no lo estamos haciendo, ya que como decamos en la nota,
es una buena costumbre indicar siempre el tipo de datos que tendrn nuestras variables y constantes.
Esa obligatoriedad la podemos aplicar a todo el proyecto o a un mdulo en
particular, para ello tenemos que usar la instruccin Option Strict On, una
vez indicado, se aplicar a todo el cdigo, no solo a las declaraciones de variables, constantes o al tipo de datos devuelto por las funciones y propiedades, sino tambin a las conversiones y asignaciones entre diferentes tipos de
datos.
29
www.depurando.com
No debemos confundir Option Strict con Option Explicit, este ltimo, sirve
para que siempre tengamos que declarar todas las variables, mientras que el
primero lo que hace es obligarnos a que esas declaraciones tengan un tipo
de datos.
Tanto una como la otra tienen dos estados: conectado o desconectado dependiendo de que agreguemos On u Off respectivamente.
Insistimos en la recomendacin de que siempre debemos "conectar" estas
dos opciones, si bien Option Explicit On ya viene como valor por defecto,
cosa que no ocurre con Option Strict, que por defecto est desconectado.
Aplicar Option Strict On a un fichero en particular
Cuando agregbamos un nuevo fichero a nuestro proyecto de Visual Basic
2005 si ya tenemos predefinida las opciones "estrictas", como es el caso de
Option Explicit On, estas no se aadirn a dicho fichero, (en un momento
veremos cmo hacerlo para que siempre estn predefinidas), pero eso no
significa que no se aplique, aunque siempre podemos escribir esas instrucciones (con el valor On al final) en cada uno de los ficheros de cdigo que
agreguemos a nuestro proyecto. Si nos decidimos a aadirlas a los ficheros,
esas lneas de cdigo deben aparecer al principio del fichero y solamente
pueden estar precedidas de comentarios.
En la figura 2.1 mostrada en la leccin anterior, tenemos una captura del
editor de Visual Basic 2005 en la que hemos indicado que queremos tener
comprobacin estricta.
Aplicar Option Strict On a todo el proyecto
Tambin podemos hacer que Option Strict funcione igual que Option Expli
cit, es decir, que est activado a todo el proyecto, en este caso no tendramos que indicarlo en cada uno de los ficheros de cdigo que formen parte
de nuestro proyecto, si bien solamente ser aplicable a los que no tengan
esas instrucciones, aclaremos esto ltimo: si Option Strict (u Option Expli
cit) est definido de forma global al proyecto, podemos desactivarlo en
cualquiera de los ficheros, para ello simplemente habra que usar esas declaraciones pero usando Off en lugar de On. De igual forma, si ya est definido
30
Cursos
www.depurando.com
Figura 2.2
De la lista despegable Option Strict, seleccionamos On. Por defecto ya estarn seleccionadas las opciones On de Option Explicit y Binary de Option Compare, por tanto no es necesario realizar ningn cambio ms, para
aceptar los cambios y cerrar el cuadro de dilogo, presionamos en el botn
Aceptar.
Visual Studio 2005
31
www.depurando.com
Figura 2.3
Desde este momento el compilador de VB se volver estricto en todo lo relacionado a las declaraciones de variables y conversiones, tal como vemos
en la figura 2.4 al intentar declarar una variable sin indicar el tipo de datos.
Nota.-
32
Cursos
www.depurando.com
Figura 2.4
33
www.depurando.com
Figura 2.5
34
Cursos
www.depurando.com
Figura 2.6
2.
35
www.depurando.com
Indicando el atributo FlagsAttibute, (realmente no hace falta indicar el sufijo Attribute cuando usamos los atributos) de esta forma
podremos usar los valores de la enumeracin para indicar valores
que se pueden "sumar" o complementar entre s, pero sin perder el
nombre, en breve veremos qu significa esto de "no perder el nombre".
<Flags()>
Enum Colores As Byte
Rojo = 1
Verde = 2
Azul = 4
End Enum
Nota.- Los atributos los veremos con ms detalle en otra leccin de este
mismo mdulo.
El nombre de los miembros de las enumeraciones
Tanto si indicamos o no el atributo Flags a una enumeracin, la podemos
usar de esta forma:
Dim c As Colores = Colores.Azul Or Colores.Rojo
Es decir, podemos "sumar" los valores definidos en la enumeracin. Antes
de explicar con detalle que beneficios nos puede traer el uso de este atributo, veamos una caracterstica de las enumeraciones.
Como hemos comentado, las enumeraciones son constantes con nombres,
pero en Visual Basic 2005 esta definicin llega ms lejos, de hecho, podemos saber "el nombre" de un valor de una enumeracin, para ello tendremos
que usar el mtodo ToString, (el cual se usa para convertir en una cadena
cualquier valor numrico).
36
Cursos
www.depurando.com
37
www.depurando.com
Por tanto, podemos pensar que podemos usar cualquier valor para
asignar a una variable declarada como una enumeracin, al menos si ese
valor est dentro del rango adecuado.
En Visual Basic 2005 esto no es posible, al menos si lo hacemos de forma
"directa" y con Option Strict conectado, ya que recibiremos un error indicndonos que no podemos convertir, por ejemplo, un valor entero en un valor del tipo de la enumeracin. En la figura 2.8 podemos ver ese error al intentar asignar el valor 3 a una variable del tipo Colores (definida con el tipo
predeterminado Integer).
Figura 2.8
38
Cursos
www.depurando.com
El error nos indica que no podemos realizar esa asignacin, pero el entorno
integrado de Visual Studio 2005 tambin nos ofrece alternativas para que
ese error no se produzca, esa ayuda se obtiene presionando en el signo de
admiracin que tenemos justo donde est el cursor del mouse, pero no solo
nos dice cmo corregirlo, sino que tambin nos da la posibilidad de que el
propio IDE se encargue de corregirlo, tal como podemos apreciar en la figura 2.9.
Lo nico que tendramos que hacer es presionar en la sugerencia de correccin, que en este caso es la nica que hay, pero en otros casos pueden ser
varias las opciones y tendramos que elegir la que creamos adecuada.
El cdigo final (una vez corregido) quedara de la siguiente forma:
Dim c As Colores = CType(3, colores)
CType es una de las formas que nos ofrece Visual Basic 2005 de hacer conversiones entre diferentes tipos de datos, en este caso convertimos un valor
entero en uno del tipo Colores.
Si compilamos y ejecutamos la aplicacin, sta funcionar correctamente.
Aunque sabemos que es posible que usando CType no asignemos un valor
dentro del rango permitido. En este caso, el valor 3 podramos darlo por
bueno, ya que es la suma de 1 y 2 (Rojo y Verde), pero que pasara si el
valor asignado es, por ejemplo, 15? En teora no deberamos permitirlo.
Visual Studio 2005
39
www.depurando.com
2.
Usando funciones especficas del tipo Enum. Aunque en este ltimo caso, solo podremos comprobar los valores definidos en la
enumeracin.
Arrays (matrices)
Los arrays (o matrices) nos permitirn agrupar valores que de alguna forma
queremos que estn relacionados entre si.
40
Cursos
www.depurando.com
41
www.depurando.com
Para que quede claro que el lmite inferior debe ser cero, en Visual Basic
2005 podemos usar la instruccin 0 To para indicar el valor mximo del ndice superior, ya que, tal como podemos comprobar si vemos 0 To 10, quedar claro que nuestra intencin es declarar un array con 11 elementos, o al
menos nuestro cdigo resultar ms legible:
Dim nombres (0 To 10) As String
Declarar e inicializar un array
En Visual Basic 2005 tambin podemos inicializar un array al declararlo,
para ello debemos poner los valores a asignar dentro de un para de llaves,
tal como vemos en el siguiente ejemplo:
Dim nombres() As String = {Pepe, Juan, Luisa}
Con el cdigo anterior estamos creando un array de tipo String con tres valores cuyos ndices van de cero a dos.
En este caso, cuando iniciamos el array al declararlo, no debemos indicar el
nmero de elementos que tendr ese array, ya que ese valor lo averiguar el
compilador cuando haga la asignacin. Tampoco es vlido indicar el nmero de elementos que queremos que tenga y solo asignarle unos cuantos menos (o ms), ya que se producir un error en tiempo de compilacin.
Si el array es bidimensional (o con ms dimensiones), tambin podemos
inicializarlos al declararlo, pero en este caso debemos usar doble juego de
llaves:
Dim nombres(,) As String = {{Juan, Pepe}, {Ana, Eva}}
En este cdigo tendramos un array bidimensional con los siguientes valores:
nombres(0,0)= Juan
nombres(0,1)= Pepe
nombres(1,0)= Ana
42
Cursos
www.depurando.com
nombres(1,1) = Eva
Como podemos ver en la declaracin anterior, si definimos arrays con ms
de una dimensin, debemos indicarlas usando una coma para separar cada
dimensin, o lo que es ms fcil de recordar: usando una coma menos del
nmero de dimensiones que tendr el array. En los valores a asignar, usaremos las llaves encerradas en otras llaves, segn el nmero de dimensiones.
Aunque, la verdad, es que hay algunas veces hay que hacer un gran esfuerzo
mental para asociar los elementos con los ndices que tendrn en el array,
por tanto, algunas veces puede que resulte ms legible si intentamos o agrupamos esas asignaciones, tal como vemos en el siguiente cdigo:
Dim nomTri(,,) As String =
{
{{Juan, Pepe}, {Luisa, Eva}}
{{A, B}, {C, D}}
}
Console.WriteLine(nomTri(0, 0, 0)) Juan
Console.WriteLine(nomTri(0, 0, 1)) Pepe
Console.WriteLine(nomTri(0, 1, 0)) Luisa
Console.WriteLine(nomTri(0, 1, 1)) Eva
Console.WriteLine(nomTri(1, 0, 0)) A
Console.WriteLine(nomTri(1, 0, 1)) B
Console.WriteLine(nomTri(1, 1, 0)) C
Console.WriteLine(nomTri(1, 1, 1)) D
Tal como podemos comprobar, as es ms legible. Por suerte tenemos el carcter del guin bajo para continuar lneas de cdigo.
Cambiar el tamao de un array
Para cambiar el tamao de un array, usaremos la instruccin ReDim, esta
instruccin solo la podemos usar para cambiar el tamao de un array previamente declarado, no para declarar un array, ya que siempre hay que declarar previamente los arrays antes de cambiarles el tamao.
43
www.depurando.com
ReDim nombres(3)
nombres(0) = Juan
nombres(1) = Pepe
La mayor utilidad de esta instruccin, es que podemos cambiar el tamao de
un array y mantener los valores que tuviera anteriormente, para lograrlo debemos usar ReDim Preserve.
ReDim Preserve nombres(3)
nombres(2) = Ana
nombres(3) = Eva
En este ejemplo, los valores que ya tuviera el array nombres, se seguiran
manteniendo, y se asignaran los nuevos.
Si bien tanto ReDim como ReDim Preserve se pueden usar en arrays de
cualquier nmero de dimensiones, en los arrays de ms de una dimensin
solamente podemos cambiar el tamao de la ltima dimensin.
Eliminar el contenido de un array
Una vez que hemos declarado un array y le hemos asignado valores, es posible que nos interese eliminar esos valores de la memoria, para lograrlo,
podemos hacerlo de tres formas:
1.
2.
3.
44
Cursos
www.depurando.com
45
www.depurando.com
Cursos
www.depurando.com
Clases y estructuras
Introduccin
En la leccin anterior (El sistema de tipos) vimos los tipos de datos predefinidos en .NET Framework, en esta leccin veremos cmo podemos crear
nuestros propios tipos de datos, tanto por valor como por referencia.
Tambin tendremos ocasin de ver los distintos niveles de accesibilidad que
podemos aplicar a los tipos, as como a los distintos miembros de esos tipos
de datos. De los distintos miembros que podemos definir en nuestros tipos,
nos centraremos en las propiedades para ver en detalle los cambios que han
sufrido con respecto a VB6. Tambin veremos temas relacionados con la
programacin orientada a objetos (POO) en general y de forma particular
los que ataen a las interfaces.
47
www.depurando.com
48
Cursos
www.depurando.com
La encapsulacin nos permite abstraer la forma que tiene de actuar una clase sobre los datos que contiene o manipula, para poder lograrlo se exponen
como parte de la clase los mtodos y propiedades necesarios para que podamos manejar esos datos sin tener que preocuparnos cmo se realiza dicha
manipulacin.
El polimorfismo es una caracterstica que nos permite realizar ciertas acciones o acceder a la informacin de los datos contenidos en una clase de forma semi-annima, al menos en el sentido de que no tenemos porqu saber
sobre que tipo objeto realizamos la accin, ya que lo nico que nos debe
preocupar es que podemos hacerlo, por la sencilla razn de que estamos
usando ciertos mecanismos que siguen unas normas que estn adoptadas por
la clase.
El ejemplo clsico del polimorfismo es que si tengo un objeto que "sabe"
cmo morder, da igual que lo aplique a un ratn o a un dinosaurio, siempre
y cuando esas dos "clases" expongan un mtodo que pueda realizar esa accin... y como deca la documentacin de Visual Basic 5.0, siempre ser
preferible que nos muerda un ratn antes que un dinosaurio.
Object: La clase base de todas las clases de .NET
Todas las clases de .NET se derivan de la clase Object, es decir, lo indiquemos o no, cualquier clase que definamos tendr el comportamiento
heredado de esa clase. El uso de la clase Object como base del resto de las
clases de .NET es la nica excepcin a la herencia simple soportada por
.NET, ya que de forma implcita, todas las clases de .NET se derivan de la
clase Object independientemente de que estn derivadas de cualquier otra.
Esta caracterstica nos asegura que siempre podremos usar un objeto del tipo Object para acceder a cualquier clase de .NET, aunque no debemos
abrumarnos todava, ya que en el texto que sigue veremos con ms detalle
que significado tiene esta afirmacin.
De los miembros que tiene la clase Object debemos resaltar el mtodo ToS
tring, el cual ya lo vimos en la leccin anterior cuando queramos convertir
un tipo primitivo en una cadena. Este mtodo est pensado para devolver
una representacin en formato cadena de un objeto. El valor que obtengamos al usar este mtodo depender de cmo est definido en cada clase y
Visual Studio 2005
49
www.depurando.com
Cursos
www.depurando.com
Enumeraciones
Campos
51
www.depurando.com
Propiedades
Eventos
52
Cursos
www.depurando.com
Si bien cada uno de ellos tienen su propia "semntica", tal como podemos
ver a continuacin:
mbito
Es el alcance que la definicin de un miembro o tipo puede tener. Es decir,
cmo podemos acceder a ese elemento y desde dnde podemos accederlo.
El mbito de un elemento de cdigo est restringido por el "sitio" en el que
lo hemos declarado. Estos sitios pueden ser:
x
Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora.
53
www.depurando.com
Por ejemplo, podemos declarar miembros privados a una clase, en ese caso,
dichos miembros solamente los podremos acceder desde la propia clase, pero no desde fuera de ella.
Nota.- Al declarar una variable con Dim, por regla general, el mbito que
le estamos aplicando es privado, pero como veremos, en Visual
Basic 2005, dependiendo del tipo en el que declaremos esa variable, el mbito puede ser diferente a privado.
Miembros compartidos
Por otro lado, los miembros compartidos de una clase o tipo, son elementos
que no pertenecen a una instancia o copia en memoria particular, sino que
pertenecen al propio tipo y por tanto siempre estn accesibles o disponibles,
dentro del nivel del mbito y accesibilidad que les hayamos aplicado, y su
tiempo de vida es el mismo que el de la aplicacin.
Del mbito, la accesibilidad y los miembros compartidos nos ocuparemos
con ms detalle en una leccin posterior, donde veremos ciertas peculiaridades, como puede ser la limitacin del mbito de un miembro que aparen
temente tiene una accesibilidad no restringida.
Parmetros y parmetros opcionales
En Visual Basic 2005, tanto los miembros de una clase, (funciones y mtodos Sub), como las propiedades pueden recibir parmetros. Esos parmetros
pueden estar explcitamente declarados, de forma que podamos indicar
cuantos argumentos tendremos que pasar al mtodo, tambin podemos declarar parmetros opcionales, que son parmetros que no hace falta indicar
al llamar a la funcin o propiedad, y que siempre tendrn un valor predeterminado, el cual se usar en caso de que no lo indiquemos. Adems de los
parmetros especficos y opcionales, podemos usar un array de parmetros
opcionales, en los que se puede indicar un nmero variable de argumentos
al llamar a la funcin que los define, esto lo veremos en la siguiente seccin.
54
Cursos
www.depurando.com
55
www.depurando.com
56
Cursos
www.depurando.com
57
www.depurando.com
lo podramos haber hecho ms al "estilo .NET", ya que, como sabemos todos los arrays de .NET realmente se derivan de la clase Array:
Nota.- Cuando queramos usar ParamArray para recibir un array de parmetros opcionales, esta instruccin debe ser la ltima de la lista de
parmetros de la funcin (mtodo).
Tampoco se permite tener parmetros opcionales y ParamArray en
la misma funcin.
Sobrecarga de mtodos y propiedades
La sobrecarga de funciones (realmente de mtodos y propiedades), es una
caracterstica que nos permite tener una misma funcin con diferentes tipos
de parmetros, ya sea en nmero o en tipo.
Supongamos que queremos tener dos funciones (o ms) que nos permitan
hacer operaciones con diferentes tipos de datos, y que, segn el tipo de datos usado, el valor que devuelva sea de ese mismo tipo.
En este ejemplo, tenemos dos funciones que se llaman igual pero una recibe
valores de tipo entero y la otra de tipo decimal:
Como podemos comprobar las dos funciones tienen el mismo nombre, pero
tanto una como otra reciben parmetros de tipos diferentes.
Con Visual Basic 2005 podemos sobrecargar funciones, pero lo interesante
no es que podamos hacerlo, sino cmo podemos usar esas funciones. En el
cdigo anterior tenemos dos funciones llamadas Suma, la primera acepta
dos parmetros de tipo Integer y la segunda de tipo Double. Lo interesante
es que cuando queramos usarlas, no tenemos que preocuparnos de cual va58
Cursos
www.depurando.com
mos a usar, ya que ser el compilador el que decida la ms adecuada al cdigo que usemos, por ejemplo:
El compilador de Visual Basic 2005 es el que decide que funcin usar, esa
decisin la toma a partir de los tipos de parmetros que hayamos indicado.
En el segundo ejemplo de uso, el que mejor coincide es el de los dos parmetros de tipo Double.
Tambin podemos tener sobrecarga usando una cantidad diferente de parmetros, aunque stos sean del mismo tipo. Por ejemplo, podemos aadir esta declaracin al cdigo anterior sin que exista ningn tipo de error, ya que
esta nueva funcin recibe tres parmetros en lugar de dos:
Figura 2.10
59
www.depurando.com
Si tenemos esta declaracin adems de las anteriores, el programa no compilar, ya que si hacemos una llamada a la funcin Suma con dos parmetros enteros, el compilador no sabr si usar esta ltima o la primera que declaramos, por tanto producir un error.
Parmetros por valor y parmetros por referencia
Al igual que tenemos dos tipos de datos diferentes, en los parmetros de las
funciones tambin podemos tenerlos, para ello tendremos que usar ByVal o
ByRef para indicar al compilador cmo debe tratar a los parmetros.
Cuando un parmetro es por valor (ByVal), el runtime antes de llamar a la
funcin hace una copia de ese parmetro y pasa la copia a la funcin, por
tanto cualquier cambio que hagamos a ese parmetro dentro de la funcin
no afectar al valor usado "externamente".
En el caso de que el parmetro sea por referencia (ByRef), el compilador pasa una referencia que apunta a la direccin de memoria en la que estn los
datos, por tanto si realizamos cambios dentro de la funcin, ese cambio si
que se ver reflejado en el parmetro usado al llamar a la funcin.
Nota.- Hay que tener en cuenta que si pasamos un objeto a una funcin,
da igual que lo declaremos por valor o por referencia, ya que en
ambos casos se pasa una referencia a la direccin de memoria en la
que estn los datos, porque, como sabemos, las variables de los tipos por referencia siempre contienen una referencia a los datos, no
los datos en s.
60
Cursos
www.depurando.com
Con esta lnea de cdigo lo que estamos indicando a Visual Basic es que tenemos intencin de usar una variable llamada c para acceder a una clase de
tipo Cliente. Esa variable, cuando llegue el momento de usarla, sabr todo
lo que hay que saber sobre una clase Cliente, pero hasta que no tenga una
"referencia" a un objeto de ese tipo no podremos usarla.
Visual Studio 2005
61
www.depurando.com
O tambin:
Cursos
www.depurando.com
63
www.depurando.com
Teniendo esta declaracin de la clase Cliente, podemos crear nuevos clientes de dos formas:
64
Cursos
www.depurando.com
65
www.depurando.com
Cursos
www.depurando.com
de un mtodo, cuando ese mtodo termina, el objeto se destruye, (hay algunas excepciones a esta ltima regla, como puede ser que ese mismo objeto
tambin est referenciado por otra variable externa al mtodo.)
Lo que debemos tener muy presente es que en .NET los objetos no se destruyen inmediatamente. Esto es as debido a que en .NET existe un "sistema" que se encarga de realizar esta gestin de limpieza: El recolector de basura o de objetos no usados (Garbage Collector, GC). Este recolector de objetos no usados se encarga de comprobar constantemente cuando un objeto
no se est usando y es el que decide cuando hay que llamar al destructor.
Debido a esta caracterstica de .NET, si nuestra clase hace uso de recursos
externos que necesiten ser eliminados cuando el objeto ya no se vaya a seguir usando, debemos definir un mtodo que sea el encargado de realizar
esa liberacin, pero ese mtodo debemos llamarlo de forma manual, ya que,
aunque en .NET existen formas de hacer que esa llamada sea automtica,
nunca tenderemos la seguridad de que se llame en el momento oportuno, y
esto es algo que, segn que casos, puede ser un inconveniente.
Recomendacin.-
67
www.depurando.com
sual Basic 2005 a los tipos por valor definidos por el usuario se llaman estructuras.
Las estructuras pueden contener los mismos miembros que las clases, aunque algunos de ellos se comporten de forma diferente o al menos tengan algunas restricciones, como que los campos definidos en las estructuras no se
pueden inicializar al mismo tiempo que se declaran o no pueden contener
constructores "simples", ya que el propio compilador siempre se encarga de
crearlo, para as poder inicializar todos los campos definidos.
Otra de las caractersticas de las estructuras es que no es necesario crear una
instancia para poder usarlas, ya que es un tipo por valor y los tipos por valor
no necesitan ser instanciados para que existan.
Definir una estructura
Las estructuras se definen usando la palabra Structure seguida del nombre y
acaba usando las instrucciones End Structure.
El siguiente cdigo define una estructura llamada Punto en la que tenemos
dos campos pblicos.
Aunque en las estructuras, usar New, sera algo redundante y por tanto no
necesario.
68
Cursos
www.depurando.com
Nota.- Tanto en las estructuras como en las clases podemos tener constructores compartidos, (Shared), en el caso de las estructuras, este
tipo de constructor es el nico que podemos declarar sin parmetros.
Destructores de las estructuras
69
www.depurando.com
Debido a que las estructuras son tipos por valor y por tanto una variable declarada con un tipo por valor "contiene el valor en si misma", no podemos
destruir este tipo de datos, lo ms que conseguiramos al asignarle un valor
nulo (Nothing) sera eliminar el contenido de la variable, pero nunca podemos destruir ese valor. Por tanto, en las estructuras no podemos definir destructores.
Los miembros de una estructura
Como hemos comentado, los miembros o elementos que podemos definir en
una estructura son los mismos que ya vimos en las clases. Por tanto aqu veremos las diferencias que existen al usarlos en las estructuras.
Campos
Como vimos, las variables declaradas a nivel del tipo, son los campos, la
principal diferencia con respecto a las clases, es que los campos de una estructura no pueden inicialiarse en la declaracin y el valor que tendrn inicialmente es un valor "nulo", que en el caso de los campos de tipo numricos es un cero. Por tanto, si necesitamos que los campos tengan algn valor
inicial antes de usarlos, deberamos indicarlo a los usuarios de nuestra estructura y proveer un constructor que realice las inicializaciones correspondientes, pero debemos recordar que ese constructor debe tener algn parmetro, ya que el predeterminado sin parmetros no podemos "reescribirlo".
Los nicos campos que podemos inicializar al declararlos son los campos
compartidos, pero como tendremos oportunidad de ver, estos campos sern
accesibles por cualquier variable declarada y cualquier cambio que realicemos en ellos se ver reflejado en el resto de "instancias" de nuestro tipo.
Mtodos y otros elementos
El resto de los miembros de una estructura se declaran y usan de la misma
forma que en las clases, si bien debemos tener en cuenta que el modificador
de accesibilidad predeterminado para los miembros de una estructura es Pu
blic, (incluso si son campos declarados con Dim).
70
Cursos
www.depurando.com
Otro detalle a tener en cuenta es que en una estructura siempre debe existir
al menos un evento o un campo no compartido, no se permiten estructuras
en las que solo tienen constantes, mtodos y/o propiedades, estn o no compartidos.
Cmo usar las estructuras
Tal como hemos comentado las estructuras son tipos por valor, para usar los
tipos por valor no es necesario instanciarlos explcitamente, ya que el mero
hecho de declararlos indica que estamos creando un nuevo objeto en memoria. Por tanto, a diferencia de las clases o tipos por referencia, cada variable
definida como un tipo de estructura ser independiente de otras variables
declaradas, aunque no las hayamos instanciado.
Esta caracterstica de las estructuras nos permite hacer copias "reales" no
copia de la referencia (o puntero) al objeto en memoria como ocurre con los
tipos por referencia. Vemoslos con un ejemplo.
En este trozo de cdigo definimos e instanciamos una variable del tipo Punto, a continuacin declaramos otra variable del mismo tipo y le asignamos
la primera, si estos tipos fuesen por referencia, tanto una como la otra estaran haciendo referencia al mismo objeto en memoria, y cualquier cambio
realizado a cualquiera de las dos variables afectaran al mismo objeto, pero
en el caso de las estructuras (y de los tipos por valor), cada cambio que realicemos se har sobre un objeto diferente, por tanto la asignacin del valor
200 al campo X de la variable p1 solo afecta a esa variable, dejando intacto
el valor original de la variable p.
Ver vdeo 20 Estructuras.
Accesibilidad y mbito
71
www.depurando.com
Tal y como comentamos anteriormente, dependiendo de dnde y cmo estn declarados los tipos de datos y los miembros definidos en ellos, tendremos o no acceso a esos elementos.
Recordemos que el mbito es el alcance con el que podemos acceder a un
elemento y depende de dnde est declarado, por otro lado, la accesibilidad
depende de cmo declaremos cada uno de esos elementos.
mbito
Dependiendo de donde declaremos un miembro o un tipo, ste tendr mayor
alcance o cobertura, o lo que es lo mismo, dependiendo del mbito en el que
usemos un elemento, podremos acceder a l desde otros puntos de nuestro
cdigo. A continuacin veremos con detalle los mbitos en los que podemos
declarar los distintos elementos de Visual Basic 2005.
x
mbito de bloque: Disponible nicamente en el bloque de cdigo en el que se ha declarado. Por ejemplo, si declaramos una variable dentro de un bucle For o un If Then, esa variable solo estar
accesible dentro de ese bloque de cdigo.
72
Cursos
www.depurando.com
73
www.depurando.com
cdigo interno, como es el caso del bucle For, en el que nuevamente declaramos una variable llamada i, que nada tiene que ver con el resto de variables declaradas con el mismo nombre en los otros bloques.
Lo nico que no podemos hacer en cualquiera de esos bloques, es declarar
una variable llamada n, ya que al estar declarada en el procedimiento, el
compilador de Visual Basic 2005 nos indicar que no podemos ocultar una
variable previamente definida fuera del bloque, tal como podemos ver en la
figura 2.12.
Esta restriccin solo es aplicable a las variables declaradas en el procedimiento, ya que si declaramos una variable a nivel de mdulo, no habr ningn problema para usarla dentro de un bloque, esto es as porque en un procedimiento podemos declarar variables que se llamen de la misma forma
que las declaradas a nivel de mdulo, aunque stas ocultarn a las del "nivel" superior.
Figura 2.12
mbito de procedimiento
Las variables declaradas en un procedimiento tendrn un mbito o cobertura
que ser el procedimiento en el que est declaradas, y como hemos visto,
ese mbito incluye tambin cualquier bloque de cdigo declarado dentro del
procedimiento. Estas variables ocultarn a las que se hayan declarado fuera
del procedimiento, si bien, dependiendo del tipo de mdulo, podremos acceder a esas variables "externas" indicando el nombre completo del mdulo
o bien usando la instruccin Me, tal como vimos en el cdigo del constructor parametrizado de la estructura Punto.
74
Cursos
www.depurando.com
En este ejemplo, el hecho de que una variable est declarada con la letra
ENE en mayscula o en minscula no implica ninguna diferencia, ya que
Visual Basic 2005 no hace distinciones de este tipo; an as, Visual Basic
2005 respetar el nombre segn lo hemos escrito y no cambiar automticamente el "case" de las variables, salvo cuando estn en el mismo nivel de
mbito, es decir, si la variable nombre que hemos definido en la funcin
Mostrar la volvemos a usar dentro de esa funcin, Visual Basic 2005 la seguir escribiendo en minsculas, pero si escribimos "nombre" fuera de esa
funcin, VB se dar cuenta de que hay una variable declarada con la ENE
en maysculas y automticamente la cambiar a Nombre, aunque nosotros
la escribamos de otra forma.
mbito de mdulo
Cuando hablamos de mdulos, nos estamos refiriendo a un "tipo" de datos,
ya sea una clase, una estructura o cualquier otro tipo de datos que nos permita definir .NET. En estos casos, las variables declaradas dentro de un tipo
de datos sern visibles desde cualquier parte de ese tipo, siempre teniendo
en cuenta las restricciones mencionadas en los casos anteriores.
mbito de espacio de nombres
Los espacios de nombres son los contenedores de tipos de datos de mayor
nivel, y sirven para contener definiciones de clases, estructuras, enumeraciones y delegados. Cualquier tipo definido a nivel de espacio de nombres
estar disponible para cualquier otro elemento definido en el mismo espacio
Visual Studio 2005
75
www.depurando.com
de nombres. Al igual que ocurre en el resto de mbitos "inferiores", si definimos un tipo en un espacio de nombres, podemos usar ese mismo nombre
para nombrar a un procedimiento o a una variable, en cada caso se aplicar
el mbito correspondiente y, tal como vimos anteriormente, tendremos que
usar nombres nicos para poder acceder a los nombres definidos en niveles
diferentes
La palabra clave Global
En Visual Basic 2005 podemos definir espacios de nombres cuyos nombres
sean los mismos que los definidos en el propio .NET Framework, para evitar conflictos de mbitos, podemos usar la palabra clave Global para acceder a los que se han definido de forma "global" en .NET. Por ejemplo, si tenemos el siguiente cdigo en el que definimos una clase dentro de un espacio de nombres llamado System y queremos acceder a uno de los tipos definidos en el espacio de nombres System de .NET, tendremos un problema:
El problema es que el compilador de
Visual Basic 2005 nos indicar que el
tipo Int32 no est definido, ya que intentar buscarlo dentro del mbito
que actualmente tiene, es decir, la declaracin que nosotros hemos hecho de System, por tanto para poder acceder
al tipo Int32 definido en el espacio de nombres "global" System de .NET
tendremos que usar la instruccin Global, por suerte el IDE de Visual Studio 2005 reconoce este tipo de error y nos ofrece ayuda para poder solventar
el conflicto, tal como vemos en la figura 2.13:
Figura 2.13 Ayuda del IDE en los conflictos de espacios nombres globales
76
Cursos
www.depurando.com
Nota.- Afortunadamente este conflicto con los espacios de nombres no ser muy habitual para los desarrolladores que usemos el idioma de
Cervantes, por la sencilla razn de que los espacios de nombres de
.NET Framework suelen estar definidos usando palabras en ingls.
Accesibilidad
La accesibilidad es la caracterstica que podemos aplicar a cualquiera de los
elementos que definamos en nuestro cdigo. Dependiendo de la accesibilidad declarada tendremos distintos tipos de accesos a esos elementos.
Los modificadores de accesibilidad que podemos aplicar a los tipos y elementos definidos en nuestro cdigo pueden ser cualquiera de los mostrados
en la siguiente lista:
x
Public: Acceso no restringido. Este es modificador de accesibilidad con mayor "cobertura", podemos acceder a cualquier miembro
pblico desde cualquier parte de nuestro cdigo. Aunque, como veremos, este acceso no restringido puede verse reducido dependiendo de dnde lo usemos.
Protected Friend: Acceso limitado al proyecto actual o a los tipos derivados de la clase contenedora. Una mezcla de los dos modificadores anteriores.
77
www.depurando.com
Estos modificadores de accesibilidad los podemos usar tanto en clases, estructuras, interfaces, enumeraciones, delegados, eventos, mtodos, propiedades y campos. Aunque no sern aplicables en espacios de nombres (Na
mespace) ni clases de tipo Module, en estos dos casos siempre tendrn cobertura pblica, si bien no se permite el uso de ningn modificador.
Accesibilidad a las variables en los procedimientos
Las variables declaradas dentro de un procedimiento solo son accesibles dentro de ese procedimiento, en este caso solo se puede aplicar el mbito privado, aunque no podremos usar la instruccin Private, sino Dim o Static.
Nota.- La palabra clave Static, nos permite definir una variable privada (o
local) al procedimiento para que mantenga el valor entre diferentes
llamadas a ese procedimiento; esto contrasta con el resto de variables declaradas en un procedimiento cuya duracin es la misma
que la vida del propio procedimiento, por tanto, las variables no estticas pierden el valor al terminar la ejecucin del procedimiento.
Las accesibilidades predeterminadas
La accesibilidad de una variable o procedimiento en la que no hemos indicado el modificador de accesibilidad depender del sitio en el que la hemos
declarado.
Por ejemplo, en las estructuras si definimos los campos usando Dim, estos
tendrn un mbito igual que si le hubisemos aplicado el modificador Pu
blic; sin embargo, esa misma variable declarada en una clase (Class o Mo
dule) tendr una accesibilidad Private. As mismo, si el elemento que declaramos es un procedimiento y no indicamos el modificador de mbito, ste
tendr un mbito de tipo Public si lo definimos en una estructura y si el lugar en el que lo declaramos es una clase (o Module), ste ser Friend.
En la siguiente tabla tenemos la accesibilidad predeterminada de cada tipo
(clase, estructura, etc.), as como de las variables declaradas con Dim y de
los procedimientos en los que no se indican el modificador de accesibilidad.
78
Cursos
www.depurando.com
Tabla 2.3
79
www.depurando.com
Cursos
www.depurando.com
81
www.depurando.com
Cursos
www.depurando.com
nombre corto para acceder a las clases contenidas en un espacio de nombres, por ejemplo, si queremos indicar de forma explcita las clases de un
espacio de nombres como el de Microsoft.VisualBasic, podemos hacerlo de
esta forma:
De esta forma podemos usar el "alias" vb para acceder a las clases y dems
tipos definidos en ese espacio de nombres.
En las figuras 2.14 2.15 podemos ver las dos formas de acceder a las clases
del espacio de ese espacio de nombres, en el primer caso sin usar un alias y
en el segundo usando el alias vb.
Figura 2.14
83
www.depurando.com
Figura 2.15
Propiedades
Las propiedades son los miembros de los tipos que nos permiten acceder a
los datos que dicho tipo manipula. Normalmente una propiedad est relacionada con un campo, de forma que el campo sea el que realmente contenga el valor y la propiedad simplemente sea una especie de mtodo a travs
del cual podemos acceder a ese valor.
Debido a que el uso de las propiedades realmente nos permite acceder a los
valores de una clase (o tipo), se suelen confundir los campos con las propiedades, de hecho si definimos una variable pblica en una clase, sta se
comporta de manera similar, pero realmente un campo (o variable) pblico
no es una propiedad, al menos en el sentido de que el propio .NET Framework no lo interpreta como tal, aunque en la prctica nos puede parecer que
es as, ya que se utilizan de la misma forma. Pero no debemos dejarnos llevar por la comodidad y si no queremos perder funcionalidad, debemos diferenciar en nuestro cdigo las propiedades de los campos.
Lo primero que debemos tener presente es que gracias a esta diferenciacin
que hace .NET Framework, podemos poner en prctica una de las caractersticas de la programacin orientada a objetos: la encapsulacin, de forma,
que la manipulacin de los datos que una clase contiene siempre se deben
hacer de forma "interna" o privada a la clase, dejando a las propiedades la
posibilidad de que externamente se manipulen, de forma controlada, esos
datos. De esta forma tendremos mayor control sobre cmo se acceden o se
asignan los valores a esos datos, ya que al definir una propiedad, tal como
hemos comentado, realmente estamos definiendo un procedimiento con el
cual podemos controlar cmo se acceden a esos datos.
Definir una propiedad
84
Cursos
www.depurando.com
Debido a que una propiedad realmente nos permite acceder a un dato que la
clase (o estructura) manipula, siempre tendremos un campo relacionado con
una propiedad. El campo ser el que contenga el valor y la propiedad ser la
que nos permita manipular ese valor.
En Visual Basic 2005, las propiedades las declaramos usando la instruccin
Property y la definicin de la misma termina con End Property, dentro de
ese bloque de cdigo tenemos que definir otros dos bloques: uno se usar a
la hora de leer el valor de la propiedad (bloque Get), y el otro cuando queremos asignar un valor a la propiedad (bloque Set).
El bloque que nos permite acceder al valor de la propiedad estar indicado
por la instruccin Get y acaba con End Get, por otra parte, el bloque usado
para asignar un valor a la propiedad se define mediante la instruccin Set y
acaba con End Set.
Veamos como definir una propiedad en Visual Basic 2005:
Como podemos comprobar tenemos dos bloques de cdigo, el bloque Get que es el que se usa cuando
queremos acceder al valor de la
propiedad, por tanto devolvemos el
valor del campo privado usado para
almacenar ese dato. El bloque Set
es el usado cuando asignamos un
valor a la propiedad, este bloque tiene definido un parmetro (value) que
representa al valor que queremos asignar a la propiedad.
Propiedades de solo lectura
En Visual Basic 2005 podemos hacer que una propiedad sea de solo lectura, de for
ma que el valor que representa no pueda ser cambiado.
Para definir este tipo de propiedades solo debemos indicar el bloque Get de la pro
piedad, adems de indicar de forma expresa que esa es nuestra intencin, para ello
debemos usar el modificador ReadOnly para que el compilador de Visual Basic
2005 acepte la declaracin:
85
www.depurando.com
Cursos
www.depurando.com
Nota.- El nivel de accesibilidad de los bloques Get o Set debe ser igual o
inferior que el de la propiedad, por tanto si la propiedad la declaramos como Private, no podemos definir como pblico los bloques
Get o Set.
Propiedades predeterminadas
Las propiedades predeterminadas son aquellas en las que no hay que indicar
el nombre de la propiedad para poder acceder a ellas, pero en Visual Basic
2005 no podemos definir como predeterminada cualquier propiedad, ya que
debido a como se realizan las asignaciones de objetos en .NET, siempre debemos indicar la propiedad a la que queremos asignar el valor, porque en
caso de que no se indique ninguna, el compilador interpretar que lo que
queremos asignar es un objeto y no un valor a una propiedad. Para evitar
conflictos o tener que usar alguna instruccin "extra" para que se sepa si lo
que queremos asignar es un valor o un objeto, en Visual Basic 2005 las propiedades predeterminadas siempre deben ser parametrizadas, es decir, tener
como mnimo un parmetro. Para indicar que una propiedad es la propiedad
por defecto lo debemos hacer usando la instruccin Default:
Como vemos en este ejemplo, una propiedad por defecto puede ser de solo
lectura y tambin de solo escritura o de lectura/escritura.
Para usar esta propiedad, al ser la propiedad por defecto, no es necesario indicar el nombre de la propiedad, aunque si as lo deseamos podemos indicarla, aunque en este caso no tendra mucha utilidad el haberla definido como propiedad por defecto:
87
www.depurando.com
Incluso como vemos en este cdigo una de las sobrecargas puede ser de solo lectura y la otra de lectura/escritura. Lo que realmente importa es que el
nmero o tipo de parmetros de cada sobrecarga sea diferente.
Las propiedades predeterminadas tienen sentido en Visual Basic 2005
cuando queremos que su uso sea parecido al de un array. Por tanto es habitual que las clases de tipo coleccin sean las ms indicadas para definir propiedades por defecto. Aunque no siempre el valor devuelto debe ser un elemento de una coleccin o array, ya que podemos usar las propiedades predeterminadas para acceder a los miembros de una clase "normal", de forma
que se devuelva un valor segn el parmetro indicado, esto nos permitira,
por ejemplo, acceder a los miembros de la clase desde un bucle For. Si definimos una propiedad predeterminada como en el siguiente cdigo:
88
Cursos
www.depurando.com
Interfaces
Las interfaces son un elemento bastante importante en .NET Framework, ya
que de hecho se utiliza con bastante frecuencia, en esta leccin veremos que
son las interfaces y como utilizarlas en nuestros proyectos, tambin veremos
que papel juegan en .NET y cmo aplicar algunas de las definidas en la biblioteca base.
Qu es una interfaz?
Las interfaces son una forma especial de una clase, aunque la diferencia
principal con las clases es que las interfaces no contienen cdigo ejecutable,
solo definen los miembros.
Las interfaces se utilizan para indicar el "comportamiento" que tendr una
clase, o al menos qu miembros debe definir esa clase.
89
www.depurando.com
Para definir una interfaz en Visual Basic 2005 tenemos que usar la instruccin Interface seguida del nombre de la interfaz y terminar la declaracin
con End Interface:
90
Cursos
www.depurando.com
2.
Los miembros de las interfaces siempre son pblicos, tal como indicbamos en la tabla 2.3.
91
www.depurando.com
Como podemos apreciar, no solo ha aadido las definiciones de cada miembro de la interfaz, sino que tambin aade cdigo extra a cada uno de esos
92
Cursos
www.depurando.com
93
www.depurando.com
2.
Cursos
www.depurando.com
Es decir, lo nico que tendramos que hacer es indicar la otra implementacin separndola con una coma.
Dnde podemos implementar las interfaces?
Para ir acabando este tema nos queda por saber, entre otras cosas, dnde
podemos implementar las interfaces, es decir, en que tipos de datos podemos usar Implements.
La implementacin de interfaces la podemos hacer en las clases (Class), estructuras (Structure) y en otras interfaces (Interface).
Debido a que una interfaz puede implementar otras interfaces, si en una clase implementamos una interfaz que a su vez implementa otras, esa clase
tendr definidas cada una de las interfaces, lo mismo ocurre con una clase
Visual Studio 2005
95
www.depurando.com
que "se derive" de otra clase que implementa alguna interfaz, la nueva clase
tambin incorporar esa interfaz.
Nota.- Cuando una interfaz implementa otras interfaces, stas no se pueden indicar mediante Implements, en lugar de usar esa instruccin
debemos usar Inherits.
Public Interface IPrueba2
Inherits IMostrar
Si en una clase implementamos una interfaz que a su vez implementa otras
interfaces, esa clase tendr definiciones de todos los miembros de todas las
interfaces, por ejemplo, si tenemos la siguiente definicin de la interfaz
IPrueba2 que "implementa" la interfaz IMostrar:
96
Cursos
www.depurando.com
Figura 2.16
97
www.depurando.com
98
Cursos
www.depurando.com
Manejo de excepciones
Es indiscutible que por mucho que nos lo propongamos, nuestras aplicaciones no estarn libres de errores, y no nos referimos a errores sintcticos, ya
que, afortunadamente, el IDE (Integrated Development Envirnment, entorno
de desarrollo integrado) de Visual Basic 2005 nos avisar de cualquier error
sintctico e incluso de cualquier asignacin no vlida (al menos si tenemos
activado Option Strict On), pero de lo que no nos avisar, como es lgico,
ser de los errores que se produzcan en tiempo de ejecucin. Para estos casos, Visual Basic pone a nuestra disposicin el manejo de excepcione, veamos pues cmo utilizarlo, sobre todo el sistema de excepciones estructuradas que es el recomendable para cualquier desarrollo con .NET Framework.
Manejo de excepciones
En Visual Basic 2005 el tratamiento de errores (excepciones) podemos
hacerlo de dos formas distintas, dependiendo de que utilicemos el tratamiento de errores heredado de versiones anteriores o el recomendado para
la plataforma .NET: el control de errores estructurado, con idea de hacerlo
de una forma ms "ordenada".
En esta leccin solamente veremos cmo tratar los errores de forma estructurada, porque, como hemos comentado es la forma recomendada de hacerlo en .NET Framework.
Manejo de excepciones no estructuradas
Como acabamos de comentar, no trataremos o explicaremos cmo trabajar
con el tratamiento de errores no estructurados, pero al menos queremos
hacer una aclaracin para que no nos llevemos una sorpresa si nos decidimos a usarlo:
Visual Studio 2005
99
www.depurando.com
No podemos usar los dos sistemas de tratamiento de errores al mismo tiempo, por lo menos en un mismo mtodo o propiedad, o utilizamos On Error o
utilizamos Try/Catch. De todas formas, si escribimos nuestro cdigo con el
IDE (entorno integrado) de Visual Studio 2005, ste nos avisar de que no
podemos hacer esa mezcla.
Manejo de excepciones estructuradas
Las excepciones en Visual Basic 2005 las podemos controlar usando las
instrucciones Try / Catch / Finally. Estas instrucciones realmente son bloques de instrucciones, al estilo de If / Else. Cuando queramos controlar una
parte del cdigo que puede producir un error lo incluimos dentro del bloque
Try, si se produce un error, ste lo podemos detectar en el bloque Catch, por
ltimo, independientemente de que se produzca o no una excepcin, podemos ejecutar el cdigo que incluyamos en el bloque Finally, para indicar el
final del bloque de control de excepciones lo haremos con End Try.
Cuando creamos una estructura de control de excepciones no estamos obligados a usar los tres bloques, aunque el primero: Try si es necesario, ya que
es el que le indica al compilador que tenemos intencin de controlar los
errores que se produzcan. Por tanto podemos crear un "manejador" de excepciones usando los tres bloques, usando Try y Catch o usando Try y Fina
lly.
Veamos ahora con ms detalle cada uno de estos bloques y que es lo que
podemos hacer en cada uno de ellos.
Bloque Try
En este bloque incluiremos el cdigo en el que queremos comprobar los
errores. El cdigo a usar ser un cdigo normal, es decir, no tenemos que
hacer nada en especial, ya que en el momento que se produzca el error se
usar (si hay) el cdigo del bloque Catch.
Bloque Catch
Si se produce una excepcin, sta la capturamos en un bloque Catch.
100
Cursos
www.depurando.com
En el bloque Catch podemos indicar que tipo de excepcin queremos capturar, para ello usaremos una variable de tipo Exception, la cual pude ser del
tipo de error especfico que queremos controlar o de un tipo genrico.
Por ejemplo, si sabemos que nuestro cdigo puede producir un error al trabajar con ficheros, podemos usar un cdigo como este:
Aunque si no vamos usar la variable indicada en el bloque Catch, pero queremos que no se detenga la aplicacin cuando se produzca un error, podemos hacerlo de esta forma:
101
www.depurando.com
Es importante tener en cuenta que cuando se produce un error y usamos varios bloques Catch, Visual Basic buscar la captura que mejor se adapte al
error que se ha producido, pero siempre lo har examinando los diferentes
bloques Catch que hayamos indicado empezando por el indicado despus
del bloque Try, por tanto deberamos poner las ms genricas al final, de
forma que siempre nos aseguremos de que las capturas de errores ms especficas se intercepten antes que las genricas.
Evaluacin condicional en un bloque Catch
Adems de indicar la excepcin que queremos controlar, en un bloque
Catch podemos aadir la clusula When para evaluar una expresin. Si la
evaluacin de la expresin indicada despus de When devuelve un valor
verdadero, se procesar el bloque Catch, en caso de que devuelva un valor
falso, se ignorar esa captura de error.
Esto nos permite poder indicar varios bloques Catch que detecten el mismo
error, pero cada una de ellas puede tener diferentes expresiones indicadas
con When.
En el siguiente ejemplo, se evala el bloque Catch solo cuando el valor de
la variable y es cero, en otro caso se utilizar el que no tiene la clusula
When:
Bloque Finally
En este bloque podemos indicar las instrucciones que queremos que se ejecuten, se produzca o no una excepcin. De esta forma nos aseguramos de
102
Cursos
www.depurando.com
103
www.depurando.com
Eventos y delegados
La forma que tienen nuestras clases y estructuras de comunicar que algo est ocurriendo, es por medio de eventos. Los eventos son mensajes que se
lanzan desde una clase para informar al "cliente" que los utiliza de que est
pasando algo.
Seguramente estaremos acostumbrados a usarlos, incluso sin tener una nocin consciente de que se tratan de eventos, o bien porque es algo tan habitual que no le prestamos mayor atencin, es el caso de las aplicaciones de
escritorio, cada vez que presionamos un botn, escribimos algo o movemos
el mouse se estn produciendo eventos.
El compilador de Visual Basic 2005 nos facilita mucho la creacin de los
eventos y "esconde" todo el proceso que .NET realmente hace "en la sombra". Ese trabajo al que nos referimos est relacionado con los delegados,
una palabra que suele aparecer en cualquier documentacin que trate sobre
los eventos.
Y es que, aunque VB2005 nos oculte, o facilite, el trabajo con los eventos,
stos estn estrechamente relacionados con los delegados. En esta leccin
veremos que son los delegados y que relacin tienen con los eventos, tambin veremos que podemos tener mayor control sobre cmo se interceptan
los eventos e incluso cmo y cuando se asocian los eventos en la aplicacin
cliente, aunque primero empezaremos viendo cmo declarar y utilizar eventos en nuestros tipos de datos.
Eventos
Como hemos comentado en la introduccin, en Visual Basic 2005 podemos
usar los eventos de una forma bastante sencilla, al menos si la comparamos
104
Cursos
www.depurando.com
con otros lenguajes de la familia .NET. En las secciones que siguen veremos cmo utilizar los eventos que producen las clases de .NET, empezaremos con ver cmo utilizar los eventos de los formularios, que con toda seguridad sern los que estamos ms acostumbrados a usar. Tambin veremos
las distintas formas que tenemos de asociar un mtodo con el evento producido por un control (que al fin y al cabo es una clase).
Interceptar los eventos de los controles de un formulario
Debido a que an no hemos visto el mdulo dedicado a las aplicaciones de Win
dows, en las que se utilizan los "clsicos" formularios, no vamos a entrar en detalles
sobre cmo crear un formulario ni como aadir controles, etc., todo eso lo veremos
en el siguiente mdulo. Para simplificar las cosas, veremos cmo se interceptan en
un formulario de la nueva versin de Visual Basic, aunque sin entrar en demasiados
detalles.
La forma ms sencilla de asociar el evento de un control con el cdigo que se usar,
es haciendo doble pulsacin en el control cuando estamos en modo de diseo; por
ejemplo, si en nuestro formulario tenemos un botn, al hacer doble pulsacin sobre
l tendremos asociado el evento Click del botn, ya que ese es el evento predetermi
nado de los controles Button, y desde el diseador de formularios de Windows, al
realizar esa doble pulsacin, siempre se muestra el evento predeterminado del con
trol en cuestin.
Lo primero que podemos notar es que en Visual Basic 2005 utiliza dos argumentos, esto siempre es as en todos los eventos producidos por los controles. El primero indica el control que produce el evento, (en nuestro ejemplo sera una referencia al control Button1), y el segundo normalmente conVisual Studio 2005
105
www.depurando.com
Figura 2.17
Cursos
www.depurando.com
hay ninguna relacin directa entre ese nombre y el evento que queremos interceptar.
Tal como resaltamos en la nota anterior, en Visual Basic 2005, el nombre
asociado a un evento puede ser el que queramos, lo realmente importante es
que indiquemos la instruccin Handles seguida del evento que queremos interceptar. Aunque, como veremos a continuacin, tambin hay otras formas
de "relacionar" los eventos con el mtodo usado para recibir la notificacin.
Formas de asociar los eventos con un control
Cuando estamos trabajando con el diseador de formularios, tenemos tres
formas de asociar un evento con el cdigo correspondiente:
La forma ms sencilla es la expuesta anteriormente, es decir, haciendo doble click en el control, esto har que se muestre el evento predeterminado
del control. En el caso del control Button, el evento predeterminado es el
evento Click.
Si queremos escribir cdigo para otros eventos podemos hacerlo de tres
formas, aunque la primera que explicaremos no ser la ms habitual, ya que
debemos saber exactamente qu parmetros utiliza el evento.
Asociar el evento manualmente por medio de Handles
Con esta forma, simplemente escribimos el nombre del procedimiento (puede ser cualquier nombre), indicamos los dos argumentos que recibe: el primero siempre es de tipo Object y el segundo depender del tipo de evento, y
finalmente por medio de la clusula Handles lo asociamos con el control y
el evento en cuestin.
Asociar el evento desde la ventana de cdigo
En Visual Basic 2005 tambin podemos seleccionar los eventos disponibles
de una lista desplegable. Esto lo haremos desde la ventana de cdigo. En la
parte superior derecha tenemos una la lista con los controles que hemos
aadido al formulario, seleccionamos el control que nos interese y en la lista
que hay a su izquierda tenemos los eventos que ese control produce. Por
Visual Studio 2005
107
www.depurando.com
tanto podemos seleccionar de esa lista de eventos el que nos interese interceptar, tal como podemos ver en la figura 2.18
Figura 2.18
De esta forma el propio IDE ser el que cree el "esqueleto" del procedimiento de evento usando los parmetros adecuados.
Asociar el evento desde el diseador de formularios
Figura 2.19 Ventana de propiedades con los eventos del
control seleccionado
La tercera forma de asociar un evento con un control, es hacerlo desde el diseador de formularios.
En la ventana de propiedades del control, (tal como podemos apreciar en la figura 2.19), tenemos
una lista con los eventos ms importantes de cada
control, seleccionando el evento de esa lista y
haciendo doble-click en el que nos interese, conseguiremos exactamente el mismo resultado que
con el paso anterior.
Asociar varios eventos a un mismo procedimiento
Cuando utilizamos Handles para asociar eventos, podemos indicar que un
mismo procedimiento sirva para interceptar varios eventos. Veamos un caso
prctico en el que tenemos varios controles de tipo TextBox y queremos que
108
Cursos
www.depurando.com
Figura 2.20
109
www.depurando.com
Cursos
www.depurando.com
Delegados
Como hemos comentado anteriormente, los eventos son acciones que una
clase puede producir cuando ocurre algo. De esta forma podemos notificar a
las aplicaciones que hayan decidido interceptar esos mensajes para que tomen las acciones que crean conveniente.
Visual Basic 2005 esconde al desarrollador prcticamente todo lo que ocurre cada vez que definimos, lanzamos o interceptamos un evento, nosotros
solo vemos una pequea parte de todo el trabajo que en realidad se produce,
y el que no lo veamos no quiere decir que no est ocurriendo. Tambin es
cierto que no debe preocuparnos demasiado si no sabemos lo que est pasando, pero si somos consciente de que es lo que ocurre, puede que nos
ayude a comprender mejor todo lo relacionado con los eventos.
Qu ocurre cuando se asigna y se produce un evento?
Intentemos ver de forma sencilla lo que ocurre "por dentro" cada vez que
definimos un mtodo que intercepta un evento y cmo hace el Visual Basic
para comunicarse con el receptor de dicho evento.
1.
111
www.depurando.com
2.
3.
Cuando usamos la instruccin RemoveHandler, le estamos indicando al evento que elimine de la lista el mtodo indicado en esa
instruccin, de esta forma, la prxima vez que se produzca el evento, solo se llamar a los mtodos que actualmente estn en la lista.
Cuando definimos un evento, realmente estamos definiendo un delegado, (que en el fondo es una clase con un tratamiento especial),
y un mtodo del mismo tipo que el delegado.
2.
112
Cursos
www.depurando.com
3.
Cuando se produce el evento, (por medio de RaiseEvent), realmente estamos llamando al delegado para que acceda a todas las "direcciones" de memoria que tiene almacenadas y ejecute el cdigo
que hayamos definido en cada uno de esos mtodos.
113
www.depurando.com
Si seguimos buscando ms informacin sobre los delegados en la documentacin de Visual Basic 2005, tambin nos encontramos con esta definicin:
"Los delegados habilitan escenarios que en otros lenguajes se han
resuelto con punteros a funcin. No obstante, a diferencia de los
punteros a funcin, los delegados estn orientados a objetos y
proporcionan seguridad de tipos."
Que es lo que comentamos en la seccin anterior: los delegados nos facilitan el acceso a "punteros" (o direcciones de memoria) de funciones, pero
hecho de una forma "controlada", en este caso por el propio .NET framework.
Por ejemplo, el evento DatosCambiados definido anteriormente, tambin
lo podemos definir de la siguiente forma:
Es decir, el mtodo que intercepte este evento debe ser del tipo Sub y no recibir ningn parmetro.
Si nuestro evento utiliza, por ejemplo, un parmetro de tipo String, la definicin del delegado quedara de la siguiente forma:
114
Cursos
www.depurando.com
Como podemos comprobar, Visual Basic 2005 nos permite definir los eventos de dos formas distintas: definiendo un delegado y un evento que sea del
tipo de ese delegado o definiendo el evento con los argumentos que debemos usar.
Declaremos como declaremos los eventos, los podemos seguir usando de la
misma forma, tanto para producirlo mediante RaiseEvent como para definir
el mtodo que reciba ese evento.
Utilizar un delegado para acceder a un mtodo
Ahora veamos brevemente cmo usar los delegados, en este caso sin necesidad de que defina un evento.
Como hemos comentado, un delegado realmente es una clase que puede
contener una referencia a un mtodo, adems define el prototipo del mtodo
que podemos usar como referencia. Sabiendo esto, podemos declarar una
variable del tipo del delegado y por medio de esa variable acceder al mtodo que indiquemos, siempre que ese mtodo tenga la misma "firma" que el
delegado. Parece complicado verdad? Y no solo lo parece, es que realmente lo es. Comprobemos esta "complicacin" por medio de un ejemplo. En
este cdigo, que iremos mostrando poco a poco, vamos a definir un delegado, un mtodo con la misma firma para que podamos usarlo desde una variable definida con el mismo tipo del delegado.
Definimos un delegado de tipo Sub que recibe un valor de tipo cadena:
115
www.depurando.com
Ahora vamos a declarar una variable para que acceda a ese mtodo.
Para ello debemos declararla con el mismo tipo del delegado:
La variable saludando es del mismo tipo que el delegado Saludo. La cuestin es cmo o que asignamos a esta variable?
Primer intento: Como hemos comentado, los delegados realmente son clases, por tanto podemos usar New Saludo y, segn parece, deberamos pasarle un nombre como argumento. Algo as:
Pero esto no funciona, entre otras cosas, porque hemos comentado que un
delegado contiene (o puede contener) una referencia a un mtodo, y "Pepe"
no es un mtodo ni una referencia a un mtodo.
Segundo intento: Por lgica y, sobre todo, por sentido comn, mxime
cuando hemos declarado un mtodo con la misma "firma" que el delegado,
deberamos pensar que lo que debemos pasar a esa variable es el mtodo, ya
que un delegado puede contener una referencia a un mtodo.
Pues tampoco.
Para usar un delegado debemos indicarle la direccin de memoria de un mtodo, a eso se refiere la definicin que vimos antes, una referencia a un mtodo no es ni ms ni menos que la direccin de memoria de ese mtodo. Y
en Visual Basic, desde la versin 5.0, tenemos una instruccin para obtener
la direccin de memoria de cualquier mtodo: AddressOf. Por tanto, para
116
Cursos
www.depurando.com
indicarle al delegado dnde est ese mtodo tendremos que usar cualquiera
de estas dos formas:
117
www.depurando.com
118
Cursos
www.depurando.com
Esto es todo lo que necesitamos hacer en Visual Basic 2005 para definir un
evento.
Como podemos comprobar es muy sencillo, ya que solo tenemos que usar la
instruccin Event. Aunque detrs del teln ocurren otras cosas de las que, al
menos en principio, no debemos preocuparnos, ya que es el propio compilador de Visual Basic 2005 el que se encarga de esos "pequeos detalles".
Producir un evento en nuestra clase
Para producir un evento en nuestra clase, y de esta forma notificar a quin
quiera interceptarlo, simplemente usaremos la instruccin RaiseEvent seguida del evento que queremos producir. Cuando escribimos esa instruccin
en el IDE de Visual Basic 2005, nos mostrar los distintos eventos que podemos producir, tal como vemos en la figura 2.21:
Figura 2.21
119
www.depurando.com
Figura 2.22
Cursos
www.depurando.com
En este caso, el uso de AddressOf es una forma "fcil" que tiene Visual Basic 2005 de asociar un procedimiento de evento con el evento. Aunque por
el fondo, (y sin que nos enteremos), realmente lo que estamos usando es un
constructor a un delegado.
La ventaja de usar esta forma de asociar eventos con el procedimiento, es
que podemos hacerlo con variables que no estn declaradas con WithEvents,
realmente esta sera la nica forma de asociar un procedimiento de evento
con una variable que no hemos declarado con WithEvents.
Desasociar eventos mediante RemoveHandler
De la misma forma que por medio de AddHandler podemos asociar un procedimiento con un evento, usando la instruccin RemoveHandler podemos
hacer el proceso contrario: desligar un procedimiento del evento al que previamente estaba asociado. Los parmetros a usar con RemoveHandler son
los mismos que con AddHandler.
Podemos usar RemoveHandler tanto con variables y eventos definidos con
AddHandler como con variables declaradas con WithEvents y ligadas por
medio de Handles. Esto ltimo es as porque cuando nosotros definimos los
procedimientos de eventos usando la instruccin Handles, es el propio Visual Basic el que internamente utiliza AddHandler para ligar ese procedimiento con el evento en cuestin. Saber esto nos facilitar comprender mejor cmo funciona la declaracin de eventos mediante la instruccin Cus
tom, aunque de este detalle nos ocuparemos despus de ver que son los delegados.
Ver vdeos 30 Delegados 2 y 31 Delegados 3.
121
www.depurando.com
sual Studio 2005, tambin tiene esta caracterstica, pero aunque pueda parecer extrao, es menos potente que la de VB2005; por medio de esta declaracin, tal como indicamos en el ttulo de la seccin, tendremos mayor informacin sobre cmo se declara el evento, cmo se destruye e incluso cmo
se produce, es lo que la documentacin de Visual Basic llama evento personalizado (Custom Event).
Cuando declaramos un evento usando la instruccin Custom estamos definiendo tres bloques de cdigo que nos permite interceptar el momento en
que se produce cualquiera de las tres acciones posibles con un evento:
1.
2.
3.
Para declarar este tipo de evento, siempre debemos hacerlo por medio de un
delegado.
Veamos un ejemplo de una declaracin de un evento usando Custom Event:
Cursos
www.depurando.com
Atributos
Esta es la definicin que nos da la ayuda de Visual Basic sobre lo que es un
atributo.
Los atributos son etiquetas descriptivas que proporcionan infor
macin adicional sobre elementos de programacin como tipos,
campos, mtodos y propiedades. Otras aplicaciones, como el com
pilador de Visual Basic, pueden hacer referencia a la informacin
adicional en atributos para determinar cmo pueden utilizarse es
tos elementos.
En esta leccin veremos algunos ejemplos de cmo usarlos en nuestras propias aplicaciones y, aunque sea de forma general, cmo usar y aplicar algunos de los atributos definidos en el propio .NET Framework, al menos los
que ms directamente nos pueden interesar a los desarrolladores de Visual
Basic.
Atributos
Como hemos comentado en la introduccin, los atributos son etiquetas que
podemos aplicar a nuestro cdigo para que el compilador y, por extensin,
el propio .NET Framework los pueda usar para realizar ciertas tareas o para
obtener informacin extra sobre nuestro cdigo.
De hecho en cualquier aplicacin que creemos con Visual Basic 2005 estaremos tratando con atributos, aunque nosotros ni nos enteremos, ya que el
propio compilador los utiliza para generar los metadatos del ensamblado, es
decir, la informacin sobre todo lo que contiene el ejecutable o librera que
hemos creado con Visual Basic 2005.
Visual Studio 2005
123
www.depurando.com
Por otra parte, el uso de los atributos nos sirve para ofrecer cierta funcionalidad extra a nuestro cdigo, por ejemplo, cuando creamos nuestros propios
controles, mediante atributos podemos indicarle al diseador de formularios
si debe mostrar ciertos miembros del control en la ventana de propiedades,
etc.
Atributos para representar informacin de nuestra aplicacin
De forma ms genrica podemos usar los atributos para indicar ciertas caractersticas de nuestra aplicacin, por ejemplo, el ttulo, la versin, etc. Todos estos atributos los indicaremos como "caractersticas" de nuestra aplicacin, y lo haremos sin ser demasiados conscientes de que realmente estamos
usando atributos, ya que el propio Visual Basic los controla mediante propiedades de la aplicacin.
Por ejemplo, si mostramos la ventana de propiedades de nuestro proyecto,
ver figura 2.24:
Cursos
www.depurando.com
extra, como la versin, el copyright, etc. podemos presionar el botn "Assembly Information", al hacerlo, se mostrar una nueva ventana en la que
podemos escribir esa informacin, tal como mostramos en la figura 2.25:
125
www.depurando.com
Figura 2.26
En este cdigo podemos resaltar tres cosas: La primera es que tenemos una
importacin al espacio de nombres System.Reflection, este espacio de
nombres contiene la definicin de las clases/atributos utilizados para indicar
los atributos de la aplicacin, como el ttulo, etc. La segunda es la forma de
usar los atributos, estos deben ir encerrados entre signos de menor y mayor:
<Assembly: ComVisible(False)>. La tercera es que, en este caso, los atributos estn definidos a nivel de ensamblado, para ellos se aade la instruccin Assembly: al atributo. Como veremos a continuacin, los atributos
tambin pueden definirse a nivel local, es decir, solo aplicable al elemento
en el que se utiliza, por ejemplo, una clase o un mtodo, etc.
Mostrar los ficheros ocultos del proyecto
Como acabamos de comentar, el fichero AssemblyInfo.vb que es el que
contiene la informacin sobre la aplicacin (o ensamblado), est oculto. Para mostrar los ficheros ocultos, debemos hacer lo siguiente:
En la ventana del explorador de soluciones, presionamos el segundo botn,
(si pasamos el cursor por encima, mostrar un mensaje que indica "Mostrar
126
Cursos
www.depurando.com
todos los ficheros"), de esta forma tendremos a la vista todos los ficheros de
la aplicacin, incluso el de los directorios en el que se crea el ejecutable, tal
como podemos apreciar en la figura 2.27:
Figura 2.27
127
www.depurando.com
Atributos personalizados
Adems de los atributos que ya estn predefinidos en el propio .NET o Visual Basic, podemos crear nuestros propios atributos, de forma que en tiempo de ejecucin podamos acceder a ellos mediante las clases del espacio de
nombres Reflection, aunque debido a que este tema se sale un poco de la intencin de este curso, simplemente indicar que los atributos personalizados
son clases que se derivan de la clase System.Attribute y que podemos definir
las propiedades que creamos conveniente utilizar en ese atributo para indicar cierta informacin a la que podemos acceder en tiempo de ejecucin.
En el siguiente cdigo tenemos la declaracin de una clase que se utilizar
como atributo personalizado, notamos que, por definicin las clases para
usarlas como atributos deben terminar con la palabra Attribute despus del
nombre "real" de la clase, que como veremos en el cdigo que utiliza ese
atributo, esa "extensin" al nombre de la clase no se utiliza.
Veamos primero el cdigo del atributo personalizado:
128
Cursos
www.depurando.com
Nota.- Cuando utilizamos el atributo, en el constructor que de forma predeterminada crea Visual Basic, los parmetros se indican por el orden alfabtico de las propiedades, pero que nosotros podemos alterar usando directamente los nombres de las propiedades, tal como
podemos ver en el cdigo de ejemplo anterior.
Acceder a los atributos personalizados en tiempo de ejecucin
Para acceder a los atributos personalizados podemos hacer algo como esto,
(suponiendo que tenemos la clase AutorAttribute y una clase llamada
PruebaAtributos a la que hemos aplicado ese atributo personalizado):
Visual Studio 2005
129
www.depurando.com
VBFixedStringAttribute Este atributo se utiliza para crear cadenas de longitud fija en Visual Basic 2005. Habitualmente se aplica
a campos o miembros de una estructura, principalmente cuando
queremos acceder al API de Windows o cuando queremos usar esa
estructura para guardar informacin en un fichero, pero utilizando
una cantidad fija de caracteres.
Cursos
www.depurando.com
Si trabajamos con el IDE de Visual Basic, ese mensaje se mostrar al compilar o utilizar los atributos marcados como obsoletos, tal como podemos
apreciar en la figura 2.28:
Figura 2.28
131
www.depurando.com
Cuadro de herramientas
El cuadro o barra de herramientas de Visual Studio 2005, nos permite utilizar los distintos componentes que .NET Framework pone a nuestra disposicin, en Visual Studio 2005 tenemos una gran cantidad de controles dispuestos en diferentes categoras.
132
Cursos
www.depurando.com
133
www.depurando.com
Figura 1
134
Cursos
www.depurando.com
Por defecto, la ventana Agregar conexin queda preparada para establecer una conexin con una fuente
de datos de origen de datos OLE
DB, por lo que si nuestra intencin
es establecer una conexin con otra
fuente de datos, entonces deberemos
hacer clic sobre el botn Cambiar...
que se indica en la figura 3.
135
www.depurando.com
FAQ:
Puedo utilizar el proveedor OLE
DB en lugar del proveedor de SQL
Server para conectar con una base
de datos SQL Server? Con OLE DB,
puede acceder a fuentes de datos
SQL Server u otras fuentes de datos
como Microsoft Access, sin embar
go, si utiliza SQL Server 7.0, SQL
Server 2000 SQL Server 2005, se
recomienda el uso del proveedor de
SQL Server, que es un proveedor de
acceso a datos nativo que aumenta el rendimiento de nuestras aplicaciones
con SQL Server. Slo si utiliza una versin de SQL Server anterior a SQL
Server 7.0, deber utilizar necesariamente el proveedor de acceso a datos
OLE DB.
Una vez que hemos seleccionado el proveedor de acceso a datos, nos centraremos en la opcin Nombre de archivo base de datos como se muestra
en la figura 5.
Figura 5 En este lugar indicaremos el fichero de base de datos con el que estableceremos la conexin
Cursos
www.depurando.com
A tener en cuenta: En este ejemplo, la conexin con la base de datos Microsoft Access, no tiene ningn tipo de usuario y contrasea. Tenga en cuenta que en la parte identificada
como Conexin con la base de datos, podramos indicar el usuario y contrasea si fuera necesario.
En este punto, tan slo deberemos presionar sobre el botn Aceptar para
que la base de datos con la que hemos establecido la conexin, quede ahora
insertada en la ventana del Explorador de base de datos como se muestra
en la figura 8.
Figura 8 Base de datos Microsoft Access
insertada en la ventana del Explorador de
base de datos
Advertencia!
Tener demasiadas
conexiones activas en el entorno o
configuradas en l, puede incidir negativamente en el rendimiento de Visual Studio 2005 cuando se trabaja
con l. Tenga configuradas solamente, aquellas conexiones que va a utilizar, o aquellas conexiones de uso
Visual Studio 2005
137
www.depurando.com
ms habitual y frecuente.
Ver vdeo 34 Explorador de base de datos.
Explorador de soluciones
El Explorador de soluciones lo podemos encontrar en la parte derecha de
nuestro entorno de desarrollo.
Una solucin se compone de proyectos y stos, de recursos y objetos. Por lo
general, una solucin contendr un proyecto, pero podemos encontrarnos
con ms de un proyecto dentro de una misma solucin. Sin embargo, estos
conceptos son muy sencillos de comprender y controlar, y para nada debe
hacernos pensar que esto es algo complejo que nos costar mucho tiempo
dominar.
En la figura 1, podemos observar el explorador de soluciones de Visual Stu
dio 2005.
Figura 1 La opcin Explorador de soluciones desplegada en Visual Studio 2005
Si queremos aadir un nuevo formulario al proyecto, lo haremos presionando con el botn secundario en
cualquier parte de la ventana del explorador de soluciones, pero si esa
pulsacin la hacemos en alguno de
los objetos que contiene el proyecto,
no podremos hacerlo, ya que el IDE
de Visual Studio 2005 muestra un
men diferente segn el objeto presionado, por ejemplo si queremos
aadir un nuevo proyecto, podemos
hacerlo presionando con el botn
secundario del mouse sobre la "solucin".
138
Cursos
www.depurando.com
Propiedades
La ventana de propiedades la encontraremos en la parte derecha y ms abajo
de la ventana Explorador de soluciones en nuestro entorno de desarrollo.
Esta ventana nos permitir acceder a las propiedades de los objetos insertados en nuestros formularios Windows, como se muestra en la figura 1.
Figura 1 Ventana de Propiedades de Visual Studio 2005
139
www.depurando.com
Figura 1
Algunas de las opciones que tenemos en los mens tambin las podemos
conseguir usando los mens contextuales (el mostrado al presionar con el
botn secundario del mouse), y como es de esperar, tambin sern diferentes segn el elemento sobre el que hemos presionado.
Por ejemplo, para configurar el proyecto actual, podemos elegir la opcin
Propiedades del men Proyecto o bien presionar con el botn secundario
del mouse sobre el proyecto mostrado en el Explorador de soluciones.
Al seleccionar las propiedades del proyecto, tendremos una nueva ventana
desde la que podemos configurar algunas de las caractersticas de nuestro
proyecto. En la figura 2, tenemos esa ventana de propiedades del proyecto,
en la que podemos apreciar que est dividida segn el tipo de configuracin
que queremos realizar, en este caso concreto las opciones de generacin o
compilacin del proyecto.
140
Cursos
www.depurando.com
Figura 2
Otras consideraciones
El desarrollador que haya utilizado previamente otros entornos de desarrollo
distinto a los de la familia de Visual Studio .NET, encontrar muy interesantes algunos de los cambios incorporados en Visual Studio 2005. Al principio, quizs se encuentre un poco desorientado, pero rpidamente y gracias
a su experiencia en otros entornos de desarrollo, se acostumbrar al cambio.
Entre algunos de estos cambios, destacara los siguientes:
141
www.depurando.com
Figura 1
Visual Basic 2005 permite, hacer un Stop & Go (editar y continuar), de nuestras aplicaciones, es decir, pausar la ejecucin de una
aplicacin en modo depuracin y modificar los valores o propiedades que deseemos y continuar ejecutndola. Esta opcin que los
programadores de Visual Basic 6 utilizan con mucha frecuencia en
el desarrollo de sus aplicaciones, se ha mantenido en Visual Basic
2005, pero no en Visual Studio .NET 2002 y Visual Studio .NET
2003. Si por alguna razn, debe trabajar con alguno de estos entornos, debe saber que esta opcin no est disponible para las versiones comentadas.
Otra caracterstica que debemos conocer de nuestro entorno de desarrollo, es la capacidad de anclar o fijar una ventana de las comentadas anteriormente o de permitir que se haga visible cuando acercamos el puntero del mouse sobre ella. Esta opcin es la que puede
verse en la figura 2.
Figura 2
142
Cursos
www.depurando.com
Figura 3
Icono para ocultar o mostrar la ventana seleccionada cuando se encuentra en modo anclado
Algo que oculta el entorno de Visual Studio 2005 por defecto, son las de
nominadas clases parciales. Se trata de una nueva caracterstica aadida a
.NET 2.0 y por lo tanto a Visual Basic 2005, que permite separar o partir
una clase en varias porciones de cdigo.
El comportamiento de la clase es el de una nica clase, por lo que su declaracin y uso es como el de cualquier clase normal, tal y como se indica en el
siguiente cdigo:
143
www.depurando.com
De todas las maneras, el entorno nos oculta muchas veces las clases parciales de una aplicacin. Para ello, presionaremos la opcin Mostrar todos los
archivos de la ventana Explorador de soluciones como se indica en la figura 4.
Figura 4
Icono u opcin para
mostrar todos los archivos del proyecto
A tener en cuenta:
Cuando se genera un proyecto con Visual
Studio 2005, el entorno genera diferentes
clases parciales, como por ejemplo la que
se genera para un formulario.
Ver vdeo 38 Otras consideraciones.
Cursos
www.depurando.com
Datos
El grupo Datos corresponde con el
grupo que tiene relacin directa con los componentes de acceso a datos,
como se muestra en la figura 1.
Figura 1
dio 2005
145
www.depurando.com
Ver www.goddotnet.com.
Ver vdeo 40 Datos.
Componentes
Windows Forms incluye un conjunto de componentes muy nutrido y variado.
146
Cursos
www.depurando.com
Componentes de Windows
Controles comunes
Con este nombre, se aglutinan los controles ms generales y variados que
podemos utilizar en nuestras aplicaciones Windows. Sera algo as, como el
resto de controles y componentes no contenidos en ninguna de las secciones
que hemos visto anteriormente, aunque esto no es siempre as. Por esa razn, si encuentra dos controles o componentes iguales en dos o ms secciones, no lo tenga en consideracin.
147
www.depurando.com
Digamos que en esta solapa se aglutinan por lo tanto, los controles que utilizaremos con ms frecuencia.
En la figura 1 podemos observar los controles y componentes citados.
Figura 1 Controles Windows Forms en
Visual Studio 2005
148
Cursos
www.depurando.com
General
Esta seccin es como el cajn desastre, un lugar dnde podemos insertar
otros controles o componentes desarrollados por terceros, por ejemplo.
Figura 1 Seccin General en Visual Studio
2005
149
www.depurando.com
Otro caso de ejemplo es cuando se trabaja con controles o componentes similares desarrollados por dos empresas diferentes que queremos tener localizados o separados para no mezclarlos. En otras circunstancias, tampoco es
raro encontrarse con controles o componentes con iconos similares, por lo
que aclararse cul es el que nos interesa puede ser una tarea obligada.
An as, otra de las posibilidades con la que nos podemos encontrar para
utilizar esta seccin es la de tener que utilizar un control o componente circunstancialmente en un momento dado, y por eso, que no deseemos aadir
este control o componente a otra seccin como la de Controles comunes por
ejemplo.
Utilice por lo tanto esta seccin como lo considere oportuno.
Ver vdeo 43 General.
Otras consideraciones
La seccin General nos indica un repositorio de mbito y carcter general,
sin embargo, el desarrollador puede querer ordenar su propio repositorio o
seccin de controles y componentes.
Manipulando el cuadro de herramientas
Para ello, nos posicionaremos en la barra de herramientas y presionaremos
el botn secundario del mouse sobre la parte gris de la barra de herramientas desplegada y seleccionaremos la opcin Agregar ficha del men emergente, como se muestra en la figura 1.
Cuando seleccionamos esta opcin, aparecer una caja de texto en la barra
de herramientas dnde podremos escribir el nombre que consideremos
oportuno, como se muestra en la figura 2.
Si se hace la siguiente pregunta, cmo cambiar el nombre de una seccin
ya creada o una existente?, sepa que deber realizar los siguiente pasos.
150
Cursos
www.depurando.com
Haga clic con el botn secundario del mouse sobre la seccin sobre la que
desea cambiar el nombre y seleccione la opcin Cambiar nombre de ficha
como se muestra en la figura 3.
? Figura 1 Opcin de personalizacin de
nuestros propios grupos de controles y
componentes
Figura 3
151
www.depurando.com
FAQ:
Qu ocurre si me equivoco personalizando mi barra de herramientas?
Visual Studio 2005 nos proporciona
la posibilidad de resetear o restau
rar el estado inicial de la barra de
herramientas en el entorno de desa
rrollo. Para hacer esto, haremos
clic con el botn secundario del
mouse la barra de herramientas y
seleccionaremos la opcin Restablecer cuadro de herramientas del men emergente, como se muestra en la
siguiente figura.
Ojo!, al seleccionar esta opcin,
perderemos todas las modificaciones
que hayamos realizado sobre la barra de herramientas.
Otros controles a tener en cuenta
Dentro del entorno de Visual Studio
2005 y en .NET en general, se han
aadido una serie de controles nuevos que conviene comentar.
Uno de estos controles, se llama
WebBrowser, tal y como se indica
en la figura 5.
Este control es la representacin de un control especfico para mostrar contenido XML o contenido HTML, como si de una pgina Web se tratara.
152
Cursos
www.depurando.com
Control WebBrowser en
153
www.depurando.com
Figura 8
Figura 9
154
Cursos
www.depurando.com
155
www.depurando.com
Ya hemos visto anteriormente como insertar un control a nuestro formulario, pero quizs no sepamos como manejarlos de forma eficiente en ese
formulario.
Inserte en un formulario Windows por ejemplo, tres controles Button como
se muestra en la figura 1.
? Figura 1 Controles Button insertados
en un formulario Windows
Cursos
www.depurando.com
Figura 3
Figura 4 Otras opciones especiales, nos permiten alinear o trabajar con los controles de
forma rpida y segura
? Figura 5 Controles alineados y espaciados segn la eleccin de opciones del entorno
157
www.depurando.com
Figura 7
Una vez seleccionada esta opcin, los controles se modificarn con el mismo tamao tal y como se muestra en la figura 8.
Truco: Suponiendo que tengamos tres controles Button de diferentes ta
maos y que queramos que todos tengan el mismo tamao que el segundo
158
Cursos
www.depurando.com
159
www.depurando.com
Prcticamente todo en .NET son objetos. Los controles tambin, as que para aadir un control a un formulario en tiempo de ejecucin, deberemos
hacerlo tratndolo como un objeto.
La declaracin principal de un objeto, se realiza con la instruccin New.
El siguiente ejemplo de cdigo, crea un control Button en tiempo de ejecucin.
En la figura 1 podemos ver el resultado en ejecucin del cdigo escrito anteriormente. Para ejecutar nuestra aplicacin, presionaremos el botn F5,
que es la forma habitual de ejecutar una aplicacin.
Figura 1 Creacin de un control en tiempo de ejecucin en Visual Basic 2005
160
Cursos
www.depurando.com
Analizando este cdigo, parece estar bien escrito, pero al presionar F5 para
ejecutar nuestro proyecto, nos encontramos con que Visual Basic 2005 nos
muestra un error. Nos indica que btn1 no est declarado. Qu ocurre?. Al
buscar la clase de ensamblados de la aplicacin, el control Button de nombre btn1 no existe, por lo que Visual Basic 2005 detecta que debemos declarar el control, sin embargo y en nuestro caso, esta declaracin la hacemos en
tiempo de ejecucin. Cmo acceder a la propiedad Text del control Button
creado en tiempo de ejecucin?
El siguiente cdigo resuelve esta duda:
161
www.depurando.com
162
Cursos
www.depurando.com
Hasta ahora hemos visto como crear controles en tiempo de ejecucin, pero
en muchas ocasiones, nos es til no slo crear un control en tiempo de ejecucin, sino relacionarlo con un evento. En nuestro ejemplo del control
Button, cuando hacemos clic sobre el control, no ocurre nada, y sera interesante mostrar un mensaje o realizar una accin determinada.
163
www.depurando.com
Figura 3
Ejecucin del
ejemplo con asociacin de
evento desarrollado en Visual Basic 2005
Nuestro ejemplo en
ejecucin es el que se
muestra en la figura 3.
Creacin de una
matriz de controles
En el captulo anterior,
hemos visto como crear
controles en tiempo de
ejecucin e incluso
como asociar un evento a un control creado dinmicamente en Visual Basic
2005, pero, qu ocurre si queremos crear un array o matriz de controles?
Podemos simular una matriz de controles de muchas formas. Yo en este
ejemplo, aplicar la siguiente forma de llevar a cabo esta tarea:
164
Cursos
www.depurando.com
165
www.depurando.com
Cursos
www.depurando.com
La diferencia mayor que reside entre el desarrollo de componentes y controles en .NET, es que en lugar de heredar de la clase Component como en el
caso de la creacin de los componentes, se ha de heredar de la clase Control o System.Windows.Forms.UserControl.
El tipo de proyecto seleccionado no posee por defecto como ocurre con los
controles ActiveX, de la superficie contenedora sobre la cul podremos insertar otros controles o realizar las acciones que consideremos pertinentes
para crear as nuestro control personalizado. En este caso, la superficie contenedora la deberemos crear aadiendo las referencias necesarias a nuestro
programa.
Haga clic con el botn secundario del mouse sobre el proyecto o solucin
de la ventana Explorador de soluciones y a continuacin, seleccione la opcin Propiedades del men emergente. A continuacin, agregue las referencias a las libreras de clases System.Drawing y System.Windows.Forms. Por ltimo, escriba las siguientes instrucciones bsicas.
En este punto, nuestra clase habr sido transformada en la clase contenedora de un control
que es la que puede verse en la figura 2.
167
www.depurando.com
De las opciones que salen, (ver figura 2B), deberamos seleccionar entonces
la plantilla Control de usuario.
Figura 2B
168
Cursos
www.depurando.com
Observando el cdigo, vemos que hemos creado una propiedad Acceso que
nos permitir saber si un usuario y contrasea han sido validadas o no.
Ahora nuestro control, est listo ya para ser compilado y probado en una
aplicacin Windows.
Para compilar nuestro control, haga clic en el men Generar > Generar
Solucin como se muestra en la figura 3.
A continuacin aada un nuevo proyecto Aplicacin para Windows a la
solucin. Para aadir un proyecto a la solucin actual, tendremos que ir al
men Archivo y seleccionar Nuevo proyecto, cuando nos muestre el cuadro de dilogo, indicaremos que lo aada a la misma solucin.
Visual Studio 2005
169
www.depurando.com
Figura 3
Cursos
www.depurando.com
171
www.depurando.com
Figura 7
Nuestro formulario Windows de prueba en ejecucin con el control insertado en l, es el que puede verse en la figura 8.
? Figura 8 Formulario Windows de
prueba en ejecucin con el control insertado
Otras consideraciones
Controladores contenedores
Cuando trabajamos con controles, surgen muchas veces muchas dudas de
carcter habitual. Definamos que hay dos tipos de controles, los controles
contenedores y los controles no contenedores.
La diferencia entre ambos es que los controles contenedores, pueden como
su propia palabra dice, contener otros controles dentro de ste. Los controles no contenedores no pueden.
Un claro ejemplo de control contenedor, es el control TabControl, el cul
permite incluir dentro de l otros controles, incluso controles contenedores a
su vez.
172
Cursos
www.depurando.com
Figura 1
173
www.depurando.com
Observando este cdigo, vemos que lo que hacemos no es otra cosa que recorrer los objetos como controles dentro del formulario y miramos si se trata de un control de tipo TextBox. En este caso, modificamos la propiedad
Text para dejarla en blanco. Ejecute este ejemplo con la tecla de funcin
F5, escriba algo en las cajas de texto y pulse el botn. Observar que logramos conseguir nuestro objetivo de borrar el contenido de todos los controles TextBox
A continuacin, lo que haremos ser aadir un control TabControl a nuestro formulario Windows, y dentro de l, aadiremos los cuatro controles
TextBox y el control Button anteriormente comentados, tal y como se
muestra en la figura 2.
Figura 2 Controles insertados dentro
de un control contenedor como el control
TabControl
174
Cursos
www.depurando.com
Para solventar este problema, deberemos recorrer los controles del contenedor. Una forma de solventar esto es de la siguiente manera:
De esta manera, recorreremos todos los controles que residen en las pginas
de un control TabControl y si se trata de un control TextBox, modificaremos la propiedad Text correspondiente.
Por esta razn, cuando trabajamos con controles dentro de un formulario y
queremos actuar sobre un conjunto de controles determinado, debemos tener en cuenta entre otras cosas, si se trata de un conjunto de controles o un
control simplemente, se encuentra dentro de un control contenedor o fuera
de l.
Sin embargo, para resolver el problema de recorrer todos los controles de un
formulario, estn o no dentro de un control contenedor, lo mejor es ampliar
la funcin anterior y hacerla recursiva, de modo que permita recorrer todos
los controles del formulario, estn o no dentro de un contenedor.
El siguiente cdigo, refleja un ejemplo de como hacer esto posible. En el
mismo proyecto, podemos aadir nuevos TextBox a la otra ficha del TabControl, adems uno en el propio formulario, (para que no est dentro del
TabControl). Rellene algo de contenido en los controles TextBox y ejecute
el cdigo:
175
www.depurando.com
Smart Tags
Otras de las novedades del diseador de formularios de Visual Studio 2005,
es el hecho de poder utilizar las denominadas Smart Tags.
Si usted es usuario de Office en sus ltimas versiones, sabr a que me refiero. Las Smart Tags nos indican trucos y consejos directa a la cul se puede
acceder desde Visual Basic 2005 de forma rpida, ahorrndonos tiempo y
aportndonos productividad en nuestros desarrollos.
Las Smart Tags aparecen en Visual Studio 2005 tanto en el lado del diseo
del formulario Windows como en la parte correspondiente del cdigo fuente
escrito.
En el caso de los controles insertados en un formulario Windows, estas
Smart Tags aparecern por lo general en el borde superior derecho del control y se representar con un icono parecido a este .
Si hacemos clic sobre ese icono, aparecer una ayuda grfica con varias opciones que permite realizar las acciones ms comunes sobre el control seleccionado, tal y como se indica en la figura 3 para el caso del control TabControl.
Figura 3
176
Cursos
www.depurando.com
En el caso del cdigo, las Smart Tags poseen un comportamiento ligeramente diferente dependiendo del caso. Un ejemplo habitual es el hecho de
declarar una variable incorrecta tratando de trabajar con ella. Cuando ejecutamos nuestra aplicacin, el depurador se detiene en la declaracin incorrecta y nos muestra una ventana de depuracin, como se indica en la figura 4.
Figura 4
La ventana emergente de depuracin nos indica no slo el tipo de error encontrado, sino que adems, nos indica las posibles soluciones para solventar
el problema. Estos consejos, sugerencias o Tips, nos ofrecen una ventaja sobre nuestros desarrollos, proporcionndonos una rpida solucin a un problema y permitindonos ahorrar mucho tiempo resolviendo el porqu del
problema.
177
www.depurando.com
De esta manera, conoceremos los detalles del problema detectado por Studio 2005 permitindonos corregirlo cmodamente.
Otra posibilidad de las Smart Tags es la deteccin de una declaracin de
variable o cualquier parte de cdigo, no esperada. Como ejemplo, declararemos una variable de la forma:
Queramos decir Integer, pero con las prisas he escrito intger. En ese instante, Visual Studio 2005 se ha percatado de que la declaracin no es correcta
y antes de que me pueda dar cuenta de que lo he escrito incorrectamente, el
entorno me indica el error marcndolo con un subrayado caracterstico como se indica en la figura 6.
178
Cursos
www.depurando.com
Figura 6
Subrayado de Visual Studio
2005 indicando un error en la instruccin
de cdigo escrita
179
www.depurando.com
Como ejemplo, sitese con los cursores sobre Math, pulse Enter, seleccione a continuacin Get a Ran
dom Number using the Random class
como se indica en la figura 11 y vuelva a presionar Enter. El cdigo quedar insertado a nuestro proyecto de Visual Basic 2005 como se muestra a
continuacin:
180
Cursos
www.depurando.com
181
www.depurando.com
Grficos 3D
Para trabajar con imgenes y grficos en 3D, deberemos utilizar DirectX, ya
que dentro de la plataforma .NET de Microsoft, no tenemos la posibilidad
de crear representaciones 3D.
Esto significa por otra parte, que si desarrollamos una aplicacin con representacin 3D con DirectX, deberemos distribuir tambin las libreras DirectX en la mquina en la que se ejecute nuestra aplicacin. Es decir, no
bastar con distribuir Microsoft .NET Framework.
Pero DirectX no nos permite slo crear grficos e imgenes en 3D, tambin
podemos crear imgenes en 2D, pero lo ms normal en este ltimo caso y
salvo que no requeramos un uso continuado de DirectX, ser utilizar en su
lugar GDI+, como veremos ms adelante.
Para trabajar con DirectX en Visual Basic 2005, deberemos aadir una referencia al proyecto con la librera o libreras COM de DirectX, eso si trabajamos con DirectX 8 o anterior, ya que a partir de DirectX 9, Microsoft ha
proporcionado un conjunto de clases y libreras que interactan con .NET
directamente, permitindonos ejecutar aplicaciones .NET con DirectX administrado.
En nuestro caso, lo mejor es realizar un ejemplo, no sin antes recordar, que
debera descargar Microsoft DirectX SDK 9 e instalarlo en su sistema. El
SDK contiene ficheros de ayuda y documentacin que le ensear a crear
aplicaciones con DirectX 9 en Visual Basic 2005.
FAQ:
Dnde puedo descargar Microsoft DirectX 9.0 SDK? La ltima versin de
DirectX SDK la encontrar en la pgina Web de MSDN de DirectX, espe
cialmente creada para desarrolladores de aplicaciones y juegos.
Descargas de Microsoft DirectX:
http://msdn microsoft.com/library/dafault.asp?url=downloads/list/directx.asp
182
Cursos
www.depurando.com
Una vez que tenemos instalado en nuestro sistema las libreras de desarrollo
de DirectX para .NET, iniciaremos una nueva aplicacin Windows, aadiremos las referencias a las libreras Microsoft.DirectX y Micro
soft.DirectX.Direct3D tal y como se muestra en la figura 1 y las cules encontraremos normalmente en el directorio c:\windows\system32\.
183
www.depurando.com
Grficos 2D
Las APIs de GDI+ corresponden a la evolucin natural de las APIs y libreras GDI que se utilizaban en otros lenguajes de desarrollo. GDI+ no es otra
cosa que un conjunto de clases desarrolladas para el entorno .NET y por esa
razn, podemos entonces dibujar y crear representaciones grficas en Visual
Basic 2005.
Todas las clases GDI+, pueden ser localizadas a travs del nombre de espacio System.Drawing. As, podemos acceder a todas las posibilidades que
nos ofrece GDI+ y las cuales veremos ms adelante.
184
Cursos
www.depurando.com
185
www.depurando.com
Atendiendo al cdigo, observamos que hemos representado la grfica indicando que queremos dibujar una lnea e.Graphics.DrawLine indicando posteriormente una serie de atributos como el color del lpiz y tamao o grosor
de ste Pen(Color.DarkBlue, 2) y un conjunto de parmetros (x,y) que representan las coordenadas de la lnea (1,1) y (50,50). Otra representacin
similar sera e.Graphics.DrawLine(Pens.DarkBlue, 1, 1, 50, 50), con la salvedad de que en este caso, el grosor del lpiz es el grosor por defecto, que
es 1. De todos los modos, la declaracin e.Graphics.DrawLine(New Sys
tem.Drawing.Pen(Color.DarkBlue,
2),
1,
1,
50,
50)
y
e.Graphics.DrawLine(New System.Drawing.Pen(Color.DarkBlue, 2), 50,
50, 1, 1) en el caso de la representacin de lneas es igualmente compatible.
Este ejemplo de prueba en ejecucin es el que se puede ver en la figura 1.
Figura 1 Ejemplo de dibujo con GDI+ de una lnea recta en un formulario Windows
Lneas personalizadas
Sin embargo, la representacin de lneas
con GDI+ tiene diferentes particularidades
que nos permiten sacar un alto grado de
personalizacin a la hora de pintar o representar las imgenes y grficos en nuestras
aplicaciones.
La representacin de lneas con GDI+, nos permite entre otras cosas, personalizar no slo el color y el grosor de una lnea, sino otras caractersticas de
sta como por ejemplo los extremos a dibujar. As, podemos dibujar unos
extremos ms o menos redondeados, puntiagudos, o personalizados. Esto lo
186
Cursos
www.depurando.com
conseguimos hacer mediante las propiedades StartCap y EndCap de la clase Pen que es lo que vulgarmente he denominado como lpiz.
A estas propiedades, las podemos dar diferentes valores. Sirva el siguiente
ejemplo de muestra de lo que podemos llegar a hacer.
187
www.depurando.com
188
Cursos
www.depurando.com
189
www.depurando.com
Curvas de Bzier
Otra posibilidad que nos ofrece GDI+
es la representacin de curvas de Bzier, algo que conseguiremos gracias
al mtodo DrawBezier de GDI+.
La representacin de las curvas de Bzier pueden hacerse mediante dos pares de puntos (x,y) o mediante cuatro coordenadas de puntos que definen la
asignacin de las curvas a representar.
El siguiente ejemplo nos muestra como representar una curva de Bzier con
Visual Basic 2005 y GDI+.
190
Cursos
www.depurando.com
Rellenando curvas
En algunas ocasiones, nos podemos
ver con la necesidad de crear curvas y
de rellenar su interior para destacarlo
de alguna manera. Esto es lo que veremos a continuacin.
El mtodo AddArc nos permite aadir una serie de puntos para representar
una circunferencia. En realidad, se representan puntos, los cuales son el
punto (x,y) inicial, el ancho y el alto de la representacin, el ngulo de comienzo de representacin, y el ngulo final de la representacin. En ejemplo
que veremos a continuacin, utilizaremos tambin los mtodos FillPath y
DrawPath, para representar la curva en el formulario.
El cdigo del ejemplo es el que se detalla a continuacin:
191
www.depurando.com
Dibujando tartas
Otra posibilidad que nos ofrece GDI+
es la representacin de las conocidas
tartas. Todas estas representaciones
son representaciones 2D, pero siempre
se puede emular una representacin
3D, superponiendo tartas una encima de otra.
El siguiente ejemplo, utiliza los mtodos FillPie y DrawPie para generar un
grfico de tarta y rellenarlo de un determinado color. El cdigo de nuestro
ejemplo, quedara de la siguiente manera:
Cursos
www.depurando.com
193
www.depurando.com
El siguiente ejemplo, ilustra en cmo abordar un pequeo proyecto para representar una cadena de texto en pantalla.
194
Cursos
www.depurando.com
Otras consideraciones
GDI+ proporciona un variadsimo
juego de brochas que nos permiten dibujar degradados en un formulario o
control que permita el trabajo con grficos.
El siguiente ejemplo de cdigo, nos muestra como dibujar un degradado en
un formulario Windows.
Evidentemente, podemos jugar con la clase LinearGradientBrush y con la lista enumerada LinearGraVisual Studio 2005
195
www.depurando.com
dientMode para dar una aspecto o un toque ligeramente diferente al degradado, como el que se indica en la figura 2.
Figura 2 Otro ejemplo de representacin
degradada en un formulario Windows
La figura 3 nos muestra el resultado final de insertar una imagen en el formulario Windows.
Figura 3 Imagen insertada con GDI+ dentro del
formulario Windows
Cursos
www.depurando.com
Para realizar esto, deberemos indicar el color o colores que queremos utilizar para provocar en l un efecto transparente.
El siguiente ejemplo, nos muestra como hacer esto utilizando para ello el
mtodo MakeTransparent.
Despliegue de aplicaciones
En este captulo veremos las partes
ms generales en el uso y generacin
de imgenes y grficos con Visual
Basic 2005.
Pasaremos de puntillas sobre el uso de DirectX para la generacin de grficos 3D y nos adentraremos un poco ms profundamente, en el desarrollo de
grficos e imgenes 2D con GDI+.
197
www.depurando.com
Los ensamblados, son para entenderlo muy rpidamente, como los ejecutables de una aplicacin.
La nica diferencia notable, es que en .NET, un proyecto o aplicacin, se
compila en cdigo intermedio, el conocido como Intermediate Language o
lenguaje intermedio, que luego interpretar el CLR o Common Language
Runtime para ejecutarla en el sistema operativo correspondiente.
Ese cdigo intermedio, es el ensamblado de nuestra aplicacin que a su vez
puede contener uno o ms ficheros, y a su vez, un proyecto, puede estar
contenido por uno o ms ensamblados.
Por lo tanto, dentro de un ensamblado, se encierran algunas partes importantes que debemos conocer.
Lo mejor para entender bien lo que hay en un ensamblado y que contiene es
que abramos Visual Studio 2005 y seleccionemos una plantilla de proyecto
de tipo Console Application como se muestra en la figura 1.
Figura 1
198
Cursos
www.depurando.com
A continuacin, escribiremos un ejemplo simple de consola, para que estudiemos el resultado de ste.
El cdigo fuente de nuestra pequea aplicacin de ejemplo, es el que se detalla a continuacin:
Ahora bien, lo que tenemos una vez compilamos nuestra aplicacin de consola, no es un ejecutable como tal o como lo entenderamos en otros compiladores, por ejemplo en Visual C++.
En Visual C++, generbamos un ejecutable nativo al sistema en el cul
compilbamos el proyecto y si ese ejecutable lo llevbamos a otra mquina
con otro sistema operativo diferente a Windows, ese programa no iba a funcionar.
199
www.depurando.com
Con .NET y en nuestro caso con Visual Basic 2005, este concepto ha cambiado.
El proyecto que hemos desarrollado no se compila a un ejecutable nativo,
sino que el sistema .NET lo compila a un lenguaje intermedio, que luego el
CLR de la mquina en la cul lanzamos nuestra aplicacin, ser capaz de interpretar adecuadamente.
Puede que estos conceptos le puedan desorientar un poco, pero es muy fcil
de comprender.
Adicionalmente a esto, lo suyo es destripar un poco lo que hay dentro del
ensamblado que hemos convertido a cdigo intermedio.
Para llevar a cabo nuestra tarea, haremos uso de una herramienta externa de
Microsoft y del entorno Visual Studio 2005, que nos permite analizar el ensamblado de un proyecto convertido a cdigo intermedio.
Aclaracin: Un ensamblado o el cdigo intermedio, (IL a partir de ahora),
no es ni el cdigo fuente de nuestra aplicacin ni el programa ejecutable.
El IL se puede analizar con una herramienta de Microsoft denominada ildasm. Si est usando una versin Express de Visual Studio debe saber que
esta herramienta no se incluye con estas versiones, slo forma parte del
SDK de .NET Framework que se incluye con las versiones de Visual Studio
2005.
Cuando abrimos el fichero ejecutable de nuestra aplicacin con la herramienta il
dasm.exe, observamos que esta tiene una gran cantidad de informacin, como se in
dica en la figura 3.
200
Cursos
www.depurando.com
201
www.depurando.com
Figura 4
Cursos
www.depurando.com
203
www.depurando.com
204
Cursos
www.depurando.com
Con los Strong Names, aseguramos un uso seguro de los componentes contenidos en el ensamblado. Hay que tener en cuenta que un ensamblado declarado en la GAC que es llamado por varias aplicaciones, crea una nica
instancia. De ah, que crear un Strong Name para el ensamblado, est ms
que justificado.
Visual Studio 2005
205
www.depurando.com
Un Strong Name, nos asegura por otro lado, que el nombre de un ensamblado es nico y que por lo tanto, al ser nico, no puede ser utilizado por
otros ensamblados.
Los Strong Names se generan con un par de claves, una de ellas de carcter
pblico y otra de carcter privado, claves que se introducen en fichero de
ensamblado de la aplicacin, y que luego al compilar nuestra aplicacin,
queda registrada con ese Strong Name.
Para indicar un Strong Names a un ensamblado, debe crear primero el par
de claves (clave pblica y clave privada), que se generar en un fichero con
extensin snk, y modificar posteriormente el fichero AssemblyInfo.vb de su
proyecto. En ese archivo, debe aadir una instruccin similar a la siguiente:
<Assembly: AssemblyKeyFile("KeyFile.snk")>
Ver vdeo 60 GAC y Strong Names.
Cursos
www.depurando.com
207
www.depurando.com
Si utilizamos la plantilla, Merge Module Project, crearemos un paquete instalacin para componentes compartidos.
El uso de la plantilla, Web Setup Project por su parte, nos permitir generar
un paquete de instalacin para aplicaciones basadas en Internet o aplicaciones Web.
La plantilla, Setup Wizard genera un asistente para generar uno de los cuatro anteriores tipos de proyectos de despliegue. Es una forma rpida de generar el proyecto de despliegue.
Ver vdeo 60 Creando un paquete de instalacin.
Otras consideraciones
Setup Proyect
208
Cursos
www.depurando.com
209
www.depurando.com
Una vez que ha escrito el cdigo fuente de la aplicacin, ejectela y compruebe que funciona como se espera.
Si lo desea, abra el fichero AssemblyInfo.vb e indique la versin de la aplicacin que desee. En mi caso he dejado la versin 1.0.0.0 que es la versin
que aparece por defecto.
Despus de esto, genere la aplicacin como se indica en la figura 2.
Figura 2 Generamos la aplicacin para
comprobar entre otras cosas que todo est
preparado
Por ltimo, pulse el botn secundario del mouse sobre el proyecto y seleccione la opcin Publicar... como
se indica en la figura 3.
210
Cursos
www.depurando.com
211
www.depurando.com
212
Cursos
www.depurando.com
? Figura 9
La aplicacin Windows ejecutada a travs del Servidor
Web, debe ser confiable y segura.
Figura 10
213
www.depurando.com
214
Cursos
www.depurando.com
Una vez hecho esto, acudimos a la pgina Web de la aplicacin y presionamos nuevamente el botn Instalar como se indica en la figura 13.
215
www.depurando.com
Cursos
www.depurando.com
System.Collections.Generic, las cuales utilizan la nueva "tecnologa" de los tipos genricos (generic) para almacenar los elementos,
(cuyo tipo interno puede ser de cualquier tipo).
Como podemos imaginar, dependiendo del "contrato" firmado por cada una
de estos tipos de colecciones, podremos hacer ciertas operaciones con ellas.
A continuacin veremos con ms detalle estos tipos de colecciones y cuales
son las que podemos usar dependiendo del interfaz que cada una de ellas
implemente.
Nota.- La diferencia bsica entre estos tipos de colecciones es cmo estn
almacenados los elementos que contienen, por ejemplo, las colecciones de tipo IList (y las directamente derivadas de ICollection)
solo almacenan un valor, mientras que las colecciones de tipo IDictionary guardan un valor y una clave relacionada con dicho valor.
Tambin veremos unas clases base que implementan cada una de estas dos
interfaces, las cuales las podemos usar como base de nuestras propias colecciones personalizadas.
Las colecciones basadas en ICollection
La interfaz ICollection es un caso aparte, ya que realmente todas las colecciones de .NET implementan esta interfaz, de hecho, esta interfaz se deriva
de IEnumerable que es la que nos permite recorrer las colecciones usando
bucles For Each.
Visual Studio 2005
217
www.depurando.com
Cursos
www.depurando.com
Las colecciones de tamao fijo, no se pueden quitar ni aadir elementos, pero si modificarlos. Por ejemplo, las colecciones basadas
en Array son de tamao fijo.
Las de tamao variable permiten cualquier tipo de adicin, eliminacin y modificacin. La mayora de las colecciones suelen ser de
este tipo, es decir, nos permiten dinmicamente aadir o eliminar
elementos.
Existe un gran nmero de colecciones en .NET que implementan esta interfaz, (sobre todo las colecciones basadas en controles), entre las que podemos destacar las siguientes:
x
ArrayList, la coleccin "clsica" para este tipo de interfaz. Contiene todos los miembros habituales en este tipo de colecciones.
CollectionBase, una clase abstracta para poder crear nuestras propias colecciones basadas en IList.
StringCollection, una coleccin especializada que solo puede contener valores de tipo cadena.
La coleccin ArrayList
Tal como hemos comentado, el tipo de coleccin que se usa como referencia a la hora de hablar de las colecciones basadas en la interfaz IList, es
ArrayList.
219
www.depurando.com
Esta coleccin permite aadir, eliminar y modificar fcilmente los elementos que contiene. Tambin podemos recorrerlos mediante un bucle For accediendo a los elementos por medio de un ndice e incluso mediante un bucle del tipo For Each. Al igual que ocurre con los arrays, el ndice inferior
es siempre el cero y los elementos se almacenan de forma consecutiva, es
decir, si aadimos dos elementos a una coleccin de tipo ArrayList (y a las
que implementen la interfaz IList), el primero ocupar la posicin cero y el
segundo la posicin uno. La ventaja de trabajar con las colecciones es que
no debemos preocuparnos de reservar memoria cada vez que vayamos a
aadir un nuevo elemento, simplemente usamos el mtodo Add y asunto
arreglado.
Lo mismo ocurre a la hora de quitar elementos de una coleccin, no tenemos que preocuparnos demasiado por el espacio dejado al quitar elementos,
de eso se encarga el propio .NET, nosotros simplemente debemos llamar al
mtodo Remove o RemoveAt indicando respectivamente el elemento a eliminar o el ndice en el que se encuentra almacenado.
Truco Si decidimos eliminar varios elementos de una coleccin de tipo
IList (o de un array), lo normal es que lo hagamos usando un bucle
For; si este es el caso, para evitar una posible excepcin, (realmente no es posible, sino con toda certeza segura), debemos recorrer el
bucle desde el final hacia adelante, con idea de que al cambiar el
nmero de elementos no falle al intentar a acceder a un elemento
que ya no existe.
El tipo de datos de almacenamiento de las colecciones
Estos elementos internamente estn almacenados como objetos del tipo Ob
ject, por tanto podemos aadir cualquier tipo de datos a una coleccin de este tipo, ya que todos los tipos de datos de .NET estn basados en la clase
Object.
El problema con este tipo de colecciones es que siempre que queramos acceder a uno de los elementos que contiene, debemos hacer una conversin
al tipo adecuado, es decir, si en una coleccin de este tipo guardamos objetos de tipo Cliente y queremos acceder a uno de ellos, debemos hacer una
conversin (cast) del tipo Object al tipo Cliente, ya que si no lo hacemos y
220
Cursos
www.depurando.com
tenemos activada Option Strict (la opcin para las comprobaciones estrictas), se producir un error si hacemos algo como esto:
Por tanto, la ltima lnea deberamos escribirla de una de estas dos formas:
Otro de los problemas que tienen las colecciones "normales" es que en algunos casos, particularmente cuando almacenamos tipos por valor, el rendimiento se ve bastante mermado, ya que el runtime de .NET (el CLR) debe
hacer lo que en ingls se conoce como boxing/unboxing, es decir, convertir
un tipo por valor en uno por referencia cuando va a guardarlo en la coleccin (boxing), y el proceso inverso cuando lo queremos recuperar (unboxing).
Nota.- Por suerte, en Visual Basic 2005 tenemos otra forma de mejorar el
rendimiento de las colecciones, y es mediante las colecciones "generic", de
esto, nos ocuparemos ms adelante.
Otras de las ventajas de las colecciones de .NET, no solo las basadas en la
interfaz IList, es que proporcionan una gran cantidad de mtodos que nos
facilitan la manipulacin de ese tipo de datos. Por ejemplo, tenemos mtodos para clasificar el contenido de las colecciones, (aunque esos objetos deben implementar la interfaz IComparable, tal como vimos en el ltimo
ejemplo del captulo de las interfaces), adems tienen mtodos para hacer
copias, buscar elementos y muchos etcteras ms.
Las colecciones basadas en IDictionary
221
www.depurando.com
El otro grupo de colecciones que podemos encontrar en .NET son las colecciones basadas en la interfaz IDictionary. stas, a diferencia de las colecciones IList, siempre mantienen el par clave/valor, ya que la forma de acceder a los elementos es mediante una clave nica. Por tanto, cada vez que
aadimos un elemento a una coleccin de este tipo tendremos que indicar
una clave y un valor. Cada valor estar relacionado con su correspondiente
clave.
Sabiendo esto, es fcil adivinar que si queremos acceder a un elemento, lo
normal es que lo hagamos usando la clave indicada al aadirlo. Los que
hayan trabajado anteriormente con Visual Basic 6.0, (o lo estn haciendo
actualmente), puede que piensen que tambin se podr acceder a cada elemento mediante un ndice numrico, ya que el objeto Collection de VB6,
(que an sigue existiendo en Visual Basic 2005), nos permite indicar una
clave para cada elemento, y adems de acceder a esos elementos mediante
la clave, podemos hacerlo mediante un valor numrico (ndice). Pero en las
colecciones basadas en IDictionary, salvo casos muy especiales, siempre
accederemos a los valores contenidos mediante la clave y "nunca" mediante
un ndice que haga referencia a la posicin dentro de la coleccin, entre
otras cosas porque cuando almacenamos valores en este tipo de colecciones,
stos no se guardan en el mismo orden en que fueron aadidos.
Nota.- Si bien la clase Collection est disponible en la nueva versin de
Visual Basic, sta tiene algunas mejoras con respecto a la que tiene
VB6, entre esas mejoras estn dos nuevos mtodos que nos facilitarn su uso: el mtodo Clear con el que podemos eliminar todos
los elementos de la coleccin y el mtodo Contains, con el que podemos averiguar si un determinado elemento est en la coleccin.
Entre las colecciones basadas en la interfaz IDictionary podemos destacar:
x
DictionaryBase, es una clase abstracta que podemos usar como base de nuestras propias colecciones de tipo diccionario.
222
Cursos
www.depurando.com
SortedList, es una coleccin en la que los elementos estn clasificados por las claves. Internamente utiliza una mezcla entre Hash
table y Array, segn la forma en que se accedan a esos elementos.
223
www.depurando.com
Nota.- Siempre que usemos un bucle For Each para recorrer los elementos
(o datos) de una coleccin, solo tendremos acceso de solo lectura a
esos datos, es decir, no podremos modificarlos usando la variable
por medio de la que accedemos a ellos.
Ver vdeos 62 Colecciones IList y 63 Colecciones IDictionary.
224
Cursos
www.depurando.com
Tal como hemos visto, en el espacio de nombres System.Collections tenemos dos clases abstractas que podemos usar como clases base para crear
nuestras propias colecciones.
Dependiendo que queramos crear una coleccin basada en IList, por ejemplo para acceder a los elementos mediante un ndice numrico, o bien una
coleccin basada en IDictionary, para almacenar los elementos usando el
par clave/valor, tendremos que usar la clase CollectionBase o Dictionary
Base.
Estas clases ya tienen cierta funcionalidad que podremos aprovechar para
no tener que reinventar la rueda, (sa es la "gracia" de la herencia), y lo nico que tendremos que hacer es definir nuestros propios mtodos o propiedades para que la coleccin acte como nosotros decidamos y, lo ms importante, para que solo acepte los tipos de datos que realmente queramos.
Por ejemplo, si queremos almacenar datos de tipo Cliente y queremos acceder a esos datos solo por un ndice numrico, podramos basar nuestra coleccin en CollectionBase, pero si lo que necesitamos es una coleccin que
contenga, por ejemplo, objetos de tipo Artculo, nos podra interesar crear
una coleccin basada en DictionaryBase para que de esta forma podamos
acceder a cada uno de los elementos por medio del cdigo del artculo.
A continuacin veremos el cdigo (reducido) para crear estos dos tipos de
colecciones personalizadas.
Nota.- En las definiciones de las colecciones que vamos a mostrar, no
hemos aadido ninguna funcionalidad extra, sino que hemos creado las clases/colecciones para que tengan un funcionamiento parecido al de las colecciones "normales". La diferencia principal con
esas colecciones "normales" es que estas dos clases/colecciones
que vamos a mostrar, solo admitirn elementos de un tipo concreto. Esto lo hemos hecho as para que podamos comparar y comprobar la facilidad que ahora tenemos si usamos colecciones del
espacio de nombres System.Collection.Generic.
Crear una coleccin basada en CollectionBase
225
www.depurando.com
A continuacin vamos a ver un ejemplo de una coleccin personalizada basada en CollectionBase y cmo usarla. Esta coleccin almacenar elementos
de un tipo definido por nosotros: Cliente.
Primero veamos una clase Cliente muy simple, pero que implementa la interfaz IComparable, de forma que se puedan clasificar sus elementos por el
campo Apellidos. Tambin define el mtodo ToString, ya que esta es una
recomendacin que siempre deberamos seguir, ya que muchas de las clases
de punto NET utilizan este mtodo para mostrar el contenido de los objetos.
226
Cursos
www.depurando.com
227
www.depurando.com
228
Cursos
www.depurando.com
229
www.depurando.com
Cursos
www.depurando.com
231
www.depurando.com
te. Si no fuera as, esta lnea producira un error, ya que estamos accediendo
a un tipo de datos que define una propiedad llamada Apellidos:
Cursos
www.depurando.com
Para acceder a los elementos de esta coleccin por medio de un bucle For
Each, en lugar de usar una variable de tipo DictionaryEntry debemos usar
una del tipo generic KeyValuePair en la que debemos especificar los tipos
de datos que contiene la coleccin:
Podemos comprobar que los tipos de datos que esta coleccin contiene son
de tipo String para las claves y de tipo Articulo para los valores. Dentro del
bucle hacemos una asignacin a la variable art, pero en este caso, a diferencia de cuando usamos la coleccin "Articulos" basada en DictionaryBase,
no es necesario hacer una conversin explcita del tipo que tiene de.Value a
un tipo Articulo, ya que de.Value es del tipo Articulo.
Esto mismo lo podemos comprobar al acceder a un elemento dentro del segundo bucle, esos son los tipos de datos que deben tener, ya que de lo contrario, no podramos acceder a la propiedad Descripcion del objeto almacenado:
233
www.depurando.com
Cursos
www.depurando.com
Nota.- Para facilitar la lectura de los tipos generics, se recomienda leer las
declaraciones genricas usando "de" y el tipo cuando nos encontremos con un tipo despus de Of. Por ejemplo: List(Of Cliente) lo
leeremos como una coleccin List de Cliente. Precisamente esa es
la razn de que en Visual Basic 2005 se haya optado por el uso de
la instruccin Of para los tipos generics.
Por ejemplo, si tenemos una clase de tipo Persona y la utilizamos como
clase base de un tipo Cliente y otro de tipo Empleado, podramos crear una
coleccin Generic.List que admita solo elementos del tipo Persona, con lo
cual podemos aadir tanto elementos de tipo Cliente y/o de tipo Empleado,
ya que estas dos clases se derivan de la clase Persona. En el siguiente cdigo tenemos las definiciones de estas tres clases y el cdigo para crear la coleccin generic:
La clase Persona:
La clase Cliente:
235
www.depurando.com
La clase Empleado:
Las colecciones y clases generic son bastante "potentes" y en principio fciles de utilizar, con el valor aadido (o ventaja) es que nosotros tambin podemos crear nuestros propios tipos de datos que utilicen esta nueva "tecnologa", pero su tratamiento en profundidad sobrepasa el objetivo de este curso, aunque con lo aqu expuesto creemos que el lector est preparado para
investigar por su cuenta, con la ayuda de la documentacin de Visual Studio
2005 y de los muchos recursos que estn disponibles tanto en formato "artculo Web" y en libros especializados en las novedades de Visual Basic
2005.
Ver vdeo 65 Colecciones Generis.
Streams en .NET
236
Cursos
www.depurando.com
Al empezar a trabajar con .NET, uno de los "grandes" cambios que notaremos los que estamos habituados a desarrollar con otros lenguajes es todo lo
relacionado con el acceso al contenido de los ficheros. En .NET, y por tanto
en Visual Basic 2005, el acceso a ficheros se realiza por medio de los
streams (o usando la traduccin de la documentacin: las secuencias).
Con los streams no solo podemos acceder a los ficheros de
disco, sino que tambin podemos acceder a otros tipos de
"secuencias" o flujos de datos, desde streams de memoria a
streams para enviar informacin a travs de Internet.
Toda esta transmisin o flujo de informacin se realiza mediante una serie
de mtodos de lectura y escritura que estn bsicamente encapsulados en la
clase abstracta Stream. Esta clase ser la clase base de todas aquellas que de
alguna forman tienen que transmitir cierta informacin entre la fuente de
datos y nuestra aplicacin.
En este captulo trataremos de las clases basadas en Stream que con ms
frecuencia utilizaremos, sobre todo en lo relacionado con el acceso a ficheros, que es al fin y al cabo la utilidad principal de este tipo de "secuencias".
Segn hemos comentado en la introduccin, los streams (o secuencias o flujos) nos permiten abstraernos de la forma en que estn implementados los
procesos de acceso a los ficheros u otros recursos. Todas las clases que manejan este tipo de flujos de datos estn basadas (directa o indirectamente) en
la clase Stream, la cual nos ofrece ciertos mtodos que nos permiten, entre
otras cosas, leer y escribir en esos flujos de informacin.
Adems de poder leer o escribir, tambin podemos realizar bsquedas o, dicho de otro modo, podemos movernos a travs de esa secuencia de datos.
Pero debido a que no todos los flujos de datos nos permiten realizar todas
las operaciones de la clase Stream, existen ciertas propiedades por medio de
las cuales podemos saber si se permiten todas las operaciones "bsicas" que
normalmente podremos hacer con los streams. Por ejemplo, es posible que
no podamos leer o escribir en una secuencia o que no podamos cambiar la
posicin del "puntero" de lectura o escritura. Para todas estas comprobaciones podremos usar las propiedades CanRead, CanWrite o CanSeek, pero
creo que antes de entrar en detalles, deberamos ver algunos de las clases
Visual Studio 2005
237
www.depurando.com
que .NET pone a nuestra disposicin para poder realizar este tipo de operaciones con "las secuencias" de datos
BufferedStream, clase abstracta que representa un buffer de almacenamiento para operaciones de lectura y escritura de otro stream.
Nota.- Las clases DeflateStream y GZipSteam estn incluidas en el espacio de nombres System.IO.Compression. La clase CryptoStream
est
incluida
en
el
espacio
de
nombres
System.Security.Cryptography. La clase NetworkStream est incluida
en el espacio de nombres System.Net.Sockets.
Adems de estas clases que se derivan directamente de la clase Stream, y
que normalmente se usan como "secuencias" a usar por otras clases de entrada/salida, tenemos otras que nos permitirn acceder a esas secuencias de
datos de una forma ms directa, (algunas de estas las veremos con algo de
238
Cursos
www.depurando.com
Cuando trabajamos con los streams debemos olvidarnos de las "cosas simples" y debemos tener en cuenta que trataremos casi siempre con secuencias
de bytes, ya que al fin y al cabo esa es la forma de almacenar la informacin
en los streams. Por tanto cuando veamos los ejemplos que la documentacin
de Visual Basic 2005 nos proporciona no debemos extraarnos de que haya
que hacer tantas "cosas" para acceder o manipular la informacin almacenada en esas "secuencias" de datos. Si bien, esa "complicacin" nos da mayor control sorbe el formato de la informacin contenida en los streams. Por
suerte, para los que nos gustan las cosas "simples" las clases especficas nos
facilitan mucho las cosas.
A continuacin veremos un par de ejemplos en los que manipularemos cierta informacin tanto en la memoria usando un objeto del tipo MemoryS
tream, como en un fichero de disco usando FileStream y las clases que casi
con seguridad usaremos habitualmente para acceder al contenido de los ficheros: StreamReader y StreamWriter.
Manejar un fichero usando FileStream
En este primer ejemplo veremos lo complicado que pude parecer acceder a
un fichero usando la clase FileStream y por extensin cualquier mtodo de
otras clases que devuelvan este tipo de secuencia, como por ejemplo los mtodos OpenRead, OpenWrite, etc. de la clase File.
Visual Studio 2005
239
www.depurando.com
La "complejidad" de esta clase es que realmente obtiene o guarda la informacin por medio de un array de tipo Byte, cuando a lo que estamos acostumbrados es a usar cadenas.
Nota.- Realmente, esta forma "binaria" de acceder a la informacin de un
fichero no la tenemos que ver como un inconveniente, ya que nos
puede servir para acceder de forma "binaria" a ese fichero, en caso
de que nuestra intencin sea acceder de forma "normal" para, por
ejemplo, leer solo texto, deberamos usar otras clases ms especializadas para esa tarea, como lo es StreamReader.
En el siguiente cdigo tenemos dos mtodos, uno que guarda una cadena en
el fichero indicado:
En el constructor de la clase FileStream indicamos el fichero en el que queremos guardar la informacin, tambin le indicamos que queremos crearlo o
abrirlo, es decir, si ya existe lo abre y si no existe lo crea, de cualquiera de
las formas, en el siguiente parmetro del constructor le indicamos que nuestra intencin es escribir en ese fichero.
Como hemos comentado, la clase FileStream (y en general todos los
streams) trabaja con bytes, por tanto para poder almacenar algo en ese fichero debemos hacerlo mediante un array de tipo Byte. En el caso de las ca240
Cursos
www.depurando.com
denas, stas siempre deben estar codificadas, es decir, deben usar el juego
de caracteres que creamos conveniente, en el mundo de .NET ese juego de
caracteres es Unicode, ms concretamente usando la codificacin UTF-8, la
cual permite trabajar con cualquier carcter de cualquier cultura. Como lo
que nos interesa es convertir una cadena en un array de bytes, usamos el
mtodo GetBytes de un objeto UTF8Encoding, el cual convierte la cadena
en una "ristra" de bytes con el formato adecuado, en este caso UTF-8. Si en
lugar de usar UTF-8 quisiramos usar otro "codificador", por ejemplo el
predeterminado de Windows, con idea de que los ficheros sean compatibles
con otras aplicaciones que utilizan el formato predeterminado de Windows,
tendremos que declarar la variable enc de la siguiente forma:
A continuacin, simplemente le pasamos el array de bytes al mtodo Write del FileStream indicando desde que posicin de dicho
array debe escribir y cuantos bytes.
Por ltimo nos aseguramos de que todos los bytes del "buffer" se
guarden en el fichero y lo cerramos.
241
www.depurando.com
En esta funcin vamos a leer los datos del fichero indicado, como
ya hemos vistos, la clase FileStream trabaja con bytes y esos bytes
los convertimos a caracteres por medio de las clases de codificacin especializadas. Por regla general, esas lecturas las haremos de
forma parcial, es decir leyendo bloques de bytes y como tenemos
que convertir esos bytes en caracteres, y puede ser que el fichero
sea muy grande, en lugar de concatenar una cadena para almacenar
las lecturas parciales, vamos a usar un objeto del tipo StringBuilder
en el que iremos "agregando" cada trozo ledo, de forma que el
rendimiento no se vea penalizado por la forma de ser de las cadenas, ya que cada vez que hacemos una concatenacin en una variable de tipo String, realmente estamos creando nuevos objetos en la
memoria y si son muchos, pues la verdad es que tendremos al recolector de basura (GC) trabajando a tope, y si usamos un objeto
StringBuilder el rendimiento mejora una barbaridad.
242
Cursos
www.depurando.com
A continuacin veremos cmo crear las dos funciones del ejemplo anterior
para que utilicen las clases "especializadas" para leer y escribir cadenas en
un fichero. Como podremos comprobar, esta es una forma muchsimo ms
simple y, por tanto recomendada para este tipo de acceso a los ficheros.
Aunque debemos recordar que solo servir para leer la informacin de forma secuencial y en formato cadena.
Nota.- El cdigo para usar estas dos funciones ser el mismo que el usado
para las funciones que utilizan la clase FileStream.
La funcin para guardar una cadena en un fichero:
Para leer los datos podemos hacerlo de dos formas: lnea a lnea o todo el
contenido de una sola vez. En el cdigo siguiente se muestra lnea a lnea, y
al final, (comentado), cmo hacerlo en una sola pasada.
243
www.depurando.com
Si nos decidimos a leer el contenido del fichero lnea a lnea, podemos usar
el mtodo Peek, el cual devolver el siguiente carcter del buffer del stream,
o -1 si no hay nada que leer. Peek no "consume" el carcter, simplemente
comprueba si hay algo que leer. Si hay algo que leer, leemos la lnea completa y la aadimos al objeto StringBuilder, el bucle se repetir mientras
haya informacin pendiente de leer.
Pero si optamos por la va rpida, porque realmente no nos interese procesar
cada lnea, podemos usar el mtodo ReadToEnd, que en nuestro ejemplo, el
valor devuelto ser todo el contenido del fichero, el cual asignamos a una
variable de tipo String para usarla como valor devuelto por la funcin, despus de cerrar el fichero.
Asegurarnos que el fichero se cierra
Si queremos ahorrarnos el paso intermedio de asignar el valor en una variable y despus devolverlo, tambin podemos hacerlo de esta forma:
244
Cursos
www.depurando.com
En este cdigo, cuando usamos Using sr, al ejecutarse End Using, el CLR
se encargar de llamar al mtodo Dispose de la clase, de forma que se liberen los recursos que estemos usando, en este ejemplo: el fichero abierto.
Estos dos ltimos ejemplos seran equivalentes a los anteriores, ms seguros, pero tambin con ms "trabajo" para el CLR.
Nota.- Using... End Using solo se puede usar con clases que implementen
la interfaz IDisposable, que es la que asegura que el objeto implementa el mtodo Dispose. Por tanto, si implementamos el mtodo
IDisposable.Dispose en nuestras clases, en ese mtodo nos tenemos que asegurar que liberamos los recursos que nuestra clase est
utilizando.
Ejemplo de para cifrar y descifrar un fichero
En el siguiente ejemplo (adaptado de uno de la documentacin), veremos
cmo usar algunas de las clases basadas en Stream, particularmente las clase MemoryStream, FileStream, CryptoStream adems de las clases Stream
Reader y StreamWriter.
Este cdigo tiene dos funciones: La primera encripta (cifra) una cadena y la
guarda en un fichero. La segunda desencripta (descifra) el contenido de un
fichero y lo guarda en otro. Ambas funciones devuelven la cadena cifrada o
descifrada respectivamente.
Visual Studio 2005
245
www.depurando.com
246
Cursos
www.depurando.com
247
www.depurando.com
Veamos primero una relacin de esas clases y enumeraciones y despus veremos algunas de ellas con ms detalle.
Clases para manipular unidades, directorios y ficheros
Entre las clases que nos permiten trabajar con los ficheros, directorios y las
unidades de disco, podemos destacar las siguientes:
248
Cursos
www.depurando.com
FileInfo, igual que la clase File, pero los mtodos son de instancia,
dicha instancia se crear a partir de un fichero determinado.
249
www.depurando.com
BufferedStream, clase abstracta que representa un buffer de almacenamiento para operaciones de lectura y escritura de otro stream.
StreamReader, lee caracteres desde un FileStream, usando codificacin para convertir los caracteres a/desde bytes.
StreamWriter, escribe caracteres a un FileStream, usando codificacin para convertir los caracteres en bytes.
250
Cursos
www.depurando.com
Nota.- La clase abstracta Stream est diseada para entrada y salida de bytes, las clases abstractas TextReader y TextWriter estn diseadas
para la entrada/salida de caracteres Unicode.
Las clases Directory y DirectoryInfo
Cuando necesitemos acceder a un directorio, por ejemplo, para saber que
subdirectorios y ficheros contiene o para obtener otro tipo de informacin,
incluso para saber si existe o no, en esos casos podemos utilizar las clases
Directory o DirectoryInfo.
La primera de ellas: Directory, proporciona mtodos estticos, es decir, los
mtodos que contienen siempre estarn disponibles sin necesidad de crear
una nueva instancia de la clase. Por tanto, podremos usar esos mtodos simplemente usando la propia clase.
La segunda: DirectoryInfo, proporciona los mismos mtodos que Directory,
pero en lugar de ser mtodos estticos, son mtodos de instancia, es decir,
esos mtodos solamente se podrn usar despus de haber creado una instancia (u objeto en memoria) de esta clase. Cada una de las instancias de Di
rectoryInfo, har referencia a un directorio en particular, ese directorio se
indicar al crear el objeto, aunque tambin puede ser que est referenciado
al obtenerlo mediante otros mtodos que devuelven este tipo de objetos.
251
www.depurando.com
Nota.- El directorio asignado al crear la instancia de DirectoryInfo no tiene porqu existir. De esa forma podemos comprobar si existe, y en
caso de que no exista, crearlo, etc.
Por ejemplo, si queremos saber si un directorio existe, utilizaremos el mtodo Exists, en el caso de la clase Directory, como parmetro le indicaremos
el directorio del que queremos comprobar su existencia, sin embargo, si
usamos un objeto del tipo DirectoryInfo, no necesitamos indicar ningn parmetro, ya que el directorio que est asociado con esa clase lo habremos
indicado al crear el objeto.
En el siguiente cdigo vemos cmo usar estas dos clases:
252
Cursos
www.depurando.com
El resto de mtodos de estas dos clases funcionan de forma similar, al menos en el sentido de que si usamos la clase Directory, siempre habr un parmetro que haga referencia al directorio que queremos usar, mientras que
con DirectoryInfo siempre estar haciendo referencia al directorio usado al
crear la instancia.
Nota.- No queremos parecer repetitivos, pero nos interesa que quede
claro como funcionan este tipo de clases, que por otro lado, ser
similar al de las clases File y FileInfo, al menos en el sentido de
que la clase con los mtodos estticos siempre necesitar saber a
que elemento del sistema de archivos estamos refirindonos, mientras que las clases que debemos instanciar, siempre sabrn con que
elemento trabajarn.
Los mtodos de las clases Directory y DirectoryInfo
Estas clases siempre manejarn directorios y entre los mtodos que podemos utilizar, destacamos los siguientes, empezamos por la clase Directory:
x
GetDirectories, devuelve un array de String con todos los subdirectorios del directorio indicado. Se puede indicar un "pattern" de
y hora universal
253
www.depurando.com
GetFiles, devuelve un array de tipo String con los ficheros del directorio indicado. Se puede indicar un filtro de bsqueda.
GetLogicalDrives, devuelve un array con los nombres de las unidades lgicas en el formato: "<letra>:\".
254
Cursos
www.depurando.com
255
www.depurando.com
256
Cursos
www.depurando.com
257
www.depurando.com
258
Cursos
www.depurando.com
259
www.depurando.com
260
Cursos
www.depurando.com
261
www.depurando.com
262
Cursos
www.depurando.com
Nota.- Debido a que la clase Path solo maneja cadenas, podemos usar los
mtodos de esta clase con nombres de ficheros o directorios que no
existen, y por tanto, cualquier cambio que hagamos en esos parmetros, no afectarn a ningn fichero ni directorio.
Debido a que los ensamblados de .NET podemos usarlos con diferentes sistemas operativos (al menos en teora), esta clase proporciona ciertas propiedades que nos permiten averiguar los caracteres especiales de cada sistema,
por ejemplo para saber el separador usado por los directorios.
Con esta clase tambin podemos crear ficheros con nombres temporales, de
forma que nos aseguremos de que no habr otro fichero "temporal" con el
mismo nombre. Igualmente, por medio del mtodo GetTempPath podemos
averiguar el directorio temporal del sistema.
Incluso podemos generar nombres aleatorios "seguros" para ficheros o directorios mediante el mtodo GetRandomFileName.
Veamos un ejemplo para generar estos nombres temporales y aleatorios:
and
Settings\Alguien\Local
Set-
263
www.depurando.com
264
Cursos
www.depurando.com
Figura 4.3
Aunque esta deteccin automtica solo funcionar con los tipos de ficheros
que guardan dicha informacin, que son los tipos: UTF-8, UTF-16 y UTF32, de estos dos ltimos existen dos marcas segn se utilice "big-endian" o
"little-endian", es decir, si el byte ms significativo est al principio o al final respectivamente. Estas marcas, conocidas en .NET como "prembulos",
se pueden averiguar tambin por medio del mtodo GetPreamble de la clase
Encoding.
En la siguiente tabla podemos ver los valores hexadecimales de las marcas
usadas en los ficheros.
265
www.depurando.com
Si queremos que los ficheros que manejemos con nuestra aplicacin de Visual Basic 2005 sean "compatibles", por ejemplo, con
los de VB6, deberamos usar la codificacin Encoding.Default.
Si los ficheros solo se usarn desde aplicaciones de .NET, podemos usar la codificacin predeterminada, es decir: UTF-8.
266
Cursos
www.depurando.com
Si vamos a guardar ficheros XML, deberamos usar siempre codificacin UTF-8, que es la predeterminada para ese formato de ficheros.
Acceso a Internet
Esta es otra de las reas con la que los desarrolladores de VB6 se vern beneficiados, al menos si nuestra intencin es la acceder a la red de redes: Internet.
Aunque tambin tendremos clases para interactuar con nuestra red local o
empresarial, adems de clases para comunicacin por "sockets" y acceso a
FTP, etc.
La mayora de las clases que necesitemos para acceder a la red, las encontraremos en el espacio de nombres System.Net.
267
www.depurando.com
HttpListenerContext, proporciona acceso a las peticiones y respuestas utilizadas por la clase HttpListener.
HttpListenerResponse, representa una respuesta a una peticin administrada por un objeto HttpListener.
268
Cursos
www.depurando.com
IPHostEntry, proporciona una clase contenedora para la informacin de direccin de host de Internet.
WebClient, proporciona mtodos comunes para enviar o recibir datos desde un recurso identificado por una URI (Uniform Resource
Identifier).
SocketPermission, controla los derechos para realizar o aceptar conexiones en una direccin de transporte.
269
www.depurando.com
WebRequestMethods.File, representa los tipos del protocolo de fichero que se pueden usar con una peticin FILE.
270
Cursos
www.depurando.com
271
www.depurando.com
272
Cursos
www.depurando.com
273
www.depurando.com
Acceso a datos
274
Cursos
www.depurando.com
Descripcin ADO.NET
A continuacin veremos todo lo que debe saber sobre ADO.NET para crear
aplicaciones que accedan a fuentes de datos desde Visual Basic 2005. Comprobar que ahora, es incluso mucho ms fcil y rpido, si bien, es necesario
conocer el modelo con el que se trabaja para poder saber lo que deberemos
hacer en un momento dado.
Acercndonos a ADO.NET
ADO.NET ha sufrido a lo largo de los ltimos aos diferentes mejoras y actualizaciones, desde que .NET apareci. El resumen de las diferentes versiones de ADO.NET podra quedar de la siguiente forma. ADO.NET 1.0
apareci con Microsoft .NET Framework 1.0. Posteriormente, ADO.NET
1.1 sufri una pequeas y casi inapreciables actualizaciones con la aparicin
de Microsoft .NET Framework 1.1. En el caso del entorno Visual Studio
2005, ste trabaja con Microsoft .NET Framework 2.0 y por lo tanto, utiliza
ADO.NET 2.0, el cul aade algunas caractersticas nuevas adicionales.
En nuestro caso, nos centraremos nica y exclusivamente en ADO.NET
como modelo de objetos de acceso a datos para la plataforma .NET de Microsoft, ya que es el mismo para cualquier tipo de versin de ADO.NET.
Qu es ADO.NET?
275
www.depurando.com
276
Cursos
www.depurando.com
Figura 1
System.Data
277
www.depurando.com
Las clases del nombre de espacio System.Data son bastantes extensas y variadas. Quizs las clases ms importantes son la clase DataView, la clase
DataSet y la clase DataTable.
La clase DataSet
El DataSet es una representacin de datos residente en memoria que proporciona una modelo de programacin relacional coherente independientemente del origen de datos que contiene. El DataSet contiene en s, un conjunto de datos que han sido volcados desde el proveedor de datos.
Debemos tener en cuenta que cuando trabajamos con DataSets, el origen de
datos no es lo ms importante, ya que ste, puede ser cualquier tipo de origen de datos. No tiene porqu ser una base de datos.
Un DataSet contiene colecciones de DataTables y DataRelations. El Data
Table contiene una tabla o tablas, mientras que la DataRelation contiene las
relaciones entre las DataTables. Sin embargo, no es necesario especificar
todo esto hasta el ltimo detalle como veremos ms adelante.
La clase DataView
Este objeto nos permite crear mltiples vistas de nuestros datos, adems de
permitirnos presentar los datos.
Es la clase que nos permite representar los datos de la clase DataTable,
permitindonos editar, ordenar y filtrar, buscar y navegar por un conjunto
de datos determinado.
La clase DataTable
Este objeto nos permite representar una determinada tabla en memoria, de
modo que podamos interactuar con ella.
A la hora de trabajar con este objeto, debemos tener en cuenta el nombre
con el cul definamos una determinada tabla, ya que los objetos declarados
en el DataTable son sensitivos a maysculas y minsculas.
278
Cursos
www.depurando.com
Los proveedores
de acceso a datos
Los proveedores de acceso a datos es
la capa inferior de la parte correspondiente al acceso de datos y es la responsable de establecer la comunicacin con las fuentes de datos.
279
www.depurando.com
Estos proveedores de acceso a datos incluidos en Microsoft .NET Framework, los podemos encontrar en los nombres de espacio:
x
System.Data.Odbc
System.Data.OleDb
System.Data.OracleClient
System.Data.SqlClient
280
Cursos
www.depurando.com
El proveedor Oracle Client .NET es un proveedor de acceso a datos especialmente diseado para bases de datos Oracle.
Por ltimo, el proveedor SQL Server .NET es un proveedor de acceso a datos nativo, que nos permite conectar nuestras aplicaciones a fuentes de datos
Microsoft SQL Server 7 o posterior. Se trata de un proveedor especfico para bases de datos Microsoft SQL Server 7.0, Microsoft SQL Server 2000 y
Microsoft SQL Server 2005.
Consejo.- Siempre que pueda, utilice para acceder a fuentes de datos, un
proveedor de acceso a datos nativo. Esto le permitir aumentar
considerablemente el rendimiento a la hora de establecer la
conexin con una determinada fuente de datos.
Los proveedores de acceso a datos que distribuye Microsoft en ADO.NET y
algunos desarrollados por otras empresas o terceros, contienen los mismos
objetos, aunque los nombres de stos, sus propiedades y mtodos, pueden
ser diferentes. Ms adelante veremos algn ejemplo, y observar en la prctica cules son estas diferencias ms destacables.
Otros proveedores de acceso a datos
Si bien el proveedor de acceso a datos es el mecanismo a travs del cul podemos establecer una comunicacin nativa con una determinada fuente de
datos, y dado que Microsoft proporciona los proveedores de acceso a datos
ms corrientes, es cierto que no los proporciona todos, si bien, con OLE DB
y ODBC, podemos acceder a la inmensa totalidad de ellos.
Sin embargo, hay muchos motores de bases de datos de igual importancia
como Oracle, MySql, AS/400, etc. En estos casos, si queremos utilizar un
proveedor de acceso a datos nativo, deberemos acudir al fabricante o a empresas o iniciativas particulares para que nos proporcionen el conjunto de
clases necesarias que nos permitan abordar esta accin.
El objeto Connection
Este objeto es el encargado de establecer una conexin fsica con una base de datos
determinada. Para establecer la conexin con una determinada fuente de datos, no
Visual Studio 2005
281
www.depurando.com
El objeto Command
Este objeto es el que representa una determinada sentencia SQL o un Stored
Procedure. Aunque no es obligatorio su uso, en caso de necesitarlo, lo utilizaremos conjuntamente con el objeto DataAdapter que es el encargado de
ejecutar la instruccin indicada.
El objeto DataAdapter
Este objeto es quizs el objeto ms complejo y a la vez complicado de todos
los que forman parte de un proveedor de acceso a datos en .NET. Cuando
deseamos establecer una comunicacin entre una fuente de datos y un Da
taSet, utilizamos como intermediario a un objeto DataAdapter. A su vez, un
DataAdapter contiene 4 objetos que debemos conocer:
x
Cursos
www.depurando.com
El objeto DataReader
Este objeto es el utilizado en una sola direccin de datos. Se trata de un objeto de acceso a datos muy rpido. Este objeto puede usar a su vez el objeto
Command o el mtodo ExecuteReader.
Ver vdeo 75 Los proveedores de acceso a datos.
El concepto DataBinding
DataBinding es una expresin de enlace a datos. Como veremos a continuacin es una forma rpida y sencilla de manejar la fuentes de datos mediante
su enlace con controles o clases.
El uso de DataBind
El mtodo DataBind se utiliza para rellenar de datos un determinado control
o clase. Muchos controles y clases, posee este mtodo al que le asignaremos
un conjunto de datos para que se rellene con ellos, pudiendo despus interactuar con los datos de forma directa.
En s, un DataBinding es un enlace a datos que se encarga de rellenar de datos a un determinado control o clase. Como ejemplo de esto, veremos como
rellenar un control TextBox con un dato utilizando este mtodo.
Iniciaremos una nueva aplicacin Windows y escribiremos el siguiente cdigo fuente:
Cdigo
Imports System.Data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Forml
Private Sub Form1 Load (ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MyBase.Load
Dim Conexin As String Server .;uid sa;password VisualBasic; _
database MSDNVideo
Visual Studio 2005
283
www.depurando.com
Otras consideraciones
Dentro de las conexiones a fuentes de
datos, hay algunas partes de stas que
permanecen a veces en el olvido y su
importancia sin embargo, es bastante
grande.
La accin ms pesada cuando realizamos un acceso a una fuente de datos,
se encuentra en la conexin con la fuente de datos. Esa tarea, simple tarea,
es la que ms recursos del sistema consume cuando accedemos a fuentes de
datos.
Esto lo debemos tener en cuenta, y por lo tanto, variante de esto que comentamos son las siguientes premisas:
x
La conexin debe realizarse siempre que se pueda, con los proveedores de acceso a datos nativos, que por lo general salvo raras excepciones, sern ms rpidos que los accesos a fuentes de datos a
travs de proveedores del tipo OLE DB y ODBC.
284
Cursos
www.depurando.com
El paradigma de la conexin
Cuando abordamos un proyecto de acceso a fuentes de datos, siempre nos
encontramos con una duda existencial. Debemos crear una conexin con la
base de datos al principio de nuestra aplicacin y cerrarla cuando la aplicacin se cierre?, o debemos crear una conexin con la base de datos slo
cuando vayamos a trabajar con la fuente de datos?. Y si estamos trabajando continuamente con una fuente de datos?, cmo penalizaran todas estas
acciones?
Es difcil de asumir que accin tomar en cada caso, y es que dependiendo de
lo que vayamos a realizar, a veces es ms efectiva una accin que otra, y en
Visual Studio 2005
285
www.depurando.com
otras ocasiones, no est del todo claro, ya que no existe en s una regla clara
que especifique qu accin tomar en un momento dado.
Lo que s est claro es que el modelo de datos de ADO.NET que hemos visto, quedara resumido en cuanto a la conectividad de la manera en la que se
representa en la figura 1.
Figura 1
El objeto DataSet nos ofrece la posibilidad de almacenar datos, tablas y bases de datos de una determinada fuente de datos. De esta manera, podemos
trabajar con las aplicaciones estando desconectados de la fuente de datos.
Sin embargo, a veces necesitamos trabajar con la fuente de datos estando
conectados a ella. El objeto DataReader nos ofrece precisamente la posibilidad de trabajar con fuentes de datos conectadas.
Por otro lado, el objeto DataReader tiene algunas particularidades que conviene conocer y que veremos a continuacin.
Vdeo 79 El paradigma de la conexin.
286
Cursos
www.depurando.com
Connection
287
www.depurando.com
Command
DataReader
Figura 1
Cursos
www.depurando.com
289
www.depurando.com
Cursos
www.depurando.com
If bolAccion Then
True > Establecemos la conexin
Comando New SqlCommand(strSQL, MiConexion)
Abrimos la conexin
MiConexion.Open()
Ejecutamos la secuencia SQL
MiDataReader Comando.ExecuteReader()
Obtenemos la cantidad de registros obtenidos
Contador MiDataReader.VisibleFieldCount() + 1
Else
False > Finalizamos la conexin
Button1.Enabled False
Cerramos la conexin
Comando Nothing
MiConexion.Close()
End If
End Sub
Private Sub Button1 Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button1.Click
Recorremos los registros y los mostramos
Posicion + 1
MiDataReader.Read()
TextBox1.Text MiDataReader(TITULO)
Si hemos recorrido el onjeto por completo, finalizamos la conexin y
deshabilitamos el control Button que nos permite recuperar los requisitos
If Posicion Contador Then
establecer_Conexion(False)
EndIf
End Sub
End Class
Observar que la aplicacin sigue funcionando. En este punto se har la pregunta que todos
nos hemos hecho, no es el objeto DataReader
un objeto conectado?, cmo es posible que
funcione si hemos detenido el servicio de SQL
Visual Studio 2005
291
www.depurando.com
Server?
La respuesta es sencilla. El objeto DataReader recupera un nutrido conjunto de valores llenando un pequeo buffer de datos e informacin. Si el nmero de registros que hay en el buffer se acaban, el objeto DataReader regresar a la fuente de datos para recuperar ms registros. Si el servicio de
SQL Server est detenido en ese momento o en su caso, la fuente de datos
est parada, la aplicacin generar un error a la hora de leer el siguiente registro.
En s, DataReader es un objeto conectado, pero trabaja en background con
un conjunto de datos, por lo que a veces nos puede resultar chocante su
comportamiento como el ejemplo que comento.
Ver vdeo 82 Trabaja DataReader en un ambiente conectado realmente?.
292
Cursos
www.depurando.com
293
www.depurando.com
En este caso, lo que ocurre como ya hemos comentado, es que los datos que
se cargan son los que an no han sido ledos en el objeto DataReader, por lo
que se mostrarn todos los datos desde el ltimo ledo hasta llegar al final
del objeto.
Ver vdeo 83 Carga segmentada de datos con DataSource y DataReader.
Cursos
www.depurando.com
295
www.depurando.com
Figura 1
Cursos
www.depurando.com
Figura 1
297
www.depurando.com
298
Cursos
www.depurando.com
299
www.depurando.com
300
Cursos
www.depurando.com
Figura 5
301
www.depurando.com
Figura 8
Componentes aadidos en el
formulario de nuestra aplicacin ?
Una vez que tenemos todo preparado, tan slo nos queda escribir la
parte de cdigo fuente necesaria para poder realizar todas las operaciones y
acciones que necesitamos. A continuacin, se expone el cdigo fuente de
nuestra aplicacin de demostracin:
302
Cursos
www.depurando.com
Ahora nos queda nicamente ejecutar nuestra aplicacin para estudiar el resultado final. Este es el que se puede ver en la figura 9.
? Figura 9 Ejemplo en ejecucin del uso
de componentes
303
www.depurando.com
Cursos
www.depurando.com
Figura 1
Finalmente, escribiremos el cdigo necesario para ejecutar nuestra aplicacin tal y como queremos. Este es el que se detalla a continuacin:
Cdigo
Public Class Forml
Visual Studio 2005
305
www.depurando.com
Cursos
www.depurando.com
307
www.depurando.com
Cursos
www.depurando.com
SqlCommand1.Connection SqlConnection1
Le indicamos al DataAdapter, cul es el comando de actualizacin que usaremos
SqlDataAdapter1.UpdateCommand SqlCommand1
Aadimos los parmetros y comandos correspondientes para cada campo a
actualizar en la base de datos
SqlCommand1.Parameters.Add(@NIF, Data.SqlDbType.NChar, 10, NIF)
SqlCommand1.Parameters.Add(@Nombre, DataSqlType.NVarChar, 50, _
Nombre)
SqlCommand1.Parameters.Add(@Apellido1, DataSqlType.NVarChar, 50,
Apellido1)
SqlCommand1.Parameters.Add(@Apellido2, DataSqlType.NVarChar, 50,
Apellido2)
SqlCommand1.Parameters.Add(@Telefono, DataSqlType.NVarChar, 13, _
Telefono)
SqlCommand1.Parameters.Add(@Email, DataSqlType.NVarChar, 50, Email)
SqlCommand1.Parameters.Add(@Direccion, DataSqlType.NVarChar, 100,
Direccion)
SqlCommand1.Parameters.Add(@Ciudad, DataSqlType.NVarchar, 50, _
Ciudad)
SqlCommand1.Parameters.Add(@Provincia, DataSqlTypeNVarChar, 50,
Provincia)
SqlCommand1.Parameters.Add(@CP, DataSqlTypeNChar, 5, CP)
Abrimos la conexin
SqlConnection1.Open()
Realizamos la actualizacin de datos desde el DataSet a travs del DataAdapter
SqlDataAdapter1.Update(DataSet1, Ejemplo)
Cerramos la conexin
SqlConnection1.Close()
Indicamos con un mensaje que la actualizacin de datos se ha realizado con
xito
MessageBox.Show(Datos actualizados Correctamente)
End If
End Sub
End Class
309
www.depurando.com
Cursos
www.depurando.com
Apellido2)
SqlCommand1.Parameters.Add(@Telefono, DataSqlTypeNVarChar, 13, _
Telefono)
SqlCommand1.Parameters.Add(@Email, DataSqlTypeNVarChar, 50, Email)
SqlCommand1.Parameters.Add(@Direccion, DataSqlTypeNVarChar, 100,
Direccion)
SqlCommand1.Parameters.Add(@Ciudad, DataSqlTypeNVarChar, 50, _
Ciudad)
SqlCommand1.Parameters.Add(@Provincia, DataSqlTypeNVarChar, 50,
Provincia)
SqlCommand1.Parameters.Add(@CP, DataSqlTypeNChar, 5, CP)
Abrimos la conexin
SqlConnection1.Open()
Realizamos la eliminacin de datos desde el DataSet a travs del DataAdapter
SqlDataAdapter1.Update(DataSet1, Ejemplo)
Cerramos la conexin
SqlConnection1.Close()
Indicamos con un mensaje que la eliminacin de datos se ha realizado con xito
MessageBox.Show(Datos eliminados correctamente)
End If
En Sub
End Class
DataSets tipados
Otra particularidad de .NET a la hora de trabajar con fuentes de datos y con
los componentes y controles que nos permiten acceder a ellas, es el trabajo
con dos tipos de DataSets.
Sin quererlo ya hemos visto como trabajar con uno de ellos, me refiero a los
DataSets no tipados, sin embargo, hay otro tipo de DataSet diferente denominado as, DataSet tipado.
Visual Studio 2005
311
www.depurando.com
Cursos
www.depurando.com
313
www.depurando.com
Figura 1
Este diagrama nos ayudar a interpretar los datos y a trabajar con ellos, en
los ejemplos que veremos a continuacin.
A continuacin, veremos como generar DataSets tipados desde el entorno
de trabajo rpido, es decir Visual Studio 2005, y desde la lnea de comandos.
Ver Vdeo 93 Generando nuestros DataSets tipados.
314
Cursos
www.depurando.com
La forma ms rpida para generar DataSets tipados es utilizando las herramientas automticas del entorno Visual Studio 2005.
A continuacin veremos como hacer esto de manera rpida y sencilla.
Usando el entorno de desarrollo rpido Visual Studio 2005
Cree un nuevo proyecto de Aplicacin para Windows y haga clic con el botn secundario del mouse sobre la ventana Explorador de soluciones, y del
men emergente, seleccione la opcin Agregar > Nuevo elemento..., tal y
como se muestra en la figura 1.
Figura 1
315
www.depurando.com
Figura 2
Cursos
www.depurando.com
Figura 5
Esquema de la tabla Socios
aadido al entorno de trabajo ?
317
www.depurando.com
<auto generated>
Una herramienta gener este cdigo
Versin del motor en tiempo de ejecucin:2.0.50215.44
Cursos
www.depurando.com
Inherits System.Data.DataSet
Private tableSocios As SociosDataTable
Private schemaSerializationMode As System.Data.SchemaSeralizationMode
System.Data.SchemaSerializationMode.IncludeSchema
<System.Diagnostics.CodeAnalysis.SuppressMessageAtribute(Microsoft.Usage,_
CA2214:DoNotCallOverridableMethodsInConstructors)>
Public Sub New()
MyBase.New
Me.BeginInit
Me.InitClass
Dim SchemaChangedHandler As System.ComponentMode1
CollectionChangeEventHandler AddressOf Me.SchemaChanged
AddHandler MyBase.Tables.CollectionChanged, SchemaChangedHandler
AddHandler MyBase.Relations.CollectionChanged, SchemaChangedHandler
Me.EndInit
End Sub
<System.Diagnostics.CodeAbalysis.SuppressMessageAttribute(MicrosoftUsage,
CA2214:DoNotCallOverridableMethodsInConstructors)> _
Protected Sub New(ByVal info As System.Runtime.Serialization.Info, ByVal contex As _
System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
If (Me.IsBinarySerialized(info, context) true) Then
Me.InitVars(false)
Dim schemaChangedhandler1 As System.ComponentMode1. _
CollectionChangeEventHaqndler AddressOf Me.SchemaChanged
AddHandler Me.Tables.CollectionChanged, schemaChangeHandler1
AddHandler Me.relations.CollectionChanged, schemaChangeHandler1
Return
End If
Dim strSchema As String CType(info.GetValue(XmlSchema,
GetType (String)), String)
If (Me.DetermineSchemaSerializationMode(info, context)
System.Data.SchemaSerializationMode.IncludeSchema)Then
Dim ds As System.Data.DataSet New System.Data.DataSet
ds.ReadXmlSchema(New System.Xml.XmlTextReader(New
System.IO.StringReader(strSchema)))
If (Not (ds.Tables(Socios)) Is Nothing) Then
MyBase.Tables.Add(New SociosDataTable(ds.Tables(Socios)))
End If
Me.DataSetname ds.DataSetName
Me.Prefix ds.Prefix
Me.Namespace ds.Namespace
Me.Locale ds.Locale
Me.CaseSensirive ds.caseSensitive
Visual Studio 2005
319
www.depurando.com
Cursos
www.depurando.com
321
www.depurando.com
End Sub
Friend Overloads Sub InitVars(ByVal initTable As Boolean)
Me.tableSocios CType(MyBase.Tables("Socios"),SociosDataTable)
If (initTable true) Then
If (Not (Me.tableSocios) Is Nothing) Then
Me.tableSocios.InitVars
End If
End if
End sub
Private Sub InitClass()
Me.DataSetName "DataSet1"
Me.Prefix ""
Me.Namespace http://tempuri.org/DataSet1.xsd
Me.EnforceConstraints true
Me.tableSocios New SociosDataTable
MyBase.Tables.Add(Me.tableSocios)
End Sub
Private Function ShouldSerializeSocios() As Bolean
Return false
End Function
Private Sub SchemaChanged(ByVal sender As Object, ByVal e As
System.ComponentModel.CollectionChangeEventArgs)
If (e.Action System.ComponentModel. _
CollectionChangeAction.Remove) Then
Me.InitVars
End If
End sub
Public Shared Function GetTypedDataSetSchema(ByVal xs As _
System.Xml.Schema.XmlSchemaSet) As System.Xml.Schema.XmlSchemaComplexType
Dim ds As DataSet1 New DataSet1
Dim type As System.Xml.Schema.XmlSchemaComplexType
New System.Xml.Schema.XmlSchemaComplexType
Dim sequence As System.Xml.Schema.XmlSchemaSequence _
New System.Xml.Schema.XmlSchemaSequence
xs.Add(ds.GetSchemaSerializable)
Dim any As System.Xml.Schema.XmlSchemaAny
New System.Xml.Schema.XmlSchemaAny
any.Namespace ds.Namespace
sequence.Items.Add(any)
type.Particle sequence
Return type
End Function
322
Cursos
www.depurando.com
"Socios"
323
www.depurando.com
End If
Me.Prefix table.Prefix
Me.MinimumCapacity table.MinimumCapacity
End Sub
Protected Sub New(ByVal info As System.Runtime.Serialization.SerializationInfo,
ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
Me.InitVars
End Sub
Public ReadOnly Property NIFColumn() As System.Data.DataColumn
Get
Return Me.columnNIF
End Get
End Property
Public ReadOnly Property NombreColumn() As System.Data.DataColumn
Get
Return Me.columnNombre
End Get
End Property
Public ReadOnly Property Apellido1Column() As System.Data.DataColumn
Get
Return Me.columnApellido1
End Get
End Property
Public ReadOnly Property Apellido2Column() As System.Data.DataColumn
Get
Return Me.columnApellido2
End Get
End Property
Public ReadOnly Property TelefonoColumn() As System.Data.DataColumn
Get
Return Me.columnTelefono
End Get
End Property
Public ReadOnly Property EmailColumn() As System.Data.DataColumn
Get
Return Me.columnEmail
End Get
End Property
Public ReadOnly Property DireccionColumn() As System.Data.DataColumn
324
Cursos
www.depurando.com
Get
Return Me.columnDireccion
End Get
End Property
Public ReadOnly Property CiudadColumn() As System.Data.DataColumn
Get
Return Me.columnCiudad
End Get
End Property
Public ReadOnly Property ProvincialColumn() As System.Data.DataColumn
Get
Return Me.columnProvincia
End Get
End Property
Public ReadOnly Property CPColumn() As System.Data.DataColumn
Get
Return Me.columnCP
End Get
End Property
<System.ComponentModel.Browsable(false)>
Public ReadOnly Property Count() As Integer
Get
Return Me.Rows.Count
End Get
End Property
Public Default ReadOnly Property Item(ByVal index As Integer) As SociosRow
Get
ReturnCType(Me.Rows(index),SociosRow)
End Get
End Property
Public Event SociosRowChanged As SociosRowChangeEventHandler
Public Event SociosRowChanging As SociosRowChangeEventHandler
Public Event SociosRowDeleted As SociosRowChangeEventHandler
Public Event SociosRowDeleting As SociosRowChangeEventHandler
Public Overloads Sub AddSociosRow(ByVal row As SociosRow)
Me.Rows.Add(row)
End Sub
325
www.depurando.com
Cursos
www.depurando.com
327
www.depurando.com
System.Data.DataRowBuilder) As System.Data.DataRow
Return New SociosRow(builder)
End Function
Protected Overrides Function GetRowType() As System.Type
Return GetType(SociosRow)
End Function
Protected Overrides Sub OnRowChanged(ByVal e As
System.Data.DataRowChangeEventArgs)
MyBase.OnRowChanged(e)
If (Not (Me.SociosRowChangedEvent) Is Nothing) Then
RaiseEvent SociosRowChanged(Me, New _
SociosRowChangeEvent(CType(e.Row,SociosRow), e.Action))
End If
End Sub
Protected Overrides Sub OnRowChanging(ByVal e As _
System.Data.DataRowChangeEventArgs)
MyBase.OnRowChanging(e)
If (Not (Me.SociosRowChangingEvent) Is Nothing) Then
RaiseEvent SociosRowChanging(Me, New _
SociosRowChangeEvent(CType(e.Row,SociosRow), e.Action))
End If
End Sub
Protected Overrides Sub OnRowDeleted(ByVal e As _
System.Data.DataRowChangeEventArgs)
MyBase.OnRowDeleted(e)
If (Not (Me.SociosRowDeletedEvent) Is Nothing) Then
RaiseEvent SociosRowDeleted(Me, New
SociosRowChangeEvent(CType(e.Row,SociosRow), e.Action))
End If
End Sub
Protected Overrides Sub OnRowDeleting(ByVal e As
System.Data.DataRowChangeEventArgs)
MyBase.OnRowDeleting(e)
If (Not (Me.SociosRowDeletingEvent) Is Nothing) Then
RaiseEvent SociosRowDeleting(Me, New
SociosRowChangeEvent(CType(e.Row,SociosRow), e.Action))
End If
End Sub
Public Sub RemoveSociosRow(ByVal row As SociosRow)
Me.Rows.Remove(row)
End Sub
328
Cursos
www.depurando.com
329
www.depurando.com
Get
Return CType(Me(Me.tableSocios.NIFColumn),String)
End Get
Set
Me(Me.tableSocios.NIFColumn) value
End Set
End Property
Public Property Nombre() As String
Get
Try
Return CType(Me(Me.tableSocios.NombreColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la
'Nombre' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.NombreColumn) value
End Set
End Property
Public Property Apellido1() As String
Get
Try
Return CType(Me(Me.tableSocios.Apellido1Column),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de _
la columna 'Apellido1' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.Apellido1Column) value
End Set
End Property
Public Property Apellido2() As String
Get
Try
Return CType(Me(Me.tableSocios.Apellido2Column),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor _
de la columna 'Apellido2' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.Apellido2Column) value
End Set
330
Cursos
www.depurando.com
End property
Public Property Telefono() As String
Get
Try
Return CType(Me(Me.tableSocios.TelefonoColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'Telefono' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.TelefonoColumn) value
End Set
End Property
Public Property Email() As String
Get
Try
Return CType(Me(Me.tableSocios.EmailColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'Email' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.EmailColumn) value
End Set
End Property
Public Property Direccion() As String
Get
Try
Return CType(Me(Me.tableSocios.DireccionColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la
columna 'Direccionl' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.DireccionColumn) value
End Set
End Property
Public Property Ciudad() As String
Get
Try
Return CType(Me(Me.tableSocios.CiudadColumn),String)
Visual Studio 2005
331
www.depurando.com
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'Ciudad' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.CiudadColumn) value
End Set
End Property
Public Property Provincia() As String
Get
Try
Return CType(Me(Me.tableSocios.ProvinciaColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la
columna 'Provincia' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.ProvinciaColumn) value
End Set
End Property
Public Property CPl() As String
Get
Try
Return CType(Me(Me.tableSocios.CPlColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la
columna 'CP' de la tabla 'Socios' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSocios.CPColumn) value
End Set
End Property
Public Function IsNombreNull() As Bolean
Return Me.IsNull(Me.tableSocios.NombreColumn)
End Function
Public Sub SetNombreNull()
Me(Me.tableSocios.NombreColumn) System.Convert.DBNull
End Sub
Public Function IsApellido1Null() As Bolean
Return Me.IsNull(Me.tableSocios.Apellido1Column)
332
Cursos
www.depurando.com
End Function
Public Sub SetApellido1Null()
Me(Me.tableSocios.Apellido1Column)
End Sub
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
333
www.depurando.com
End Function
Public Sub SetProvinciaNull()
Me(Me.tableSocios.ProvinciaColumn)
End Sub
System.Convert.DBNull
System.Convert.DBNull
Cursos
www.depurando.com
System.ComponentModel.DesignerAttribute("Microsoft.VSDesigner.
DataSource.Design.TableAdapterDesigner, Microsoft.VSDesigner"& _
", Version 8.0.0.0, Culture neutral, PublicKeyToken b03f5f7f11d50a3a") _
System.ComponentModel.Design.HelpKeywordAttribute("vs.data.TableAdapter")>
Partial Public Class SociosTableAdapter
Inherits System.ComponentModel.Component
Private WithEvents m_adapter As System.Data.SqlClient.SqlDataAdapter
Private m connection As System.Data.SqlClient.SqlConnection
Private m_commandCollection() As System.Data.SqlClient.SqlCommand
Private m clearBeforeFill As Bolean
Public Sub New()
MyBase.New
Me.m_clearBeforeFill
End Sub
true
335
www.depurando.com
Cursos
www.depurando.com
337
www.depurando.com
System.Data.SqlClient.SqlParameter("@IsNull Apellido2",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido2", System.Data.DataRowVersion.Original, true, Nothing, _
"", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original Apellido2",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido2", System.Data.DataRowVersion.Original, false, Nothing, _
"", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@IsNull Telefono",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, _
0, 0, "Telefono", System.Data.DataRowVersion.Original, true, _
Nothing, "", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original Telefono",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Telefono", System.Data.DataRowVersion.Original, false, Nothing, _
"", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@IsNull Email",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, _
0, 0, "Email", System.Data.DataRowVersion.Original, true, Nothing, "", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original Email",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input,
0, 0, "Email", System.Data.DataRowVersion.Original, false, Nothing, "", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@IsNull Direccion",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input,
0, 0, "Direccion", System.Data.DataRowVersion.Original, true, Nothing,
"", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Original Direccion",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input,
0, 0, "Direccion", System.Data.DataRowVersion.Original, false, Nothing,
"", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@IsNull Ciudad",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input,
0, 0, "Ciudad", System.Data.DataRowVersion.Original, true, Nothing, "", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Original_Ciudad",_
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input,
0, 0, "Ciudad", System.Data.DataRowVersion.Original, false,
Nothing, "", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@IsNull_Provincia", _
338
Cursos
www.depurando.com
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input,
0, 0, "Provincia", System.Data.DataRowVersion.Original, true, Nothing, _
"", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original Provincia",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input,
0, 0, "Provincia", System.Data.DataRowVersion.Original, false, Nothing, _
"", "", ""))
Me.m adapter.DeleteCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@IsNull CP",
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input,
0, 0, "CP", System.Data.DataRowVersion.Original, true, Nothing, "", "", ""))
Me.m_adapter.DeleteCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Original CP",
System.Data.SqlDbType.NChar, 0, System.Data.ParameterDirection.Input,
0, 0, "CP", System.Data.DataRowVersion.Original, false, Nothing, "", "", ""))
Me.m_adapter.InsertCommand New System.Data.SqlClient.SqlCommand
Me.m_adapter.InsertCommand.Connection Me.Connection
Me.m adapter.InsertCommand.CommandText "INSERT INTO
[dbo].[Socios] ([NIF], [Nombre], [Apellido1], [Apellido2], [Telefono]"&
", [Email], [Direccion], [Ciudad], [Provincia],
[CP]) VALUES (@NIF, @Nombre, @Ape"& _
"llido1, @Apellido2, @Telefono, @Email, @Direccion, @Ciudad, _
@Provincia, @CP);"&Global.Microsoft.VisualBasic. ChrW(13) &
Global.Microsoft.VisualBasic.ChrW(10)&"S"&
"ELECT NIF, Nombre, Apellido1, Apellido2, Telefono, Email, Direccion,
Ciudad, Pro"& _
"vincia, CP FROM Socios WHERE (NIF @NIF)"
Me.m adapter.InsertCommand.CommandType System.Data.CommandType.
Text
Me.m adapter.InsertCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@NIF", System.Data.SqlDbType.NChar, _
0, System.Data.ParameterDirection.Input, 0, 0, "NIF", _
System.Data.DataRowVersion.Current, false, Nothing, "", "", ""))
Me.m adapter.InsertCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Nombre",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Nombre", System.Data.DataRowVersion.Current, false, _
Nothing, "", "", ""))
Me.m adapter.InsertCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Apellido1",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido1", System.Data.DataRowVersion.Current, false, Nothing, _
"", "", ""))
Me.m adapter.InsertCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Apellido2",
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido2", System.Data.DataRowVersion.Current, false, Nothing, _
Visual Studio 2005
339
www.depurando.com
Cursos
www.depurando.com
341
www.depurando.com
0, System.Data.ParameterDirection.Input, 0, 0, "Direccion",
System.Data.DataRowVersion.Current, false, Nothing, "", "", ""))
Me.m_adapter.UpdateCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Ciudad",
System.Data.SqlDbType.NVarChar,
0, System.Data.ParameterDirection.Input, 0, 0, "Ciuadad",
System.Data.DataRowVersion.Current, false, Nothing, "", "", ""))
Me.m_adapter.UpdateCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Provincia",
System.Data.SqlDbType.NVarChar,
0, System.Data.ParameterDirection.Input, 0, 0, "Provincia",
System.Data.DataRowVersion.Current, false, Nothing, "", "", ""))
Me.m_adapter.UpdateCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@CP",
System.Data.SqlDbType.NChar,
0, System.Data.ParameterDirection.Input, 0, 0, "CP",
System.Data.DataRowVersion.Current, false, Nothing, "", "", ""))
Me.m_adapter.UpdateCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@Original NIF",
System.Data.SqlDbType.NChar, 0, System.Data.ParameterDirection.Input,
0, 0, "NIF", System.Data.DataRowVersion.Original, false, Nothing, "", "", ""))
Me.m_adapter.UpdateCommand.Parameters.Add(New _
System.Data.SqlClient.SqlParameter("@IsNull_Nombre", _
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input,
0, 0, "Nombre", System.Data.DataRowVersion.Original, true, Nothing, "", "", ""))
Me.m adapter.UpdateCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original_Nombre", _
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Nombre", System.Data.DataRowVersion.Original, false,
Nothing, "", "", ""))
Me.m adapter.UpdateCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@IsNull_Apellido1",_
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido1", System.Data.DataRowVersion.Original, true,
Nothing, "", "", ""))
Me.m adapter.UpdateCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original_Apellido1",_
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido1", System.Data.DataRowVersion.Original, false, Nothing,
"", "", ""))
Me.m adapter.UpdateCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@IsNull_Apellido2",_
System.Data.SqlDbType.Int, 0, System.Data.ParameterDirection.Input, _
0, 0, "Apellido2", System.Data.DataRowVersion.Original, true,
Nothing, "", "", ""))
Me.m adapter.UpdateCommand.Parameters.Add(New
System.Data.SqlClient.SqlParameter("@Original_Apellido2",_
System.Data.SqlDbType.NVarChar, 0, System.Data.ParameterDirection.Input, _
342
Cursos
www.depurando.com
343
www.depurando.com
Cursos
www.depurando.com
Return dataTable
End Function
Public Overloads Overridable Function Update(ByVal dataTable As
DataSet1.SociosDataTable) As Integer
Return Me.Adapter.Update(dataTable)
End Function
Public Overloads Overridable Function Update(ByVal dataSet As DataSet1) As Integer
Return Me.Adapter.Update(dataSet, "Socios")
End Function
Public Overloads Overridable Function Update(ByVal dataRow As _
System.Data.DataRow) As Integer
Return Me.Adapter.Update(New System.Data.DataRow() {dataRow})
End Function
Public Overloads Overridable Function Update(ByVal dataRows() As _
System.Data.DataRow) As Integer
Return Me.Adapter.Update(dataRows)
End Function
<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel._
DataObjectMethodType.Delete, true)>
Public Overloads Overridable Function Delete(ByVal Original NIF As String,
ByVal Original Nombre As String, ByVal Original Apellido1 As String,
ByVal Original_Apellido2 As String, ByVal Original_Telefono As String, _
ByVal Original_Email As String, ByVal Original_Direccion As String, ByVal _
Original Ciudad As String, ByVal Original Provincia As String, ByVal
Original CP As String) As Integer
If (Original NIF Is Nothing) Then
Throw New System.ArgumentNullException("Original_NIF")
Else
Me.Adapter.DeleteCommand.Parameters(0).Value CType(Original NIF,String)
End If
If (Original Nombre Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(1).Value CType(1,Integer)
Me.Adapter.DeleteCommand.Parameters(2).Value System.DBNull.Value
Else
Me.Adapter.DeleteCommand.Parameters(1).Value CType(0,Integer)
Me.Adapter.DeleteCommand.Parameters(2).Value
CType(Original_Nombre,String)
End If
If (Original Apellido1 Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(3).Value CType(1,Integer)
Me.Adapter.DeleteCommand.Parameters(4).Value System.DBNull.Value
Else
Me.Adapter.DeleteCommand.Parameters(3).Value CType(0,Integer)
Visual Studio 2005
345
www.depurando.com
Me.Adapter.DeleteCommand.Parameters(4).Value
CType(Original_Apellido1,String)
End If
If (Original Apellido2 Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(5).Value
Me.Adapter.DeleteCommand.Parameters(6).Value
Else
Me.Adapter.DeleteCommand.Parameters(5).Value
Me.Adapter.DeleteCommand.Parameters(6).Value
CType(Original Apellido2,String)
End If
If (Original_Telefono Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(7).Value
Me.Adapter.DeleteCommand.Parameters(8).Value
Else
Me.Adapter.DeleteCommand.Parameters(7).Value
Me.Adapter.DeleteCommand.Parameters(8).Value
CType(Original_Telefono,String)
End If
If (Original Email Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(9).Value
Me.Adapter.DeleteCommand.Parameters(10).Value
Else
Me.Adapter.DeleteCommand.Parameters(9).Value
Me.Adapter.DeleteCommand.Parameters(10).Value
CType(Original Email,String)
End If
If (Original_Direccion Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(11).Value
Me.Adapter.DeleteCommand.Parameters(12).Value
Else
Me.Adapter.DeleteCommand.Parameters(11).Value
Me.Adapter.DeleteCommand.Parameters(12).Value
CType(Original Direccion,String)
End If
If (Original Ciudad Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(13).Value
Me.Adapter.DeleteCommand.Parameters(14).Value
Else
Me.Adapter.DeleteCommand.Parameters(13).Value
Me.Adapter.DeleteCommand.Parameters(14).Value
CType(Original_Ciudad,String)
End If
If (Original Provincia Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(15).Value
Me.Adapter.DeleteCommand.Parameters(16).Value
Else
Me.Adapter.DeleteCommand.Parameters(15).Value
346
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
_
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
_
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
CType(1,Integer)
System.DBNull.Value
CType(0,Integer)
Cursos
www.depurando.com
Me.Adapter.DeleteCommand.Parameters(16).Value
CType(Original_Provincia,String)
End If
If (Original CP Is Nothing) Then
Me.Adapter.DeleteCommand.Parameters(17).Value CType(1,Integer)
Me.Adapter.DeleteCommand.Parameters(18).Value System.DBNull.Value
Else
Me.Adapter.DeleteCommand.Parameters(17).Value CType(0,Integer)
Me.Adapter.DeleteCommand.Parameters(18).Value CType(Original CP,String)
End If
Dim previousConnectionState As System.Data.ConnectionState
Me.Adapter.DeleteCommand.Connection.State
Me.Adapter.DeleteCommand.Connection.Open
Try
Return Me.Adapter.DeleteCommand.ExecuteNonQuery
Finally
If (previousConnectionState System.Data.ConnectionState.Closed) Then
Me.Adapter.DeleteCommand.Connection.Close
End If
End Try
End function
<System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel._
DataObjectMethodType.Insert, true)>
Public Overloads Overridable Function Insert(ByVal NIF As String, ByVal Nombre
As String, ByVal Apellido1 As String, ByVal Apellido2 As String, ByVal Telefono
As String, ByVal Email As String, ByVal Direccion As String, ByVal Ciudad _
As String, ByVal Provincia As String, ByVal CP As String) As Integer
If (NIF Is Nothing) Then
Throw New System.ArgumentNullException("NIF")
Else
Me.Adapter.InsertCommand.Parameters(0).Value CType(NIF,String)
End If
If (Nombre Is Nothing) Then
Me.Adapter.InsertCommand.Parameters(1).Value System.DBNull.Value
Else
Me.Adapter.InsertCommand.Parameters(1).Value CType(Nombre,String)
End If
If (Apellido1 Is Nothing) Then
Me.Adapter.InsertCommand.Parameters(2).Value System.DBNull.Value
Else
Me.Adapter.InsertCommand.Parameters(2).Value CType(Apellido1,String)
End If
If (Apellido2 Is Nothing) Then
Me.Adapter.InsertCommand.Parameters(3).Value System DBNull.Value
Else
Me.Adapter.InsertCommand.Parameters(3).Value CType(Apellido2,String)
End If
Visual Studio 2005
347
www.depurando.com
Cursos
www.depurando.com
349
www.depurando.com
Me.Adapter.UpdateCommand.Parameters(6).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(6).Value CType(Direccion,String)
End If
If (Ciudad Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(7).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(7).Value CType(Ciudad,String)
End If
If (Provincia Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(8).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(8).Value CType(Provincia,String)
End If
If (CP Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(9).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(9).Value CType(CP,String)
End If
If (Original NIF Is Nothing) Then
Throw New System.ArgumentNullException("Original NIF")
Else
Me.Adapter.UpdateCommand.Parameters(10).Value CType(Original_NIF,String)
End If
If (Original Nombre Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(11).Value CType(1,Integer)
Me.Adapter.UpdateCommand.Parameters(12).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(11).Value CType(0,Integer)
Me.Adapter.UpdateCommand.Parameters(12).Value
CType(Original Nombre,String)
End If
If (Original_Apellido1 Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(13).Value CType(1,Integer)
Me.Adapter.UpdateCommand.Parameters(14).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(13).Value CType(0,Integer)
Me.Adapter.UpdateCommand.Parameters(14).Value _
CType(Original Apellido1,String)
End If
If (Original Apellido2 Is Nothing) Then
Me.Adapter.UpdateCommand.Parameters(15).Value CType(1,Integer)
Me.Adapter.UpdateCommand.Parameters(16).Value System.DBNull.Value
Else
Me.Adapter.UpdateCommand.Parameters(15).Value CType(0,Integer)
Me.Adapter.UpdateCommand.Parameters(16).Value
CType(Original_Apellido2,String)
End If
350
Cursos
www.depurando.com
351
www.depurando.com
Me.Adapter.UpdateCommand.Connection.Open
Try
Return Me.Adapter.UpdateCommand.ExecuteNonQuery
Finally
If (previousConnectionState System.Data.ConnectionState.Closed) Then
Me.Adapter.UpdateCommand.Connection.Close
End If
End Try
End Function
End Class
End namespace
Ms adelante veremos como usarlo, pero antes veremos otra forma de crear
nuestro DataSet tipado. Esta que hemos visto, es la forma ms sencilla y
habitual de crearlo, pero existe otra manera que es un procedimiento manual
que a modo general, conviene que la conozcamos.
Ver vdeo 94 Generando un DataSet con Visual Studio 2005
Cursos
www.depurando.com
Figura 1
Figura 2
Para eso, deberemos hacerlo mediante un editor de textos o bien, desde una
pequea aplicacin Windows que generaremos para tal propsito.
En nuestro caso lo haremos con una aplicacin Windows, para lo cul, iniciaremos un nuevo proyecto de Aplicacin para Windows. En el formula-
353
www.depurando.com
A continuacin, escribiremos el siguiente cdigo que lo que nos permitir, ser crear el fichero o documento
XML de extensin xsd correspondiente, el cul contiene la informacin para generar el DataSet tipado.
El cdigo de la aplicacin de generacin del esquema es el que se detalla a
continuacin:
354
Cursos
www.depurando.com
Una vez que hemos escrito el cdigo fuente necesario para generar el esquema, ejecutaremos nuestra aplicacin, obteniendo una ejecucin afirmativa como la que se indica en la figura 4.
Figura 4
El cdigo de nuestro esquema, ser una vez que se ha creado, como se indica en el siguiente cdigo:
355
www.depurando.com
356
Cursos
www.depurando.com
Figura 5
Figura 6
'
Visual Studio 2005
357
www.depurando.com
Cursos
www.depurando.com
<System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Usage",
"CA2214:DoNotCallOverridableMethodsInConstructors")>
Protected Sub New(ByVal info As System.Runtime.Serialization. _
SerializationInfo, ByVal context As System.Runtime.Serialization.StreamingContext)
MyBase.New(info, context)
If (Me.IsBinarySerialized(info, context) true) Then
Me.InitVars(false)
Dim schemaChangedHandler1 As _
System.ComponentModel.CollectionChangeEventHandler
AddressOf Me.SchemaChanged
AddHandler Me.Tables.CollectionChanged, schemaChangedHandler1
AddHandler Me.Relations.CollectionChanged, schemaChangedHandler1
Return
End If
Dim strSchema As String CType(info.GetValue("XmlSchema",
GetType(String)),String)
If (Me.DetermineSchemaSerializationMode(info, context) _
System.Data.SchemaSerializationMode.IncludeSchema)Then
Dim ds As System.Data.DataSet New System.Data.DataSet
ds.ReadXmlSchema(New System.Xml.XmlTextReader(New
System.IO.StringReader(strSchema)))
If (Not (ds.Tables("SOCIOS")) Is Nothing) Then
MyBase.Tables.Add(New SOCIOSDataTable(ds.Tables("SOCIOS")))
End If
Me.DataSetName ds.DataSetName
Me.Prefix ds.Prefix
Me.Namespace ds.Namespace
Me.Locale ds.Locale
Me.CaseSensitive ds.CaseSensitive
Me.EnforceConstraints ds.EnforceConstraints
Me.Merge(ds, false, System.Data.MissingSchemaAction.Add)
Me.InitVars
Else
Me.ReadXmlSchema(New System.Xml.XmlTextReader(New
System.IO.StringReader(strSchema)))
End If
Me.GetSerializationData(info, context)
Dim schemaChangedHandler As _
System.ComponentModel.CollectionChangeEventHandler
AddressOf Me.SchemaChanged
AddHandler MyBase.Tables.CollectionChanged, schemaChangedHandler
AddHandler Me.Relations.CollectionChanged, schemaChangedHandler
End Sub
<System.ComponentModel.Browsable(false),
System.ComponentModel.DesignerSerializationVisibility(System.
ComponentModel.DesignerSerializationVisibility.Content)> _
Public ReadOnly Property SOCIOS() As SOCIOSDataTable
Visual Studio 2005
359
www.depurando.com
Get
Return Me.tableSOCIOS
End Get
End Property
<System.ComponentModel.DesignerSerializationVisibilityAttribute
(System.ComponentModel.DesignerSerializationVisibility.Hidden)> _
Public Shadows ReadOnly Property Tables() As System.Data.DataTableCollection
Get
Return MyBase.Tables
End Get
End Property
<System.ComponentModel.DesignerSerializationVisibilityAttribute
(System.ComponentModel.DesignerSerializationVisibility.Hidden)>
Public Shadows ReadOnly Property Relations() As
System.Data.DataRelationCollection
Get
Return MyBase.Relations
End Get
End Property
<System.ComponentModel.DefaultValueAttribute(true)>
Public Shadows Property EnforceConstraints() As Bolean
Get
Return MyBase.EnforceConstraints
End Get
Set
MyBase.EnforceConstraints value
End Set
End Property
Protected Overrides Sub InitializeDerivedDataSet()
Me.BeginInit
Me.InitClass
Me.EndInit
End Sub
Public Overrides Function Clone() As System.Data.DataSet
Dim cln As NewDataSet CType(MyBase.Clone,NewDataSet)
cln.InitVars
Return cln
End Function
Protected Overrides Function ShouldSerializeTables() As Bolean
Return false
End Function
360
Cursos
www.depurando.com
361
www.depurando.com
End Sub
Private Sub InitClass()
Me.DataSetName "NewDataSet"
Me.Prefix ""
Me.EnforceConstraints true
Me.tableSOCIOS New SOCIOSDataTable
MyBase.Tables.Add(Me.tableSOCIOS)
End Sub
Private Function ShouldSerializeSOCIOS() As Bolean
Return false
End Function
Private Sub SchemaChanged(ByVal sender As Object, ByVal e As _
System.ComponentModel.CollectionChangeEventArgs)
If (e.Action
System.ComponentModel.CollectionChangeAction.Remove) Then
Me.InitVars
End If
End Sub
Public Shared Function GetTypedDataSetSchema(ByVal xs As
System.Xml.Schema.XmlSchemaSet) As
System.Xml.Schema.XmlSchemaComplexType
Dim ds As NewDataSet New NewDataSet
Dim type As System.Xml.Schema.XmlSchemaComplexType
New System.Xml.Schema.XmlSchemaComplexType
Dim sequence As System.Xml.Schema.XmlSchemaSequence
New System.Xml.Schema.XmlSchemaSequence
xs.Add(ds.GetSchemaSerializable)
Dim any As System.Xml.Schema.XmlSchemaAny
New System.Xml.Schema.XmlSchemaAny
any.Namespace ds.Namespace
sequence.Items.Add(any)
type.Particle sequence
Return type
End Function
Public Delegate Sub SOCIOSRowChangeEventHandler(ByVal sender As Object, _
ByVal e As SOCIOSRowChangeEvent)
<System.Serializable(),
System.Xml.Serialization.XmlSchemaProviderAttribute("GetTypedTableSchema")>
Partial Public Class SOCIOSDataTable
Inherits System.Data.DataTable
Implements System.Collections.IEnumerable
362
Cursos
www.depurando.com
"SOCIOS"
363
www.depurando.com
Me.InitVars
End Sub
Public ReadOnly Property NIFColumn() As System.Data.DataColumn
Get
Return Me.columnNIF
End Get
End property
Public ReadOnly Property NombreColumn() As System.Data.DataColumn
Get
Return Me.columnNombre
End Get
End property
Public ReadOnly Property Apellido1Column() As System.Data.DataColumn
Get
Return Me.columnApellido1
End Get
End property
Public ReadOnly Property Apellido2Column() As System.Data.DataColumn
Get
Return Me.columnApellido2
End Get
End property
Public ReadOnly Property TelefonoColumn() As System.Data.DataColumn
Get
Return Me.columnTelefono
End Get
End property
Public ReadOnly Property EmailColumn() As System.Data.DataColumn
Get
Return Me.columnEmail
End Get
End property
Public ReadOnly Property DireccionColumn() As System.Data.DataColumn
Get
Return Me.columnDireccion
End Get
End property
Public ReadOnly Property CiudadColumn() As System.Data.DataColumn
Get
Return Me.columnCiudad
364
Cursos
www.depurando.com
End Get
End property
Public ReadOnly Property ProvinciaColumn() As System.Data.DataColumn
Get
Return Me.columnProvincia
End Get
End property
Public ReadOnly Property CPColumn() As System.Data.DataColumn
Get
Return Me.columnCP
End Get
End property
<System.ComponentModel.Browsable(false)>
Public ReadOnly Property Count() As Integer
Get
Return Me.Rows.Count
End Get
End Property
Public Default ReadOnly Property Item(ByVal index As Integer) As SOCIOSRow
Get
Return CType(Me.Rows(index),SOCIOSRow)
End Get
End Property
Public Event SOCIOSRowChanged As SOCIOSRowChangeEventHandler
Public Event SOCIOSRowChanging As SOCIOSRowChangeEventHandler
Public Event SOCIOSRowDeleted As SOCIOSRowChangeEventHandler
Public Event SOCIOSRowDeleting As SOCIOSRowChangeEventHandler
Public Overloads Sub AddSOCIOSRow(ByVal row As SOCIOSRow)
Me.Rows.Add(row)
End Sub
Public Overloads Function AddSOCIOSRow(ByVal NIF As String, ByVal _
Nombre As String, ByVal Apellido1 As String, ByVal Apellido2 As String, _
ByVal Telefono As String, ByVal Email As String, ByVal Direccion As
String, ByVal Ciudad As String, ByVal Provincia As String, ByVal CP As
String) As SOCIOSRow
Dim rowSOCIOSRow As SOCIOSRow CType(Me.NewRow,SOCIOSRow)
rowSOCIOSRow.ItemArray New Object() {NIF, Nombre, _
Apellido1, Apellido2, Telefono, Email, Direccion, Ciudad, Provincia, CP}
Visual Studio 2005
365
www.depurando.com
Me.Rows.Add(rowSOCIOSRow)
Return rowSOCIOSRow
End Function
Public Overridable Function GetEnumerator() As System.Collections.
IEnumerator Implements System.Collections.IEnumerable.GetEnumerator
Return Me.Rows.GetEnumerator
End Function
Public Overrides Function Clone() As System.Data.DataTable
Dim cln As SOCIOSDataTable CType(MyBase.Clone,SOCIOSDataTable
cln.InitVars
Return cln
End Function
Protected Overrides Function CreateInstance() As System.Data.DataTable
Return New SOCIOSDataTable
End Function
Friend Sub InitVars()
Me.columnNIF MyBase.Columns("NIF")
Me.columnNombre MyBase.Columns("Nombre")
Me.columnApellido1 MyBase.Columns("Apellido1")
Me.columnApellido2 MyBase.Columns("Apellido2")
Me.columnTelefono MyBase.Columns("Telefono")
Me.columnEmail MyBase.Columns("Email")
Me.columnDireccion MyBase.Columns("Direccion")
Me.columnCiudad MyBase.Columns("Ciudad")
Me.columnProvincia MyBase.Columns("Provinvia")
Me.columnCP MyBase.Columns("CP")
End Sub
Private Sub InitClass()
Me.columnNIF New System.Data.DataColumn("NIF",
GetType(String), Nothing, System.Data.MappingType.Element)
MyBase.Columns.Add(Me.columnNIF)
Me.columnNombre New System.Data.DataColumn("Nombre", _
GetType(String), Nothing, System.Data.MappingType.Element)
MyBase.Columns.Add(Me.columnNombre)
Me.columnApellido1 New System.Data.DataColumn("Apellido1",
GetType(String), Nothing, System.Data.MappingType.Element)
MyBase.Columns.Add(Me.columnApellido1)
Me.columnApellido2 New System.Data DataColumn("Apellido2",
GetType(String), Nothing, System.Data.MappingType.Element)
MyBase.Columns.Add(Me.columnApellido2)
Me.columnTelefono New System.Data.DataColumn("Telefono",
GetType(String), Nothing, System.Data.MappingType.Element)
MyBase.Columns.Add(Me.columnTelefono)
366
Cursos
www.depurando.com
367
www.depurando.com
End If
End Sub
Protected Overrides Sub OnRowChanging(ByVal e As
System.Data.DataRowChangeEventArgs)
MyBase.OnRowChanging(e)
If (Not (Me.SOCIOSRowChangingEvent) Is Nothing) Then
RaiseEvent SOCIOSRowChanging(Me, New _
SOCIOSRowChangeEvent(CType(e.Row,SOCIOSRow), e.Action))
End If
End Sub
Protected Overrides Sub OnRowDeleted(ByVal e As
System.Data.DataRowChangeEventArgs)
MyBase.OnRowDeleted(e)
If (Not (Me.SOCIOSRowDeletedEvent) Is Nothing) Then
RaiseEvent SOCIOSRowDeleted(Me, New _
SOCIOSRowChangeEvent(CType(e.Row,SOCIOSRow), e.Action))
End If
End Sub
Protected Overrides Sub OnRowDeleting(ByVal e As _
System.Data.DataRowChangeEventArgs)
MyBase.OnRowDeleting(e)
If (Not (Me.SOCIOSRowDeletingEvent) Is Nothing) Then
RaiseEvent SOCIOSRowDeleting(Me, New _
SOCIOSRowChangeEvent(CType(e.Row,SOCIOSRow), e.Action))
End If
End Sub
Public Sub RemoveSOCIOSRow(ByVal row As SOCIOSRow)
Me.Rows.Remove(row)
End Sub
Public Shared Function GetTypedTableSchema(ByVal xs As _
System.Xml.Schema.XmlSchemaSet) As _
System.Xml.Schema.XmlSchemaComplexType
Dim type As System.Xml.Schema.XmlSchemaComplexType
New System.Xml.Schema.XmlSchemaComplexType
Dim sequence As System.Xml.Schema.XmlSchemaSequence _
New System.Xml.Schema.XmlSchemaSequence
Dim ds As NewDataSet New NewDataSet
xs.Add(ds.GetSchemaSerializable)
Dim any1 As System.Xml.Schema.XmlSchemaAny
New System.Xml.Schema.XmlSchemaAny
any1.Namespace "http:"//www.w3.org/2001/XMLSchema"
any1.MinOccurs New Decimal(0)
any1.MaxOccurs Decimal.MaxValue
368
Cursos
www.depurando.com
any1.ProcessContents
System.Xml.Schema.XmlSchemaContentProcessing.Lax
sequence.Items.Add(any1)
Dim any2 As System.Xml.Schema.XmlSchemaAny
New System.Xml.Schema.XmlSchemaAny
any2.Namespace "urn:schemas microsoft com:xml diffgram v1"
any2.MinOccurs New Decimal(1)
any2.ProcessContents _
System.Xml.Schema.XmlSchemaContentProcessing.Lax
sequence.Items.Add(any2)
Dim attribute1 As System.Xml.Schema.XmlSchemaAttribute
New System.Xml.Schema.XmlSchemaAttribute
attribute1.Name "namespace"
attribute1.FixedValue ds.Namespace
type.Attributes.Add(attribute1)
Dim attribute2 As System.Xml.Schema.XmlSchemaAttribute
New System.Xml.Schema.XmlSchemaAttribute
attribute2.Name "tableTypeName"
attribute2.FixedValue "SOCIOSDataTable"
type.Attributes.Add(attribute2)
type.Particle sequence
Return type
End Function
End Class
Partial Public Class SOCIOSRow
Inherits System.Data.DataRow
Private tableSOCIOS As SOCIOSDataTable
Friend Sub New(ByVal rb As System.Data.DataRowBuilder)
MyBase.New(rb)
Me.tableSOCIOS CType(Me.Table,SOCIOSDataTable)
End Sub
Public Property NIF() As String
Get
Try
Return CType(Me(Me.tableSOCIOS.NIFColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'NIF' de la tabla 'SOCIOS' es DBNull.", e)
End try
En Get
Set
Me(Me.tableSOCIOS.NIFColumn) value
End set
End Property
Visual Studio 2005
369
www.depurando.com
Cursos
www.depurando.com
371
www.depurando.com
End Set
End Property
Public Property Ciudad() As String
Get
Try
Return CType(Me(Me.tableSOCIOS.CiudadColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la
columna 'Ciudad' de la tabla 'SOCIOS' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSOCIOS.CiudadColumn) value
End Set
End Property
Public Property Provincia() As String
Get
Try
Return CType(Me(Me.tableSOCIOS.ProvinciaColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'Provincia' de la tabla 'SOCIOS' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSOCIOS.ProvinciaColumn) value
End Set
End Property
Public Property CP() As String
Get
Try
Return CType(Me(Me.tableSOCIOS.CPColumn),String)
Catch e As System.InvalidCastException
Throw New System.Data.StrongTypingException("El valor de la _
columna 'CP' de la tabla 'SOCIOS' es DBNull.", e)
End Try
End Get
Set
Me(Me.tableSOCIOS.CPColumn) value
End Set
End Property
Public Function IsNIFNull() As Bolean
Return Me.IsNull(Me.tableSOCIOS.NIFColumn)
End Function
372
Cursos
www.depurando.com
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
373
www.depurando.com
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
System.Convert.DBNull
Cursos
www.depurando.com
End property
Public ReadOnly Property Action() As System.Data.DataRowAction
Get
Return Me.eventAction
End Get
End property
End Class
End Class
End namespace
En este punto, podemos incluir el archivo MiEsquema.vb a nuestro proyecto, o bien compilarlo desde la lnea de comandos o desde el entorno de desarrollo.
Sin embargo, no realizaremos esa accin. Tan solo comentar que si quisiramos compilar desde la lnea de comandos el fichero con el compilador de
Visual Basic, utilizaramos el fichero ejecutable vbc.exe, que corresponde
con las iniciales de Visual Basic Compiler, y que por defecto estar en la
carpeta C:\WINDOWS\Microsoft.NET\Framework\v2.0.50215.
Ahora que ya sabemos como generar nuestros DataSet tipados, aprenderemos a usarlos en nuestras aplicaciones.
Ver vdeo 95 Generando un DataSet con la lnea de comandos.
375
www.depurando.com
Cursos
www.depurando.com
Atencin especial al
Cuadro de herramientas
Cuando trabajamos con DataSets ti
pados como lo hemos hecho hasta
ahora, habremos notado que entre
otras cosas, tenemos las capacidades
o posibilidades de trabajar con el
DataSet como objetos.
Obviamente, estos objetos estn incluidos en el Cuadro de herramientas, tal
y como puede verse en la figura 3.
Figura 3 Componentes creados por
el entorno para trabajar con DataSets tipados
Para trabajar con ellos, podemos arrastrarlos sobre el formulario como hacemos con cualquier control o componente.
Usando las herramientas automticas para trabajar con DataSets tipados
Figura 4 Seleccin de un Control DataSet
del Cuadro de herramientas
377
www.depurando.com
Para usar el objeto DataSet insertado, deberemos acceder a l a travs de cdigo, de forma muy parecida a lo
que lo hacamos anteriormente.
378
Cursos
www.depurando.com
A continuacin aadiremos un Da
taSet al cul le asignaremos el nombre del DataSet tipado correspondiente al esquema creado, tal y como se indica en la figura 8.
A este objeto DataSet, le he llamado
dtSet.
A continuacin,
componente SqlDataAdapter al formulario Windows.
aadiremos
un
379
www.depurando.com
Figura 8
Figura 9
380
Cursos
www.depurando.com
381
www.depurando.com
A continuacin, presionaremos el botn Siguiente. De esta manera, el asistente terminar de crear las instrucciones necesarias para trabajar con el
componente SqlDataAdapter.
Si todo ha ido correctamente, aparecer una ventana como la que se indica
en la figura 12.
Cursos
www.depurando.com
383
www.depurando.com
384
Cursos
www.depurando.com
Imports system.data
Imports System.Data.SqlClient
Imports System.Xml
Public Class Form1
Dim MiSqlConnection As SqlConnection
Dim MiSqlDataAdapter As SqlDataAdapter
Private Sub Form1_Load(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
' Deshabilitamos el botn de Borrar registro,
' porque hasta que no se cree no lo borraremos
Button4.Enabled False
' Rellenamos el DataSet tipado con la informacin de la tabla del SELECT
SqlDataAdapter1.Fill(dtSet, "SOCIOS")
End Sub
Private Sub Button1 Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
' Declaramos un objeto para trabajar con los datos del DataSet
Dim MisDatos As DataSet1.SociosRow
' Almacenamos en l, la informacin del DataSet para
' el NIF "111111"
MisDatos dtSet.Socios.FindByNIF("111111")
' Modificaremos el campo CP
MisDatos.CP "28022"
' Deshabilitamos como medida de seguridad el botn
Button1.Enabled False
End Sub
Private Sub Button2 Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button2.Click
If dtSet.HasChanges Then
' El DataSet tiene cambios
' Declaramos un objeto DataSet
Dim dtSetModificado As DataSet
' Le pasamos los datos modificados en el DataSet original
dtSetModificado dtSet.GetChanges
' Actualizamos el DataSet que ha cambiado a travs del DataAdapter
SqlDataAdapter1.Update(dtSetModificado)
' Aceptamos los cambios en el DataSet para
' seguir trabajando con l por ejemplo
dtSet.AcceptChanges()
' Mostramos un mensaje en pantalla indicando que
' se han modificado los datos
MessageBox.Show("Los cambios del DataSet han sido" _
Visual Studio 2005
385
www.depurando.com
386
Cursos
www.depurando.com
Figura 16 Ejemplo del uso de DataAdapter y DataSet tipado con todas las acciones de insercin y eliminacin de datos
incluidas
Enlace a formularios
Visual Studio 2005 proporciona a los desarrolladores un conjunto de herramientas y asistentes que facilitan enormemente el trabajo y ahorran grandes
cantidades de tiempo en el desarrollo de diferentes aplicaciones.
De los asistentes o herramientas que nos proporcionan mayor rendimiento
en el entorno de desarrollo rpido de Microsoft, est la que nos permite trabajar con fuentes de datos como los datos de una aplicacin tpica maestro
detalle.
Entre otras cosas, nos centraremos en esta accin, que ser la que veremos
en detalle a continuacin.
387
www.depurando.com
388
Cursos
www.depurando.com
Iniciaremos una nueva aplicacin Windows con Visual Studio 2005 y seleccionaremos el men Datos > Mostrar orgenes de datos como se indica en
la figura 1.
Figura 1
de datos
389
www.depurando.com
mo se indica en la figura 5.
? Figura 4 La ventana orgenes de datos
anclada en Visual Studio 2005
Figura 6
390
Cursos
www.depurando.com
Figura 7
391
www.depurando.com
Cursos
www.depurando.com
Figura 10
393
www.depurando.com
394
Cursos
www.depurando.com
Lo primero que haremos ser preparar la tabla padre para poderla aadir al
formulario Windows. Por esa razn, haremos clic sobre la tabla Socios de la
ventana de Orgenes de datos como se indica en la figura 1.
Figura 1 Tabal Socios de la ventana de
orgenes de datos
395
www.depurando.com
Si hacemos clic sobre la lista desplegable, aparecer una lista de opciones o posibilidades, para indicar
cmo queremos que sean los campos de la tabla seleccionada con respecto a que tipo de controles queremos que sean.
Esto es lo que se indica en la figura 6.
Figura 6 Lista desplegable de la tabla Socios de la ventana de Orgenes de datos
Por defecto, una tabla queda determinada con un icono que representa
el control DataGridView, aunque se
puede modificar la representacin
que deseamos tengan los datos dentro de un formulario seleccionando
cualquiera de las opciones que tenemos de la lista desplegable.
Estas opciones pueden ser cualquiera de las siguientes:
Representa los datos volcados dentro de un control DataGridView
Representa los datos volcados dentro de controles estndar como
TextBox u otros controles para reflejarla como Detalle de la informacin
Representa los datos volcados dentro de controles estndar como
TextBox u otros controles para reflejarla como Detalle de la informacin
En el caso de la tabla Socios que usaremos como tabla padre, cambiaremos
la representacin por defecto de DataGridView para indicarle que nos represente la informacin en controles, tal y como se indica en la figura 7.
396
Cursos
www.depurando.com
397
www.depurando.com
De esta manera, el campo AlquilerID y SocioNIF quedarn modificados en la ventana Orgenes de datos
como se indica en la figura 11.
398
Cursos
www.depurando.com
Una vez que tenemos las tabla maestra y detalle preparadas para utilizarlas, las aadiremos al formulario
Windows para que tengan el funcionamiento esperado.
399
www.depurando.com
Figura 2
Cursos
www.depurando.com
Si ejecutamos nuestra aplicacin, observaremos que esta acta como una tpica aplicacin de acceso a datos que nos permite navegar a travs de los
campos de la tabla Socios, tal y como se indica en la figura 4.
Figura 4
A continuacin, insertaremos en el formulario la tabla Alquileres y relacionaremos ambas tablas para que se muestren los datos relacionados, dentro
del formulario Windows.
Incrustando la tabla hija en el formulario
Ya tenemos la tabla padre insertada en nuestro formulario Windows. Nuestra segunda accin, ser la de incrustar en el formulario los datos o tabla
hoja, que en nuestro caso es la formada por la tabla Alquileres, la cul adems, posee una relacin entre campos con la tabla Socios insertada anteriormente.
Para llevar a cabo esta accin arrastraremos y soltaremos la tabla Alquileres
sobre el formulario como se indica en la figura 5.
401
www.depurando.com
Figura 6
Como podemos observar, el entorno de trabajo ha hecho por nosotros el trabajo ms complejo para representar los datos de forma rpida y sencilla.
El esquema de datos tipados, apareca ya en nuestro proyecto cuando asignamos el correspondiente origen de datos.
Ahora lo que ha ocurrido, es que al arrastrar y soltar la tabla padre Socios de
la ventana de Orgenes de datos, en el entorno se ha aadido un componente
402
Cursos
www.depurando.com
403
www.depurando.com
Figura 8
A continuacin, la tarea que nos queda para completar el correcto funcionamiento de nuestra aplicacin, es la de relacionar la tabla detalle y la tabla
maestra entre s, para que los datos que se muestran en la aplicacin, estn
relacionados entre s.
Relacionando la tabla padre con la tabla hija
La tarea ms sencilla es la de relacionar la tabla detalle con la tabla maestra.
Es una tarea sencilla, porque Visual Studio 2005 nos proporciona las herramientas necesarias para simplificar al mximo esta tarea.
Para llevar a cabo esta tarea, haga clic
sobre el control DataGridView que
corresponde a los datos de la tabla
maestra, y acceda a la ventana de
Propiedades.
Dentro de la ventana de Propiedades,
acceda a la propiedad DataSource
como se indica en la figura 9.
Despliegue esta propiedad, y de la lista desplegable que aparece, seleccione la opcin FK Alquileres Socios
como se indica en la figura 10.
? Figura 9 Propiedad DataSource del control DataGridView de la informacin maestra
404
Cursos
www.depurando.com
Cuando se asigna el campo de relacin de las tablas, dentro de la aplicacin se aade esta relacin para
que cuando naveguemos entre los
datos de la tabla Socios aparezca toda la informacin de la tabla Alqui
leres relacionada con la tabla Socios.
Esto de lo que hablamos, est supeditado
por
el
componente
FK Alquileres SociosBindingSourc
e que es lo que se indica en la figura
11.
Para finalizar, ejecutaremos nuestra aplicacin y comprobaremos que el
funcionamiento de esta, incluida la relacin entre tablas, funciona como esperbamos.
En la figura 12, podemos observar el comportamiento de nuestra aplicacin
en ejecucin.
405
www.depurando.com
Figura 11
Cursos
www.depurando.com
Acto seguido, cuando hayamos realizado la modificacin, haremos clic sobre la opcin de Guardar datos, tal y como se muestra en la figura 2.
Figura 2 Opcin del control BindingNavigator pata guardar los
datos modificados
407
www.depurando.com
De la misma manera funciona el mecanismo para eliminar un registro, tal y como se muestra en la figura 4.
Figura 4 Eliminar un registro de
forma rpida
Servicios Web
Este mdulo presenta al alumno los fundamentos de los Servicios Web y las
Arquitecturas Orientadas a Servicios (SOA).
Tras una introduccin a los servicios Web y sus conceptos asociados se ve
la forma de crear y consumir servicios Web. Para la creacin de un servicio
utilizaremos Visual Studio 2005. Si desea ms informacin sobre esta
herramienta puede dirigirse al curso de Desarrollo de Aplicaciones Web con
ASP.NET.
Cursos
www.depurando.com
409
www.depurando.com
En esta leccin explicaremos desde un punto de vista no-tcnico los conceptos relacionados con los Servicios Web, cmo funcionan, de dnde vienen y
a dnde van.
Un poco de historia: modelos de desarrollo
El hecho de poder comunicar componentes de software entre s tiene una
enorme importancia. Hasta no hace tantos aos era muy tpico hacer aplicaciones de una sola pieza, "monolticas":
Figura 6.1 Aplicacin monoltica aunque distribuida
Cursos
www.depurando.com
reglas de negocio residentes en la capa intermedia. Este modelo es ms eficiente y est muy evolucionado respecto al anterior pero an se puede ir
ms all.
La arquitectura de desarrollo en n-capas (n tier que dicen los anglosajones) lleva el concepto cliente-servidor un paso hacia adelante, dividiendo la
capa intermedia en muchas otras capas especializadas cada una de las cuales
puede residir en un servidor diferente:
411
www.depurando.com
cambiar el modo de trabajo de la aplicacin global, y todo ello sin que los
clientes sean conscientes de ello. Obviamente esto ofrece ms ventajas an
ya que, por ejemplo, no es necesario reinstalar la aplicacin en cada cliente,
sino que basta con sustituir un componente en un nico lugar y automticamente todos los usuarios tendrn su aplicacin actualizada.
El concepto de Arquitectura Orientada a Servicios o SOA se basa en el
uso de este tipo de componentes que suplen las necesidades de una o varias
aplicaciones, son independientes entre s y trabajan independientemente del
sistema operativo o la plataforma.
Aunque muchos programadores piensan que SOA est relacionado nicamente con los Servicios Web lo cierto es que se pueden conseguir arquitecturas SOA con otras tecnologas como veremos.
412
Cursos
www.depurando.com
asncronas. Los parmetros son transmitidos a travs de la red mediante un formato binario propio llamado NDR (Network Data Re
presentation).
x
Estos modelos son buenos y muy eficientes, cumpliendo bien su trabajo pero tienen algunas limitaciones importantes siendo las principales las siguientes:
x
Estn ligados a plataformas de desarrollo especficas, lo que dificulta la comunicacin entre ellas
413
www.depurando.com
pero su utilizacin es difcil y aaden una nueva capa de complejidad a las aplicaciones adems de disminuir su rendimiento.
SOAP
Las expectativas actuales respecto a los componentes han aumentado. Al
igual que podemos usar un navegador web para acceder a cualquier pgina
independientemente del sistema operativo del servidor en que resida, por
qu no podramos invocar mtodos de componentes a travs de la red independientemente de dnde se encuentren, del lenguaje en el que estn escritos y de la plataforma de computacin en la que se ejecuten?
Esto es precisamente lo que ofrecen los Servicios Web. Gracias a ellos se
derriban la antiguas divisiones resultantes de los modelos de componentes
descritos, y la integracin de las aplicaciones, la ubicuidad de sus componentes y su reutilizacin a travs de la red se convierten en una realidad.
La tecnologa que est detrs de todo ello se llama SOAP (jabn en ingls).
Este acrnimo (Simple Object Access Protocol) describe un concepto tecnolgico basado en la sencillez y la flexibilidad que hace uso de tecnologas y
estndares comunes para conseguir las promesas de la ubicuidad de los
servicios, la transparencia de los datos y la independencia de la plataforma
que segn hemos visto, se hacen necesarios en las aplicaciones actuales.
Breve historia de SOAP
SOAP empez como un protocolo de invocacin remota basado en XML
diseado por Dave Winer de UserLand, llamado XML-RPC. A partir de ste se obtuvo en Septiembre de 1999 la versin 1.0 de SOAP, en la que participo activamente Microsoft y el archiconocido experto en programacin
Don Box.
Esta primera versin fue ms o menos despreciada por los principales fabricantes de software que en esa poca tenan en marcha un proyecto ms ambicioso llamado ebXML. Esto puso en peligro en su nacimiento la existencia de SOAP ya que si los grandes no lo apoyaban poco se poda hacer. Por
fortuna uno de estos grandes fabricantes, IBM, decidi apoyarlo y en la actualidad no slo acepta SOAP sino que es uno de lo motores detrs de su
414
Cursos
www.depurando.com
desarrollo (dos importantes personas de IBM y su filial Lotus, David Ehnebuske y Noah Mendelsohn, son autores de la especificacin 1.1 de SOAP).
Sun Microsystems tambin anunci oficialmente en Junio de 2000 que soportaba el estndar. El hecho de que los tres gigantes del software (Microsoft, IBM y Sun) apoyen SOAP ha hecho que muchos fabricantes de Middleware y puentes CORBA-DCOM (como Roguewave o IONA) ofrezcan
productos para SOAP, as como otras muchas pequeas empresas de software.
El paso definitivo para asegurar el xito de SOAP y los servicios web es su
envo al W3C (World Wide Web Consortium) para proponerlo como estndar. La ltima versin de la especificacin se puede encontrar en
www.w3.org/TR/SOAP/.
Este soporte mayoritario hace que su xito y pervivencia estn asegurados y
hoy todas las herramientas de desarrollo del mercado ofrecen en menor o
mayor medida soporte para SOAP. Por supuesto .NET y Visual Studio son
los entornos ms avanzados en la adopcin de SOAP.
La base tecnolgica de SOAP
Lo interesante de SOAP es que utiliza para su implementacin tecnologas y
estndares muy conocidos y accesibles como son XML o el protocolo
HTTP.
x
Dado que los mensajes entre componentes y los datos de los parmetros para llamadas a mtodos remotos se envan en formato
XML basado en texto plano, SOAP se puede utilizar para comunicarse con cualquier plataforma de computacin, consiguiendo la
ansiada ubicuidad de los componentes.
415
www.depurando.com
Cursos
www.depurando.com
los distintos para transmitir mensajes SOAP. Por citar unos pocos, se podra
utilizar SMTP (correo electrnico), MSMQ (Microsoft Messaging Queue)
para enviar de manera asncrona las llamadas a procedimientos con SOAP,
etc...
Descubrimiento de servicios: WSDL y UDDI
Otro de los estndares que se definen en SOAP es WSDL (Web Service De
finition Language). Se trata de un formato estndar para describir las interfaces de los servicios web. WSDL describe qu mtodos estn disponibles a
travs de un servicio Web y cules son los parmetros y valores devueltos
por stos. Antes de usar un componente que acta como servicio web se debe leer su archivo WSDL para averiguar cmo utilizarlo.
Nota.- Para aquellos programadores que conocen otras arquitecturas podemos decir que WSDL es el equivalente en XML a los lenguajes
IDL (Interface Description Language) de DCOM y CORBA.
Se ha definido tambin un formato estndar para publicacin de informacin de servicios web llamado UDDI (Universal Description Discovery and
Integration). Esta especificacin permite la creacin de directorios de servicios web, donde se definen mtodos que permiten consultarlos para encontrar fcilmente aquel servicio que se necesite. Windows Server 2003 incluye
gratuitamente un servidor para implementar directorios UDDI en organizaciones.
417
www.depurando.com
418
Cursos
www.depurando.com
Figura 6.4
Visual Studio 2005, nos permite crear las aplicaciones y servicios Web, en
varias ubicaciones, entre ellas el sistema de archivos local o de red local,
aunque tambin podemos indicar una direccin HTTP o FTP, esas opciones
las tenemos en la lista desplegable que hay junto a la etiqueta Ubicacin,
indicaremos el directorio en el que queremos alojar nuestro cdigo y el lenguaje que utilizaremos, en este caso concreto lo haremos con Visual Basic.
Nota.- Si utiliza una versin Express de Visual Studio, debe saber que slo puede desarrollador Servicios Web con Visual Web Developer.
En los ejemplos utilizaremos esta versin, aunque todas las versiones superiores de Visual Studio 2005 tienen un funcionamiento
similar.
El proyecto creado aade una nueva clase y un fichero con extensin .asmx
que es la utilizada para los servicios Web. En la clase incluiremos todo el
cdigo necesario para crear la "clase" que usaremos para comunicarnos con
las aplicaciones cliente.
El fichero con extensin .asmx simplemente contiene el cdigo de
ASP.NET 2.0 que servir al runtime de .NET para saber que estamos tratando con un servicio Web, adems de indicarle dnde est alojado el cdigo que contiene la clase y cmo se llama esta, y cual es el lenguaje que utilizaremos, tal como podemos ver en el siguiente cdigo:
La parte importante de esa lnea de cdigo ASP.NET es <%@ WebService, con ella estamos indicando que nuestra intencin es definir un servicio
Web.
Visual Studio 2005
419
www.depurando.com
Por otra parte, el atributo CodeBehind le informa a ASP.NET 2.0 que el cdigo no est incluido en el fichero .asmx, sino en uno independiente. Este es
el tratamiento predeterminado al crear un nuevo servicio Web.
Crear un servicio Web usando un solo fichero
Pero si queremos aadir otro servicio Web a nuestro proyecto, seleccionando la opcin Agregar nuevo elemento del men Sitio Web, el cuadro de
dilogo que nos muestra los distintos tipos de ficheros que podemos agregar, nos dar la oportunidad de indicar si queremos tener el cdigo separado
o no del fichero .asmx, tal como podemos ver en la figura 6.5.
Si seleccionamos esta forma de hacerlo, tanto la directiva de ASP.NET como el cdigo del lenguaje seleccionado estar en el mismo fichero, en nuestro ejemplo HolaMundoSW.asmx.
Como podemos apreciar en la figura 6.6, al crear el servicio Web de esta
forma, tenemos todo el cdigo necesario en un solo fichero, esta ser la
forma recomendada de hacerlo, al menos si el servicio Web es simple, como
es el caso actual.
Figura 6.5
420
Cursos
www.depurando.com
Tal como podemos apreciar el cdigo de ASP.NET 2.0 se simplifica un poco, porque ya no tenemos que indicarle al runtime de .NET dnde se encuentra nuestro cdigo, lo que si tenemos que seguir indicando es que este
fichero realmente es un servicio Web, cmo se llama la clase y que lenguaje
vamos a utilizar para escribir el cdigo.
Eliminar ficheros de un proyecto
Para este ejemplo, vamos a quedarnos con este fichero en nuestro proyecto,
por tanto el resto de los ficheros que tenemos creados podemos eliminarlos,
esto lo haremos desde el propio explorador de soluciones, del cual podemos
eliminar todos los ficheros salvo el que vamos a usar en el ejemplo, por tanto dejaremos el fichero HolaMundoSW.asmx.
En la figura 6.7 podemos ver el contenido actual de nuestro proyecto y en la
figura 6.8 el que debemos dejar despus de eliminar el resto de elementos.
421
www.depurando.com
Figura 6.8
El explorador de soluciones
con nuestro servicio Web ?
Nota.- Cuando eliminamos ficheros o carpetas del explorador de soluciones, estos se eliminan fsicamente.
Analizando el contenido de un servicio Web
Como podemos comprobar en la figura 6.6, una vez que hemos cerrado la
directiva de ASP.NET 2.0 que indica que el contenido de ese fichero es un
servicio Web, lo que sigue es el cdigo en el lenguaje de nuestra preferencia, en este caso Visual Basic (VB).
Despus de las tpicas importaciones de espacios de nombres viene el cdigo que har que esta clase realmente se convierta en un servicio Web.
422
Cursos
www.depurando.com
El atributo WebService es totalmente opcional, pero siempre deberamos incluirlo en nuestros servicios Web, por dos razones:
x
La segunda razn es porque en ese mismo atributo podemos indicar una descripcin de nuestro servicio Web. Esa descripcin ser
la que se muestre cuando "descubramos" un servicio Web utilizando UDDI.
423
www.depurando.com
Lo que si es importante es que el nombre de la clase coincida con la indicada en el atributo de la directiva de ASP.NET.
Aadir mtodos para usarlos en el servicio Web
Ahora viene la parte interesante, aunque todos los preparativos preliminares
tambin lo son, pero si no definimos ningn mtodo en nuestra clase, de poco nos servir el servicio Web, ya que esos mtodos sern los que utilicemos para comunicarnos con l.
Los mtodos los declararemos de la forma habitual, pero si queremos que
sean expuestos como parte del servicio Web, debemos utilizar el atributo
WebMethod. Con este atributo le estamos indicando a la "infraestructura"
que hay detrs de los servicios Web, que tenga en cuenta ese mtodo para
utilizarlo desde nuestra clase. No vamos a entrar en detalles de que es lo que
ocurre tras el teln, pero debemos saber que sin ese atributo, nuestro mtodo
ser totalmente invisible al mundo exterior, aunque an as lo podramos
seguir usando desde nuestra clase o desde cualquier otra clase que tengamos
en nuestro proyecto, ya que al fin y al cabo es "slo" un mtodo ms.
Este atributo lo utilizaremos como de costumbre: indicndolo antes de la
declaracin del mtodo. En el siguiente cdigo vemos la declaracin de un
424
Cursos
www.depurando.com
mtodo que se incluye como plantilla de los servicios Web que creemos con
Visual Studio 2005, y que nos puede servir para nuestros propsitos, aunque
lo "castellanizaremos" para que sea ms fcilmente comprensible para los
que hablamos el idioma de Cervantes:
425
www.depurando.com
Cuando lo mostramos en el Internet Explorer, podemos ver cierta informacin del servicio Web,
principalmente las descripciones que hemos usado, adems de un par de links, que nos mostrarn
informacin extra de nuestro servicio Web y del
mtodo.
En las siguientes imgenes (6.10 y 6.11) vemos lo
que nos muestra el navegador:
426
Cursos
www.depurando.com
427
www.depurando.com
Cursos
www.depurando.com
MapPoint (evaluacin):
https://mappointcss.partners.extranet microsoft.com/MwsSignup/Eval.aspx
Servicios web de Amazn:
http://www.amazon.co.uk/exec/obidos/tg/browse/-/3242161/0265630606-4874040
Activar el servidor Web para usar con un directorio local
Si no dispone de IIS y quiere alojar un servicio web en su mquina, stos
son los pasos que debemos dar activar el servidor Web incluido con .NET
Framework 2.0:
x
429
www.depurando.com
Nota.- Estos pasos solo son necesarios si no tenemos instalado y en ejecucin el ISS, en cuyo caso tendramos que copia el servicio Web en
el directorio C:\Inetput\wwwroot y usar
http://localhost/HolaMundoSW.asmx para acceder al servicio Web.
Crear un proyecto Windows para usar el servicio Web
Lo siguiente que tenemos que hacer es abrir el Visual Studio 2005 y crear
un nuevo proyecto de Windows, al que le daremos el nombre ClienteWindows. De forma automtica se crear un formulario, al que le aadimos una
etiqueta a la que asignaremos a la propiedad Font una fuente de 16 puntos
en negrita, para que se vea bien el texto, y le cambiamos el nombre a: labelSaludo. Tambin aadiremos un botn al que le daremos el nombre
btnUsarServicioWeb, en el texto pondremos: Saludo desde servicio Web,
como es natural, tendremos que cambiar el tamao para que veamos el texto
completo.
Aadir una referencia para acceder al servicio Web
Al igual que ocurre con el resto de ensamblados de .NET, si queremos acceder a la clase que tiene el servicio Web, debemos crear una referencia en
nuestro proyecto, con idea de que tengamos a nuestra disposicin las clases
que contiene, en nuestro caso la clase HolaMundoSW. Pero como es un
servicio Web, que tericamente est alojado en algn servidor de Internet,
en lugar de agregar una referencia normal, aadiremos una referencia Web.
Para hacerlo, nos iremos al Explorador de soluciones / References, presionaremos con el botn secundario del mouse para que se muestre el men
contextual, del que elegiremos la opcin Agregar referencia Web, tal como vemos en la figura 6.13:
430
Cursos
www.depurando.com
Figura 6.13
Web
431
www.depurando.com
Cursos
www.depurando.com
433
www.depurando.com
La aplicacin
MSDN Video es una aplicacin de ejemplo empresarial desarrollada en Espaa por la comunidad de desarrollo y Microsoft. Puede utilizarse para
comprobar las mejores prcticas en la construccin aplicaciones distribui434
Cursos
www.depurando.com
Videos explicativos
Si desea ver cmo se hizo esta aplicacin puede visionar estos videos donde
desarrollamos la aplicacin paso a paso:
Ver vdeos 100 Creacin de la base de datos y el acceso a datos, 101 Esqueleto de formularios, 102 Formulario Nuevo Socio, 103 Formulario Alquilar
104 Formulario Devolver y 105 Conclusiones.
435
www.depurando.com
ndice
Bienvenido al curso de instruccin a .NET con Visual Basic 2005 ........... 3
Acerca de los autores ............................................................................. 4
Introduccin a la plataforma .NET ............................................................. 4
El entorno de ejecucin CLR ................................................................ 5
El lenguaje intermedio y el CLS ........................................................... 5
La especificacin comn de los lenguajes y el sistema de tipos
comunes ............................................................................................ 7
La biblioteca de clases ........................................................................... 9
Los espacios de nombres ................................................................ 10
Acceso a datos con ADO.NET ............................................................
Capa conectada ...............................................................................
Capa desconectada .........................................................................
Aplicaciones Windows Forms ............................................................
Aplicaciones Web Forms ....................................................................
11
12
13
14
17
20
20
21
21
23
436
Cursos
www.depurando.com
24
25
26
26
27
28
29
30
30
33
35
36
38
437
www.depurando.com
Campos ................................................................................. 70
Mtodos y otros elementos ................................................... 70
Cmo usar las estructuras .......................................................... 71
Accesibilidad y mbito ................................................................... 71
mbito ....................................................................................... 72
mbito de bloque ................................................................. 73
mbito de procedimiento ..................................................... 74
mbito de mdulo ................................................................ 75
mbito en el espacio de nombres ........................................ 75
La palabra clave Global ............................................................ 76
Accesibilidad ............................................................................. 77
Accesibilidad a las variables en los procedimientos ............ 78
Las accesibilidades predeterminadas ........................................ 78
Anidacin de tipos ..................................................................... 80
Los tipos anidables ............................................................... 80
El nombre completo de un tipo ............................................ 81
Importacin de espacios de nombres ................................... 82
Alias de espacios de nombres ............................................... 82
Propiedades .................................................................................... 84
Definir una propiedad ................................................................ 84
Propiedades de solo lectura ....................................................... 85
Propiedades de solo escritura .................................................... 86
Diferente accesibilidad para los bloques Get y Set ................... 86
Propiedades predeterminadas .................................................... 87
Sobrecarga de propiedades predeterminadas ............................ 87
Interfaces ........................................................................................ 89
Qu es una interfaz? ................................................................ 89
Una interfaz es un contrato ....................................................... 91
Las interfaces y el poliformismo ............................................... 91
Usar una interfaz en una clase ................................................... 92
Acceder a los miembros implementados ................................... 93
Saber si un objeto implementa una interfaz .............................. 93
Implementacin de mltiples interfaces .................................... 94
Mltiple implementacin de un mismo miembro ..................... 95
Dnde podemos implementar las interfaces? .......................... 95
Un ejemplo prctico usando una interfaz de .NET ................... 97
Manejo de excepciones ....................................................................... 99
Manejo de excepciones no estructuradas .................................. 99
Manejo de excepciones estructuradas ..................................... 100
438
Cursos
www.depurando.com
100
100
101
102
102
103
104
104
105
105
106
107
107
107
108
110
111
111
112
113
115
118
118
119
119
120
121
121
123
124
126
127
127
128
128
129
439
www.depurando.com
131
132
132
134
144
145
146
147
149
150
150
152
155
155
159
164
166
172
172
176
180
181
182
184
185
185
186
187
188
440
Cursos
www.depurando.com
135
138
139
139
141
216
216
217
217
218
219
220
221
223
223
224
441
www.depurando.com
224
225
228
230
230
232
233
234
236
238
239
242
244
245
245
247
248
248
249
250
251
253
257
258
260
262
264
264
267
267
267
270
271
272
273
Cursos
www.depurando.com
443
www.depurando.com
datos .............................................................................................
Connection, DataAdapter y DataSet .......................................
Conociendo el objeto DataAdapter ..............................................
Connection, DataAdapter y DataSet ......................................
Utilizando las clase de .NET ...................................................
Utilizando los componentes de .NET ......................................
Insertando datos a travs del objeto DataAdapter ........................
Cmo se insertan datos con el objeto DataAdapter? .............
Trabajando con un ejemplo .....................................................
Actualizando datos a travs del objeto DataAdapter ...................
Eliminando datos a travs del objeto DataAdapter ......................
DataSets tipados ................................................................................
Qu son los DataSets tipados? ....................................................
Cmo trabajar con un DataSet tipado .....................................
Qu ventajas nos aportan los DataSets tipados? ....................
Generando nuestros DataSets tipados ..........................................
Diagrama de datos ...................................................................
Generando un DataSet tipado con Visual Studio 2005 ................
Usando el entorno de desarrollo Visual Studio 2005 ..............
Generando un DataSet tipado con la lnea de comandos .............
Usando la herramienta XSD.exe .............................................
Usando los DataSets tipados ........................................................
Uso rpido de nuestro DataSet tipado .....................................
Atencin especial al Cuadro de herramientas .........................
Usando las herramientas automticas para trabajar con
DataSets tipados ......................................................................
Usando DataAdapter con DataSets tipados .............................
Enlace a formularios ..........................................................................
Qu son los datos Maestro detalle? ............................................
Configurando la fuente de datos ...................................................
Configurando el origen de la fuente de datos ..........................
Preparando el origen de datos ......................................................
Preparando la tabla padre ........................................................
Preparando la tabla hija ...........................................................
Incrustando los datos maestro detalle ..........................................
Incrustando la tabla padre en el formulario .............................
Relacionando la tabla padre con la tabla hija ..........................
Manipulando los datos maestro detalle ........................................
Modificando datos .................................................................
444
Cursos
www.depurando.com
296
296
297
297
297
299
304
304
304
308
309
311
312
312
313
313
314
314
315
352
352
375
376
377
377
379
387
387
388
388
394
394
397
399
399
404
406
407
408
408
409
410
412
414
414
415
417
417
418
418
420
421
422
422
424
424
425
427
428
428
429
430
430
432
433
434
434
435
435
445
www.depurando.com
446
Cursos
www.depurando.com