Sei sulla pagina 1di 456

Introduccin

Laplataforma.NETfacilitaunconjuntodetecnologasyherramientasquesimplificaneldesarrollodeaplicacionesy
proponeunasolucinparacasicualquiertipodeaplicaciones:

l AplicacionesWindowsclsicas.

l AplicacionesWeb.

l ServiciosWindows.

l ServiciosWeb.

Todos estos tipos de aplicaciones se pueden realizar gracias a un elemento esencial: el Framework .NET. Este
Framework se encarga, mediante numerosas capas de software superpuestas, de la integridad de la vida de una
aplicacin,desdeeldesarrollohastalaejecucin.ElFrameworkdebeestarinstaladoenelsistemaoperativoconel
cualvaainteractuar.Elprimersistemaquepermiteacogerloes,porsupuesto,Windows,perohayotrasversiones
disponiblesquepermitenlaadaptacindelaplataforma.NETasistemastalescomoLinuxoUnix.

El Framework contiene dos elementos principales: el Common Language Runtime y la librera de clases del .NET
Framework.

El Common Language Runtime es la base del .NET Framework. Se puede considerar el runtime como un motor de
ejecucinquegestionalaejecucindecdigoyquetambinaseguralagestindelamemoria.Elcdigodelquese
encargaelCommonLanguageRuntimesellamacdigogestionado.

Labibliotecadeclasesesunconjuntodeclasesquesepuedeutilizarparaeldesarrollodecualquieraplicacin.Lo
trataremosalolargodeestelibro.

1.PrincipiodefuncionamientodelCommonLanguageRuntime

EnlasaplicacionesWindowstradicionales,elsistemaseencargadirectamentedelaejecucindelcdigo.Enefecto,
este se genera a travs del compilador asociado al lenguaje de programacin utilizado para el diseo de la
aplicacin. El resultado de esta compilacin corresponde a un archivo binario que contiene el cdigo especificado
paraelmicroprocesadoryelsistemaoperativoconloscualesdebefuncionarlaaplicacin.Noesposibleninguna

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
compatibilidadconotrotipodemicroprocesadorosistemaoperativo.Paraconvencersedeello,bastaconintentarla
ejecucindeunaaplicacinprevistaparaWindowsenunsistemaLinux.Siseintentalaejecucinenunaestacin
detrabajoSUN,queutilizauntipodemicroprocesadorradicalmentediferente,elresultadoesidntico.Lasolucin
para paliar estos problemas consiste en generar para la aplicacin no un cdigo especfico, sino uno genrico,
independiente de cualquier plataforma de software o de hardware. Se confa este cdigo, en el momento de la
ejecucin, a una mquina virtual que se asegura de su ejecucin. Este cdigo se llama Microsoft Intermediate
Language(MSIL).Durantelaejecucindelaaplicacin,lamquinavirtualseencargadeestecdigoyasegurasu
traduccin en instrucciones especficas para el microprocesador de la mquina. Esta traduccin no se efecta en
bloque desde el principio de la aplicacin, sino nicamente en funcin de las necesidades. En efecto, para qu
perder tiempo traduciendo del cdigo MSIL, si no se va a utilizar despus? Es por esta razn por lo que el
compiladorutilizadoparaestatraduccinsellamacompiladorJustInTime(JIT).

Las ventajas de esta solucin son obvias, ya que para ejecutar una misma aplicacin en varias plataformas de
hardwareodesoftwarebastaconobtenerlamquinavirtualcapazdeefectuarlatraduccin.Estamquinavirtual
estdisponibleparatodoslossistemasMicrosoft.ElproyectoMonoproponeunaversindelamquinavirtualpara
lasplataformassiguientes:

l Linux,

l MacOSX,

l SunSolaris,

l BSDOpenBSD,FreeBSD,NetBSD.

Estndisponiblesparadescargarenelsitiohttp://www.monoproject.com.

Elesquemasiguienteretomaelconjuntodeestasoperaciones:

2.LosserviciosdelCommonLanguageRuntime

La mquina virtual no se conforma con efectuar la traduccin del cdigo. El cdigo MSIL tambin se llama cdigo
gestionado, lo que supone que un cierto nmero de operaciones adicionales se realizarn sobre el cdigo en el
momentodelaejecucin.LafigurasiguienterecogeelconjuntodelasfuncionalidadesdisponiblesenelCommon
LanguageRuntime.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ClassLoader

Gestionalacargaenmemoriadelasinstanciasdeclases.

ILtoNativeCompilers

Convierteelcdigointermedio(MSIL)encdigonativo.

CodeManager

Gestionalaejecucindelcdigo.

GarbageCollector

Aseguralagestindelamemoriavigilandolasinstanciasdeclasesqueyanosonaccesibles.

SecurityEngine

Permitelaverificacindelaidentidaddelapersonaqueejecutaelcdigoyaceptaonoestaejecucin,
enfuncindelospermisosotorgados.

DebugEngine

Permiteladepuracindelaaplicacinalencargarse,porejemplo,delaejecucinpasoapasodel
cdigo.

TypeChecker

Vigilaelusodevariablesnoinicializadasylasconversionesentrevariablesdetipodiferente.

ExceptionManager

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
FacilitalagestinestructuradadelasexcepcionesenrelacinconWindowsStructuredException
Handling(SEH).Estatcnicapermiteunagestinindividualdecadaexcepcinmsqueunagestin
global.

ThreadSupport

Proponeunconjuntodeclasesquepermitelarealizacindeaplicacionesmultihilo.

COMMarshaler

PermitetraducirllamadashaciacomponentesCOM,asegurandoporejemplolaconversindelostipos
dedatos.

BaseClassLibrarySupport

Facilitaelaccesoalosserviciosdisponiblesenelsistemaoperativoanfitrin.

3.LaBaseClassLibrary

ElFramework.NETponeadisposicindelosdesarrolladoresunconjuntodeherramientasquelespermiteobtener
unasolucinrpidaparalamayoradelosproblemasencontradosdurantelarealizacindeunaaplicacin.

Estasherramientasestndisponiblesenformadeclases.Alcontrariodelasbibliotecasdecdigodeloslenguajes
delageneracinanterior,quesoloeranunalistasinfindeprocedimientosofunciones,labibliotecadeclasesse
organiza con la forma de una estructura jerarquizada. El elemento esencial de esta jerarqua es el espacio de
nombres (Namespace). Permite la agrupacin lgica de clases que tienen puntos en comn. Por ejemplo,
encontramosenelespaciodenombresSystem.Datatodaslasclasesutilizablesparaaccederaunabasededatos.

Naturalmenteestabibliotecadeclasesesindependientedecualquierlenguajedeprogramacin.Permite,pues,la
mezcladediferenteslenguajesalolargodeldesarrollodeunaaplicacin.Tambinestperfectamenteintegradaa
VisualStudio,loquenosprocuraunacomodidaddeusoapreciableconherramientastalescomoIntelliSense.Como
estabibliotecaestorientadaaobjeto,esfcilmenteextensibleatravsderelacionesdeherencia.

Labibliotecacontieneunacantidadincrebledeespaciosdenombresyclasestantos,queesmuyposiblequeno
tengaqueutilizarnuncaalgunosdeellosalolargodesusdesarrollosconVisualBasic.

Losespaciosdenombresmsutilizadossonlossiguientes:

System

EselespaciodenombresrazparalostiposdedatosenelFramework.NET.Contieneenparticularla
definicindelaclaseObject,queeselancestrodetodoslostiposdedatosdelFramework.NET.

System.Windows

Contieneelconjuntodeloselementosquepermitenlacreacindeinterfacesparausuariosde
Windows.

System.Web

ContienetodoslosrecursosnecesariosparalacreacindeaplicacionesWeb,conlasclasesdela
tecnologaASP.NET,porejemplo,olasclasesutilizablesparalacreacindeserviciosWebXML.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
System.Data

Contieneunconjuntodeclasesespecializadasenelaccesoalasbasesdedatosconelsoportede
ADO.NET.

System.Xml

EllenguajeXMLestahoraportodaspartesyesteespaciodenombrescontienelasclasesque
permitenlamanipulacindedocumentosXML.

4.Lasversionesyevolucionesdelaplataforma.NET

La primera versin (1.0) de la plataforma .NET sali en enero de 2002 con Visual Studio 2002. Esta versin se
sustituy rpidamente por la versin 1.1, que corrigi algunos problemas de juventud de la versin anterior y
aadi tecnologas que solo estaban disponibles antes como instalaciones independientes. Las principales
aportacionesdeestaversinfueron:

l LoscontrolesmvilesASP.NET(antiguamenteMicrosoftMobileInternetToolkit),queextiendenelFramework.NETcon
compatibilidad con los perifricos mviles (sin cable) tales como los telfonos mviles y las agendas digitales
personales.

l El proveedor de datos .NET Framework para ODBC y el proveedor de datos para Oracle, que previamente solo
estabandisponiblesatravsdedescarga,fueronsuministradosconel.NETFramework.

l La compatibilidad de la nueva actualizacin del protocolo de Internet, comnmente llamado IP versin 6 o ms


sencillamente IPv6. Este protocolo est diseado para aumentar de manera sensible el espacio de direccionamiento
utilizadoparaidentificarlospuntosdeentradadecomunicacinenInternet.

Estdisponibleconlaversin2003deVisualStudioenabril2003.

Huboqueesperaranoviembrede2005paraverllegarlaversin2.0asociadaalasalidadeVisualStudio2005.
Estaversinaportamuchasmejoras:

l La compatibilidad con la nueva generacin de ordenadores de 64 bits que permiten la creacin de aplicaciones ms
competentes.

l UnaevolucinmayorenelaccesoalasbasesdedatosconADO.NET2.0,quemejoraelusodeXML.

l El desarrollo de aplicaciones Web es tambin cada vez ms fcil con la nueva versin de ASP.NET que propone una
multituddenuevoscontroles.

l LautilizacindelaclaseConsolasehaoptimizadoconlainsercindenuevaspropiedadesymtodos(gestindelos
colores,borrado,posicindelcursor...).

l El.NETFramework2.0vuelveaintroducirlafuncionalidadModificar&Continuar,quepermitealusuarioquedepura
unaaplicacinenVisualStudiomodificarelcdigofuenteenmododeapagado.Unavezaplicadaslasmodificaciones
delcdigofuente,elusuariopuederetomarlaejecucindelcdigoyobservarelefecto.

l La aparicin de la nocin de genrico, que permite declarar y definir clases, estructuras, interfaces, mtodos y
delegados con parmetros de tipo no especificado o genrico en lugar de tipos especficos. Los tipos reales se
especificanposteriormenteentiempodeejecucin.

Laversin3.0llegaennoviembre2006yaportanuevastecnologasalavezquesiguesiendoprincipalmenteuna
versin 2.0. Estas tecnologas estn disponibles en descargas que vienen a integrarse al Framework 2.0. A
continuacinlemostramosunvistazodeestasnovedades:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
l Windows Presentation Foundation (WPF) representaelnuevosistemadeinterfacesgrficas.Sebasaenunmotorde
aspectovectorialypermiteunaseparacinmsclaraentreladefinicindelainterfazgrficadeunaaplicacinysu
cdigo. Para esto utiliza el lenguaje XAML (eXtensible Application Markup Language). Las tareas se pueden repartir
msfcilmenteentrediseadoresydesarrolladores.

l WindowsCommunicationFoundation(WCF)constituyelanuevabasededesarrollodeaplicacionesdistribuidas.Facilita
la comunicacin entre aplicaciones aadiendo una capa de abstraccin que uniformiza las tcnicas de comunicacin
entreestasaplicaciones(ServiciosWeb,.NETRemoting,MicrosoftTransactionServeryMicrosoftMessageQueuing).

l Windows Workflow Foundation (WF) est compuesto por una plantilla de programacin de un motor de ejecucin y
herramientasparaintegrarflujosdetrabajoenunaaplicacin.Sepuededefinirunflujodetrabajocomounconjunto
de acciones o etapas que se ejecutan en un orden predefinido. Estas acciones se pueden encadenar en funcin de
condiciones,interaccionesconprocesosinformticosoenfuncindeinteraccioneshumanas.

l Windows Cardspace facilita una nueva tcnica a los usuarios para identificarse en una aplicacin. Tiene la misma
vocacinqueMicrosoftPassport,peronoesespecficadelasaplicacionesMicrosoft(Hotmail,MSDN).

La versin 3.5, de noviembre de 2007, aporta principalmente mejoras y evoluciones a las tecnologas aparecidas
con la versin 3.0. La nica verdadera novedad de esta versin corresponde a la aparicin del lenguaje LINQ
(Language Integrated Query).Elobjetivodeestelenguajeconsisteenuniformizarelmtodoutilizadoparaextraer
informacindeunafuentededatos.Estenuevolenguajepermiteconsultarcoleccionesdeobjetos,basesdedatos
SQLServer,DataSetADO.NETydocumentosXMLconlamismasintaxis.

Laversin4.0,publicadaenmayode2010,mejoraaunmslascapacidadesyfuncionalidadesdisponibles.Entre
susnovedadespodemossealar:

l La mejora del recolector de basura, que se ejecuta ahora en segundo plano. Durante una operacin de recoleccin,
los hilos de la aplicacin ya no quedan suspendidos para facilitar la limpieza de la memoria, lo que aumenta
naturalmenteelrendimientodelaaplicacin.

l La inclusin de un ncleo de ejecucin para poder trabajar con lenguajes dinmicos tales como IronPython y
IronRuby.Conestetipodelenguajes,lostiposdevariablesyanoserndeterminadosenelmomentodeldiseodela
aplicacin,sinodurantelaejecucindeesta.

l La inclusin de conceptos de covarianza y de contravarianza facilita la utilizacin de elementos genricos (clases o


mtodos).

l La disponibilidad de nuevos tipos de datos como BigInteger y Complex permiten respectivamente el uso de valores
numricosenterossinlmitesuperioroinferiorylamanipulacindenmeroscomplejos.

l Lamejoradelasclasesdemanipulacindelsistemadearchivosylacreacindearchivosmapeadosenmemoria.

l Poder tener en cuenta ms fcilmente los procesadores multincleo que permiten el reparto de los procesos con la
programacinparalela.

La versin 4.5, que sali al mercado en junio del ao 2012, es un complemento de la versin 4.0. La principal
novedad es la simplificacin de la programacin en modo asncrono. Esta tcnica evita el bloqueo de un thread
mientrasseejecutaunmtodo.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Escritura,compilacinyejecucindeunaaplicacin

Enestecaptulo,vamosadetallarelciclodevidadeunaaplicacindesdelaredaccindelcdigohastalaejecucin
delaaplicacin,estudiandoendetallelosmecanismospuestosenmarcha.

1.Escrituradelcdigo

La inmensa mayora de las aplicaciones se desarrollan gracias a un entorno integrado que agrupa las principales
herramientasnecesarias,asaber:

l Uneditordetexto.

l Uncompilador.

l Undepurador.

Este enfoque es, de lejos, el ms cmodo. Sin embargo se necesita una pequea fase de aprendizaje para
familiarizarseconlaherramienta.Paranuestraprimeraaplicacin,vamosautilizarunprocesounpocodiferenteya,
que vamos a emplear herramientas individuales: el bloc de notas de Windows para la escritura del cdigo y el
compiladorenlneadecomandosparaVisualBasic.

Nuestra primera aplicacin ser muy sencilla, ya que simplemente mostrar el mensaje Buenos das en una
ventanadecomandos.

Esteeselcdigoparanuestraprimeraaplicacin,queenseguidaexplicaremos.Sedebeintroducirconlaayudadel
bloc de notas de Windows o cualquier otro editor de texto siempre que este no aada ningn cdigo de
compaginacinenelinteriordeldocumento,comohacenporejemplolosprogramasdetratamientodetexto.

Ejemplo

Imports System
public Module test
dim mensaje as string="Buenos das"
public sub main ()
console.writeline(mensaje)
end sub
end module

Hay que guardar este cdigo dentro de un archivo con la extensin .vb. Dicha extensin no es obligatoria, pero
usndolaserespetanlasconvencionesdeVisualStudio.

Detallamosahoraalgunaslneasdenuestraprimeraaplicacin:

Imports System

EstalneapermiteaccederaloselementospresentesenelespaciodenombresSystem.Sinella,
habraqueutilizarlosnombresplenamentecualificadosparatodosloselementoscontenidosenel
espaciodenombres.Ennuestrocaso,deberamosutilizarentonces:System.Console.writeline
("Buenos das")

public Module test ... end module

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
EnVisualBasic,todapartedecdigodebeestarcontenidadentrodeunmdulooclase.

dim mensaje as string="Buenos das"

Estalneadeclaraunavariable.Sedebendeclarartodaslasvariablesantesdepoderutilizarlas.La
declaracinpermiteespecificareltipodeinformacinquelavariablevaacontener:aqu,unacadena
decaracteresyeventualmenteunvalorinicial,"Buenosdas"ennuestrocaso.

public sub Main() ... end sub

Todaslasinstruccionesquenoseandeclaracionesdebenestarubicadasenunprocedimientoouna
funcin.LamayorpartedelcdigosecolocaporlotantoentrelasinstruccionesSubyEndSubo
FunctionyEndFunction.Entretodoslosprocedimientosyfuncionessedesignaaunodeelloscomoel
puntodeentradaenlaaplicacin.Atravslaejecucindeesteprocedimientoarrancalaaplicacin.
EsteprocedimientodebeserpblicoysetienequellamarMain.

Console.writeline("Buenos das")

LaclaseConsoledefinidadentrodelespaciodenombresSystemproporcionaunconjuntodemtodos,
quepermitenmostrarinformacinenlaconsolaoleerinformacindeella.Elprocedimientowriteline
permitemostrarunacadenadecaracteresenlaconsola.

Hay que destacar tambin que Visual Basic no hace distincin entre minsculas y maysculas dentro de las
instrucciones. Si se utiliza el editor de Visual Studio para escribir el cdigo, este insertar automticamente las
modificacionesparahaceruniformelaortografadelcdigo.

2.Compilacindelcdigo

ElFramework.NETincluyeuncompiladorenlneadecomandosparaVisualBasic.Paracompilarelcdigofuentede
nuestroejemplo,debemosabrirunaventanadecomandoDOSconobjetodepoderlanzarelcompilador.Paraello
se ha creado un mtodo abreviado en el men Inicio durante la instalacin. Este mtodo abreviado lanza la
ejecucindeunarchivo.batquecolocaalgunasvariablesdeentornonecesariasparaelcorrectofuncionamientode
lasherramientasVisualStudioenlneadecomandos.

Yaconlaventanadecomandoabierta,convienecolocarseeneldirectorioenelqueseencuentraelarchivofuente.

Lacompilacinselanzaconelcomandovbc Buenos das.vb.

Tras un breve instante, el compilador nos devuelve el mando. Podemos comprobar la presencia del archivo
ejecutableysucorrectofuncionamiento.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Nuestraprimeraaplicacinesrealmentemuysencilla.Paraaplicacionesmscomplejas,sertilespecificaralgunas
opcionesparaelfuncionamientodelcompilador.Elconjuntodelasopcionesdisponiblessepuedeobtenerlanzando
elcomandovbc / ?.

Lasprincipalesopcionesson:

/out:archivo.exe

Estaopcinpermiteespecificarelnombredelarchivoresultadodelacompilacin.Pordefecto,seutiliza
elnombredelarchivofuenteactualqueestsiendocompilado.

/target :exe

Estaopcinpidealcompiladorlageneracindeunarchivoejecutableparaunaaplicacinenmodo
consola.

/target :winexe

EstaopcinpidealcompiladorlageneracindeunarchivoejecutabledeaplicacinWindows.

/target :library

Estaopcinpidealcompiladorlageneracindeunarchivolibreradll.

/referencia :lista de archivos

Estaopcinindicaalcompiladorlalistadelosarchivosreferenciadosenelcdigoynecesariosparala
compilacin.Losnombresdelosarchivossedebensepararconunacoma.

3.Anlisisdeunarchivocompilado

Ahoraquesehacreadonuestroarchivoejecutable,intentemosverloquecontiene.

Primerasolucin:abrirloconelblocdenotasdeWindows

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Elresultadonoesmuyelocuente.

HemosdichoqueelcompiladorgeneracdigoMSIL.Porlotanto,esteeselcdigoquevisualizamosenelblocde
notas.ParavisualizarelcontenidodeunarchivoMSIL,elFramework.NETproponeunaherramientamsadecuada.

Segundasolucin:utilizarundesensamblador

Estaherramientaselanzaapartirdelalneadecomandosconlainstruccinildasm.

Permite visualizar un archivo generado por el compilador de forma ms clara que con el bloc de notas. Conviene
indicarelarchivoquesedeseaexaminaratravsdelmenArchivoAbrir.Eldesensambladorvisualizaentonces
sucontenido.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
La informacin presente en el archivo se puede separar en dos categoras: el manifiesto y el cdigo MSIL. El
manifiesto contiene los metadatos que permiten describir el contenido del archivo y los recursos que necesita.
Hablamos en este caso de un archivo autodescriptivo. Esta tcnica es muy interesante, ya que, en cuanto el
CommonLanguageRuntimeleeelarchivo,disponedetodalainformacinnecesariaparasuejecucin.

Ya no es necesario utilizar una entrada en el registro de la mquina. Se puede visualizar el manifiesto haciendo
dobleclicensunombre.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
En el manifiesto encontraremos datos que indican que, para que la aplicacin pueda funcionar, necesita los
ensambladosexternosmscorlib,Microsoft.VisualBasicySystem.

La segunda parte corresponde realmente al cdigo MSIL. Se utiliza un conjunto de iconos para facilitar la
visualizacindelosdatos.

Smbolo Significado

Msinformacin

Espaciodenombres

Clase

Interfaz

Clasedevalores

Enumeracin

Mtodo

Mtodoesttico

Campo

Campoesttico

Evento

Propiedad

Elementodemanifiestoode
informacindeclase

Comoparaelmanifiesto,undobleclicenunelementopermiteobtenermsdetalles.Deestamanerapodemos,por

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ejemplo,visualizarlatraduccindenuestroprocedimientomain.

En un ejemplo de cdigo tan sencillo, es fcil encontrar la correspondencia entre el cdigo Visual Basic y su
traduccin en cdigo MSIL. Para las personas entusiasmadas con el cdigo MSIL, existe un ensamblador MSIL:
ilasm.EstaherramientaesperaunarchivodetextoquecontienecdigoMSILylotransformaenformatobinario.

YaquesomoscapacesdevisualizarelcdigoMSIL,podemosverificarsiesrealmenteindependientedellenguaje
fuenteutilizadoparadesarrollarlaaplicacin.EsteeselcdigoC#querealizalamismatareaquenuestrocdigo
VisualBasic.

using System;
class Program
{
static String mensaje = "Buenos das";
static void Main(string[] args)
{
Console.WriteLine(mensaje);
}
}

Traslacompilacinydesensamblajeporildasm,veamosloquenospresentaparaelmtodoMain.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
NohaydiferenciasenrelacinconlaversinVisualBasicdelmtodoMain.

TambinesposibledarlospasosinversosytransformarunarchivodetextoquecontienecdigoMSILenelarchivo
binariocorrespondiente.Estatransformacinsehacegraciasalensambladorilasm.Lanicadificultadconsisteen
crearelarchivodetextoquecontieneelcdigoMSIL,yaque,aunquelasintaxisescomprensible,noresultamuy
intuitiva. Una solucin puede consistir en pedir a la herramienta ildasm (el desensamblador) que genere este
archivodetexto.Paraello,despusdehaberabiertoelarchivoejecutableolalibreradllconildasm,usteddebe
utilizarlaopcin DumpdelmenArchivo.Seleinvitaentoncesaelegirelnombredelarchivoquedeseagenerar
(extension.il).

Estearchivosepuedemodificaracontinuacinconunsimpleeditordetexto.Sustituyaporejemploelcontenidode
lavariablemensajeconlacadena"Hello".

.method private hidebysig specialname rtspecialname static


void .cctor() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr "Hello"
IL_0005: stsfld string Program::message
IL_000a: ret
} // end of method Program::.cctor

Guardeelarchivo.Ahorasoloquedavolveragenerarelarchivoejecutablegraciasalensambladorilasm.Paraello,
introduzcalalneadecomandossiguiente:

ilasm Buenos das.il /output=Hello.exe

Laopcin/output=Hellopermiteindicarelnombredelarchivogenerado.Sinoseespecificaestaopcin,seutilizar
elnombredelarchivofuente.Ahorapuedelanzarelnuevoejecutableyverificarelmensajevisualizado.Todasestas
manipulaciones se pueden hacer en cualquier archivo ejecutable o librera dll. La nica dificultad reside en el
volumendeinformacinfacilitadoporladescompilacin.Sinembargo,estoconllevaunproblema:cualquierpersona
que disponga de los archivos ejecutables o bibliotecas dll de una aplicacin puede modificar la aplicacin. Por
supuestolasmodificacionespuedenresultarpeligrosas,sobretodosilamodificacinafectaunvalorquerepresenta
una informacin importante de la aplicacin (contrasea, clave de licencia...). Un remedio contra este tipo de
manipulacinconsisteenhacerlomsincomprensibleposibleelcdigogeneradoporeldescompilador.Paraello,
hay que actuar a nivel del archivo ejecutable o de la biblioteca dll modificando los datos que contiene sin, por
supuesto, perturbar el funcionamiento. Hay herramientas llamadas ofuscadores son capaces de realizar esta
operacin. Visual Studio se facilita con una herramienta de la empresa PreEmptive Solutions llamada DotFuscator
Community Edition. Esta versin permite realizar las operaciones bsicas paraembrollar unarchivo.Elprincipal
tratamiento efectuado en el archivo consiste en renombrar los identificadores contenidos en l (nombre de las
variables, nombre de los procedimientos y funciones...) con valores muy poco explcitos, en general de caracter
nico. He aqu un extracto de la descompilacin del archivo Buenos das.exe tras su tratamiento con Dofuscator
CommunityEdition.

.class private auto ansi beforefieldinit a


extends [mscorlib]System.Object
{
.field private static string a
.method private hidebysig static void a (string[] A_0) cil managed

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
{
.entrypoint
// Code size 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldsfld string a::a
IL_0006: call void [mscorlib]System.Console::WriteLine(string)
IL_000b: nop
IL_000c: ret
} // end of method a::a

.method public hidebysig specialname rtspecialname


instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method a:: .ctor

.method private hidebysig specialname rtspecialname static


void .cctor() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: ldstr "Buenos das"
IL_0005: stsfld string a::a
IL_000a: ret
} // end of method a:: .cctor

} // end of class a

Enestearchivoesimposibleencontrarlosnombresutilizadosenelcdigo.Elprocedimientomainsellamaahoraa,
lavariablemensajetambinsellamaa.Imagneseelresultadodeestetratamientoenunarchivoquecontiene
variasdecenasdevariablesyprocedimientos!

La versin Professional Edition permite adems la encriptacin de las cadenas de caracteres, la modificacin y el
aadidodecdigointilparacomplicarlasestructurasdecontrol(bucles,condiciones).

AcontinuacinpresentamosunejemplodetransformacindeladocumentacindeDotFuscator.

Elcdigooriginal:

public int CompareTo(Object o)


{
int n = occurrences - ((WordOccurrence)o).occurrences;
if (n == 0)
{
n = String.Compare(word, ((WordOccurrence)o).word);
}
return(n);
}

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Elcdigogenerado:

public virtual int _a(Object A_0) {


int local0;
int local1;
local0 = this.a - (c) A_0.a;
if (local0 != 0) goto i0;
goto i1;
while (true) {
return local1;
i0: local1 = local0;
}
i1: local0 = System.String.Compare(this.b, (c) A_0.b);
goto i0;
}

El anlisis de miles de lneas de cdigo de este tipo puede provocar dolor de cabeza! Por lo tanto, es preferible
conservar el cdigo original para las modificaciones posteriores. Hay ms informacin disponible en el sitio web:
http://www.preemptive.com/

4.Ejecucindelcdigo

Cuando un usuario ejecuta una aplicacin gestionada, el cargador de cdigo del sistema de explotacin carga el
CommonLanguageRuntime,queluegolanzalaejecucindelcdigogestionado.Comoelprocesadordelamquina
enlaqueseejecutalaaplicacinnopuedeencargarsedirectamentedelcdigoMSIL,elCommonLanguageRuntime
debeconvertirloencdigonativo.

Esta conversin no se aplica a la totalidad del cdigo cargado en la aplicacin. Convierte el cdigo segn las
necesidades.Lospasosadoptadossonlossiguientes:

l Al cargar una clase, el Common Language Runtime sustituye cada mtodo de la clase con un trozo de cdigo que
requierealcompiladorJITquelocompileenlenguajenativo.

l Luego,cuandoseutilizaelmtodoenelcdigo,laporcindecdigogeneradoenlacargaentraenaccinycompila
elmtodoencdigonativo.

l Eltrozodecdigoquerequierelacompilacindelmtodoluegoessustituidoporelcdigonativogenerado.

l Lasfuturasllamadasdeestemtodoseharndirectamenteenelcdigonativogenerado.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
EvolucindeVisualBasic1aVisualBasic.NET2012

Desdelaversin1.0de1991hastalaversin6.0de1998,VisualBasichasufridomuchasevoluciones.Enelorigen
sediseVisualBasiccomounlenguajesencilloquepermitadesarrollarrpidamenteunaaplicacinparaWindows
(comolopermitaGWBASICparaMSDOS).Estasencillezdeusosebasaengranmedidaenelentornodedesarrollo
queocultalastareasfastidiosasdelacreacindeunaaplicacinparaWindows.

De la versin 1.0 a la versin 3.0, no asistimos a ninguna revolucin en VB, sino a las evoluciones clsicas de un
lenguajedeprogramacin.

Conlaaparicindelaversin4.0en1996,VBpasamedirseconlosmejores,graciasaunamultituddeevoluciones:

l Posibilidaddecrearaplicacionesde32bits(todavaestabaaseguradalacompatibilidadconaplicacionesde16bits).

l CreacindeDLLapartirdeVB.

l UtilizacindeDLL(escritasenVBocualquierotrolenguaje).

l AparicindefuncionalidadesobjetoenVB(usodeclases).

Apesarde,omsbienacausade,todasestasevoluciones,laversin4.0deVBnoeramuyestable.

Rpidamente, en 1997, Microsoft sac la versin 5.0 de Visual Basic, que no aport, grandes evoluciones salvo la
desaparicindelasaplicacionesde16bits.

Lasevolucionesdelaversin6.0,quesaliunaomstarde,sebasanprincipalmenteenelmtododeaccesoalas
bases de datos, con la sustitucin de DAO (Data Access Object) de las versiones anteriores por ADO (Active Data
Object),queseconviertedehechoenelmtodocomnaloslenguajesMicrosoftparaelaccesoalosdatos.

Sin embargo, esta versin deber esperar el service pack 4 para permitir el funcionamiento correcto de ciertos
controlesdeaccesoalosdatos(elDataEnvironment).

Aunqueestgeneradaencdigonativoporlacompilacin,unaaplicacinVBsiemprerequiereelmduloruntimepara
poderejecutarseenunamquina(vbrun.dll),yaque,adiferenciadeloslenguajescomoC++,VBnoutilizalainterfaz
deprogramacinWIN32parallamarlasfuncionesdelsistemaoperativo.

Laversinsiguiente,queseestrenaen2002,aportacambiosradicalesenVisualBasic.Estaversinseintegraenla
suiteVisualStudio.NET,quesebasaenunanuevainfraestructuraparalacreacinylaejecucindeaplicacionesbajo
Windows: el Framework .NET. Los principios de funcionamiento de esta infraestructura se describen en el captulo
Presentacindelaplataforma.NET.

Lasversiones2003y2005siguenlaevolucindelFramework.NET(versin1.1luego2.0)aportandocadavezms
funcionalidadesyherramientasquefacilitanyaceleraneldesarrollodeaplicaciones.

Laversin2008tambinaportasuconjuntodenovedades,entrelascualeslasmsnotablessonlassiguientes:

l PosibilidaddegenerarunaaplicacinparaunaversinespecficadelFramework(2.0,3.0,3.5).

l CompatibilidadomejoradelacompatibilidaddenuevastecnologasparaeldesarrolloWeb(AJAX,JavaScript,CSS...).

l IntegracindeLINQenloslenguajesVisualbasicyVisualC#,quepermiteuniformizarelaccesoalosdatosdemanera
independientedelafuente(objetos,basesdedatos,archivoXML).

l Inclusindeunaherramientademapeoobjeto/relacional(O/RDesigner).

l CreacindeaplicacionesWPFoptimizadasparaWindowsVista.

l PosibilidaddecrearinformesconReportDesigner(ensustitucindeCrystalReport).

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
La versin 2010, estrenada en mayo de 2010, prosigue la evolucin de este lenguaje. El objetivo sigue siendo
proponer al usuario muchas funcionalidades que le permitan aumentar su productividad al escribir menos lneas de
cdigo.Entreestasfuncionalidadespodemossealar:

l Posibilidaddeescribirunainstruccinsobrevariaslneassintenerqueutilizarelcarcterdecontinuacin(_)exigidoen
lasversionesanteriores.

l Implantacinautomticadelaspropiedadesdelasclases.

l Inicializacindecoleccionesdurantelacreacin.

l Generacinautomticadeclases,mtodos,estructuras,propiedadesapartirdesuutilizacin.

l Compatibilidadconlavarianzadurantelautilizacindeloselementosgenricos(clases,interfaces,delegados...).

La versin 2012 de Visual Basic integra las novedades del Framework 4.5, como por ejemplo la simplificacin de la
programacin asncrona, aadiendo dos nuevas palabras claves: async y await. El entorno de desarrollo tambin
ofrece nuevas funcionalidades. Entre ellas, la jerarqua de llamadas ser una preciada ayuda para mejorar el
seguimientodelflujodeejecucindeunaaplicacinyanticiparlasconsecuenciasdeunamodificacindelcdigo.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Instalacinyprimerarranque

1.Configuracinnecesaria

Para permitir un correcto funcionamiento, Visual Studio necesita una configuracin mnima. Microsoft aconseja los
siguientesvalores:

Componente Mnimorecomendado Prestacionesptimas

Procesador Pentium1,6GHzoequivalente Pentium2,2GHzoms

RAM 1024MB 2048MBoms

Espaciodedisco 3 GBeneldiscodesistemayde2,8
a3,8GBenotrodisco

Vdeo 1024x768 1280x1024oms

LectorCDRomoDVD Indispensable Indispensable

Sistemaoperativo Windows7 Cualquierversinposterior(Windows)


WindowsServer WindowsServer2012

2.Procedimientodeinstalacin

Loselementosnecesariosson:

l LosCDRomoDVDdeVisualStudio.NET.

l Espaciodisponibleensudiscoduro(de3,8a5GBenfuncindelasherramientasinstaladas).

l Ysobretodopaciencia,yaquelainstalacineslarga...

DespusdeinsertarelprimerDVDyalgunossegundosdecarga,sevisualizalapantallasiguiente:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Estapantallaleproponeseleccionareldirectoriodeinstalacindelproductoyleindicaelespacioendisconecesario
paraestainstalacin.Paraproseguirconlainstalacin,tambindebeaceptarelcontratodelicencia.Lasiguiente
etapalepermiteseleccionarlasfuncionalidadesadicionalesquedeseainstalareiniciarlainstalacindelproducto.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lasiguientepantallaleinformadelprogresodelainstalacin:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Es necesario ser paciente porque el proceso de instalacin puede ser bastante largo, en funcin de las opciones
quesehayanseleccionado.

Alfinalizarelproceso,lasiguientepantallaleinformadelxitodelainstalacinyleofrecelaposibilidaddeejecutar
directamenteelproducto.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
3.Primerlanzamiento

UnaccesodirectocreadoautomticamenteporelprogramadeinstalacinlepermitelanzarVisualStudio.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Durante el primer lanzamiento, Visual Studio le propone personalizar el entorno de trabajo. En funcin de su
preferencia por un idioma determinado, Visual Studio configura el entorno con las herramientas adaptadas. Se
puede modificar esta configuracin ms adelante con el men Herramientas Importar y exportar
configuraciones.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Ahoradebemosexaminarlasherramientasanuestradisposicin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Descubrimientodelentorno

1.Pginadeinicio

EstapginasevisualizacadavezqueiniciaVisualStudio.Lepermiteaccederrpidamentealosltimosproyectos
en los que ha trabajado, crear un nuevo proyecto o abrir un proyecto existente. La pestaa ltimas noticias
permiteactivarunflujoRSSquefacilitainformacindelasactualizacionesdisponibles.

Alcrearunnuevoproyectooabrirunproyectoexistente,selanzaelentornoVisualStudio.

2.EntornoVisualStudio

Elentornosecomponedetrestiposdeelementos:

l Unazonadebarrademensydebarrasdeherramientas.

l Unazonacentraldetrabajo.

l Unamultituddeventanasqueconstituyenlasdiferentesherramientasanuestradisposicin.

Elconjuntopresentaunaspectocargadoy,despusdeaadirunaodosbarrasdeherramientas ylaaparicinde
algunas ventanas adicionales, la zona de trabajo se hace muy angosta, sobre todo en una pantalla de tamao
reducido.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Afortunadamente,hayvariassolucionesdisponiblesparagestionarnuestroespaciodetrabajo:

l Elanclajedelasventanas.

l Laocultacinautomticadeventanas.

l Lautilizacindepestaas.

El anclaje de ventanas no sirve para ganar espacio en la pantalla, pero nos permite colgar en un borde de la
pantallaodeunaventanatalocualventana.Tambinesposibleconvertircadaventanaenflotante,alhacerdoble
clicensubarradettulooalutilizarelmencontextual.Luegosepuededesplazaroanclarestaventanaenotro
borde.Paraguiarnosenelanclajedeunaventana,VisualStudiomuestra,durantesudesplazamiento,unasguas
quepermitenelegirelbordedondeefectuarelanclaje.

Los iconos situados en la periferia de la pantalla permiten el anclaje en el borde correspondiente de la

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
pantalla.Losiconos queaparecenenelcentrodelaventanacuandoelratnpasaporencimadeella

controlanelanclajeensusbordesocomopestaaadicionalparalaventana.
Msinteresantesparaganarespacioenlapantalla,lasventanasocultablessolosonvisiblessielcursordelratn
se encuentra encima de su superficie. Si no, solo una zona de pestaas, ubicada en el borde del entorno de
desarrollo,permitequesemuestresucontenido.Paraconservarsiemprevisibleunaventana,bastaconbloquearla

utilizandolachinchetapresenteensubarradettulo .

Finalmente,lautilizacindepestaaspermitecompartirunamismazonadepantallaentrediferentesventanasy,
enestesentido,losdiseadoresdeVisualStudiolashanutilizadosinmoderacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Lasherramientasdisponibles

Miremosmsendetallelasdiferentesbarrasdeherramientasyventanasqueestnanuestradisposicin.

1.Lasbarrasdeherramientas

EnVisualStudiohaycomomnimotreintabarrasdeherramientasdisponibles.Lavisualizacindecadaunadeellas
sepuedecontrolarconelmencontextual,haciendodobleclicenlabarraprincipaldemens.

Por supuesto, es intil visualizar el conjunto de las barras de herramienta de manera simultnea solo deben
mostrarselasmstiles.

Estndar

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Editordetexto

Editordecuadrosdedilogo

Ubicacin

Depurar

Las otras barras disponibles se muestran sobre la marcha y en funcin de sus necesidades con el fin de evitar
sobrecargarsupantalla.

Lasventanasdisponiblessontambinbastantenumerosasyvamosadescubrirlasmscorrientes.

2.Elcuadrodeherramientas

A partir del cuadro de herramientas, vamos a elegir los elementos utilizados para el diseo de la interfaz de la
aplicacin.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Elcuadrodeherramientasseorganizaporsecciones,quepermitenencontrarloscontrolesfcilmente.

Cada uno podr personalizar su cuadro de herramientas al aadirle, por ejemplo, controles no disponibles por
defecto.Puedeserconveniente,antesdeaadircontrolesalcuadrodeherramientas,crearunanuevaseccinpara
albergarlos. Para ello, visualice el men contextual del cuadro de herramientas (haciendo clic con el botn
secundariodelratnenelcuadrodeherramientas),elijalaopcinAgregarFicha,luegodunnombrealanueva
seccin as creada. Despus de haber seleccionado esta nueva seccin, puede aadirle controles. Visualice de
nuevoelmencontextualdelcuadrodeherramientas,yescojalaopcinElegirelementos.

Sepresentaentonceslalistadeloscontroles(COMo.NET),disponiblesenlamquina,quelepermiteseleccionar
los controles que se deben insertar en esta seccin del cuadro de herramientas. La configuracin del cuadro de
herramientasnoestrelacionadaconelproyectoactivo,sinoconelpropioentorno(elcuadrodeherramientasser
idnticoseacualseaelproyectoabierto).

3.Elexploradordeservidores

El explorador de servidores est disponible con el men Visualizacin Explorador de servidoresomedianteel


mtodoabreviadodeteclado[Ctrl][Alt]S.Sevisualizaenunanuevapestaadelaventanaasociadaalcuadrode
herramientas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Lamayoradelasaplicacionesrequierenotrasmquinaspresentesenlaredparapoderfuncionar.Porlotanto,es
necesariotener,durantelafasededesarrollodeunaaplicacin,laposibilidaddeaccederalosrecursosdisponibles
enotrasmquinas.

El elemento de la ventana Explorador de servidores que se utiliza de manera ms frecuente ser la seccin
Conexionesdedatos.

En particular permite la gestin de los objetos disponibles en el servidor SQL (tablas, vistas, procedimientos
almacenados).

Elexploradordeservidorestambinpermitegestionarlosserviciosquefuncionanenlasmquinas,tantoatravs
delainterfazgrficacomodelcdigo.Ofrecelaposibilidaddevisualizarlaactividaddelasmquinasanalizandolos
contadores de rendimiento o recuperando la informacin en los diferentes registros de eventos. Un sencillo
arrastrarsoltarentreelexploradordeservidoresyunaventanadediseogeneraautomticamenteelcdigoque
permite manipular este elemento en la aplicacin. Por ejemplo, el desplazamiento de un contador de rendimiento
sobreunaventanageneraelcdigosiguiente:

Friend WithEvents perfCptMemoria As System.Diagnostics.PerformanceCounter


Me.perfCptMemoria = New System.Diagnostics.PerformanceCounter

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Me.perfCptMemoria.CategoryName = "Memoria"
Me.perfCptMemoria.CounterName = "Kilo-bites disponibles"
Me.perfCptMemoria.MachineName = "portatilTG"

4.Elexploradordesoluciones

Elexploradordesolucionespermitelavisualizacindeloselementosqueconstituyenunasolucinylamodificacin
desuspropiedades.

La utilizacin del explorador de soluciones se presenta en detalle en el captulo dedicado a la organizacin de una
aplicacin.

5.Lavisualizacindeclases

LavisualizacindeclasesesaccesibleconelmenVerOtrasventanasVistadeclasesoconlacombinacinde
teclas[Ctrl][Shift]C.Compartesuzonadepantallaconelexploradordesoluciones.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
La visualizacin de clases permite tener una visin lgica de una solucin presentando las diferentes clases
utilizadasenestasolucin.

6.Laventanadepropiedades

Laventanadepropiedadessepuedevisualizarcontresmtodos:

l UtilizandoelmenVerVentanaPropiedades.

l Conlatecladefuncin[F4].

l Conlaopcin Propiedadesdelmencontextualdisponiblealhacerclicconelbotnsecundariodelratnenunode
loselementosqueconstituyeunproyecto(elementogrficodelainterfazdeusuario,archivoocarpetadelproyecto).
La ventana de propiedades adapta automticamente su contenido en funcin del elemento seleccionado y permite
modificarestascaractersticas.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Loselementoscuyascaractersticasdeseamodificarsepuedenseleccionardirectamenteenlalistadesplegableo
enlainterfazdelaaplicacin.

Haydospresentacionesdisponiblesparalalistadepropiedades:

ElmodoAlfabtico,queseactivaalhacerclicenelicono .


ElmodoPorcategora,queseactivaalhacerclicenelicono .

7.Lalistadetareas

EstaventanalepermitirsustituirdecenasdePostitpegadosenelbordedesupantalla.Enefecto,ustedpodr
gestionar lo que queda por hacer en su proyecto teniendo en cuenta una lista de modificaciones pendientes de
aportarasucdigo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Lainformacinpresenteenlalistapuedetenerdosorgenes:

l Loscomentariosinsertadosensucdigo.

l Lainformacinintroducidadirectamenteenlaventana.

Puede ubicar en su cdigo comentarios que aparecern luego en la lista de tareas. Esta tcnica le permite, por
ejemplo,indicarunamodificacinquedebaefectuarmstardeensucdigo.

Bastaconqueelcomentarioempieceportodoparaluegoretomarloautomticamenteenlalistadetareas.

Tambin puede introducir directamente los datos en la lista de tareas. Para ello deber elegir tareas de usuario
utilizandolazonadelistadisponibleenlabarradettulodelalistadetareas.


Lainclusindeunatareaseejecutaconelbotn ,disponibleenlalistadetareas.

Puedeespecificarunadescripcinyunaprioridadparalanuevatareahaciendoclicenlacolumnadeizquierda,enla
listadetareas.Haytresnivelesdeprioridaddisponibles:

l Alta.

l Normal.

l Baja.

Para cada tarea, una casilla de verificacin permite indicar si se ha realizado. Su descripcin aparece entonces
tachadaenlalistadetareas.Paralastareasdeusuario,nohayenlaceautomticoconunaporcincualquierade
cdigo.

8.Lalistadeerrores

El cdigo que introduce es analizado continuamente por Visual Studio y los posibles errores de sintaxis que
encuentrasemuestranenlaventanaListadeerrores.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Para ir directamente a la lnea donde apareci un error de sintaxis, basta con hacer doble clic en el elemento
correspondientedelalista(enelejemploanterior,hagadobleclicen{Elcarcternoesvlidoparaalcanzarla
lnea 7). No es necesario pedir la compilacin completa del cdigo para rastrear todos los errores de sintaxis. En
cuantoelerrorquedacorregido,desapareceautomticamentedelalistadeerrores.

Losbotonesde errores,advertenciasymensajesactivanunfiltrosobrelosmensajesvisualizadosenlalistade
errores.

9.Laventanadeedicindelcdigo

Vamosadedicarmstiempoaestaventana,yaqueproponemuchasfuncionalidadesquepermitenautomatizarlas
accionesmscorrientes.

a.LosSnippetsofragmentosdecdigo

Los Snippets son fragmentos de cdigo que se pueden incorporar muy fcilmente a un archivo fuente. Permiten
escribirrpidamenteporcionesdecdigorelacionadoconsituacioneshabituales.VisualStudiopropone,deforma
predeterminada,unamultituddeSnippets.HaydossolucionesdisponiblesparainsertarunSnippet:

l UsarlaopcinInsertarfragmentodecdigodelmencontextualdeleditordecdigo.

l Usarlascombinacionesdeteclas[Ctrl]K,luego[Ctrl]X.

Para estos dos mtodos, Visual Studio le propone elegir en una lista el Snippet que le interesa. Se pueden
personalizarestasporcionesdecdigodelSnippet,queestnresaltadasenazulclaro.Lamodificacindeunade
estasporcionesdecdigorepercuteentodaslasaparicionesenelSnippet.

Enelejemploquevieneacontinuacin,seutilizunSnippetparaaadirunanuevapropiedadaunaclase.

SeefectuarlamodificacindelosvaloresnewPropertyValue,StringyNewPropertyencascadaenelconjuntodel

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
cdigodelSnippet.

UstedtambinpuededisearsuspropiosSnippets.Paraello,debecrearunarchivoXMLquecontendrelcdigo
delSnippet,ydarlelaextensin.snippet.

ParaayudarleenlacreacindeunSnippet,MicrosofttieneprevistounSnippet.Ustedpuedeincorporarloensu
archivoXMLconelmencontextualInsertarfragmentodecdigoSnippet.

Obtendreldocumentosiguiente:

<?xml version="1.0" encoding="utf-8" ?>


<CodeSnippet Format="1.0.0"
xmlns="http://schemas.microsoft.com/VisualStudio/2005/CodeSnippet">
<Header>
<Title>title</Title>
<Author>author</Author>
<Shortcut>shortcut</Shortcut>
<Description>description</Description>
<SnippetTypes>
<SnippetType>SurroundsWith</SnippetType>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>
<Snippet>
<Declarations>
<Literal>
<IDname/ID>
<Defaultvalue/Default>
</Literal>
</Declarations>
<Code Language="XML">
<![CDATA[<test>
<name>$name$</name>
$selected$ $end$</test>]]>
</Code>
</Snippet>
</CodeSnippet>

AcontinuacinpodrpersonalizarsuSnippet.Enprimerlugar,debermodificarlaseccinHeadersustituyendolos
valoresdelasdiferentesetiquetas.

<Header>
<Title>Recorre una matriz de datos</Title>
<Author>Thierry</Author>
<Shortcut>matriz</Shortcut>
<Description>Funcionalidad que permite recorrer una
matriz de datos</Description>
<SnippetTypes>
<SnippetType>Expansion</SnippetType>
</SnippetTypes>
</Header>

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LaseccinDeclarationspermitecrearparmetrosutilizadosenelSnippet.Paracadaparmetro,debercrearuna
seccin<Literal>yfacilitarunnombreparaelparmetroyunvalorpordefecto.

<Declarations>
<Literal>
nombreMatriz</ID>
<Default>laMatriz</Default>
</Literal>
<Literal>
tipoMatriz</ID>
<Default>tipoDelaMatriz</Default>
</Literal>
<Literal>
tamaoMatriz</ID>
<Default>tamaoDelaMatriz</Default>
</Literal>
</Declarations>

LuegodebeindicarparaqulenguajeestprevistosuSnippet.

<Code Language="VB">

Y finalmente definir en la etiqueta CDATA el cdigo Snippet. En este cdigo, puede utilizar los parmetros del
Snippetenmarcndolosentredoscaracteres$.

<![CDATA[
dim $nombreMatriz$($tamaoMatriz$) as $tipoMatriz$
dim index as integer
for index=0 to $tamaoMatriz$ -1
aada el cdigo que gestiona la matriz
next ]]>

Luego puede guardar el archivo y su Snippet est listo. Conviene ahora integrarlo en Visual Studio. Para ello,
deberactivarelgestordeSnippetatravsdelmenHerramientasAdministradordefragmentosdecdigo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
ElbotnImportarpermiteaadirsuSnippetalosyadisponiblesenVisualStudio.

Despus de haber seleccionado el archivo que contiene el Snippet, deber elegir la ubicacin en la que se
guardar.

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
SuSnippetestahoradisponibleeneleditordecdigo.

Sololequedapersonalizarelcdigogenerado.

b.Seguimientodelasmodificaciones

PuedevisualizarlosfragmentosdecdigoqueyahansidomodificadosdesdeellanzamientodeVisualStudio.Se
identificanlasmodificacionesconunbordedecolorenelmargendeleditordecdigo.

l Unbordeamarilloindicaquesehamodificadoelcdigo,peroqueannohasidoguardado.

l Unbordeverdeindicaquesehamodificadoyguardadoelcdigo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Tambin puede renombrar fcilmente un elemento y propagar de forma automtica la modificacin al resto del
cdigo. El uso tpico consiste en cambiar el nombre de una variable o clase. No debe renombrar la variable
directamente en el cdigo, sino utilizar el cuadro de dilogo visualizado usando la opcin Cambiar nombre del
mencontextualdeleditordecdigosobreelnombreactualdelavariable.

Lamodificacinrealizadamedianteestecuadrodedilogorepercutesobreelconjuntodelcdigodondeseutiliza
lavariable.

10.Lasherramientasdeedicindecdigo

LoseditoresdetextodeVisualStudiodisponendemuchasfuncionalidadesquepermitenfacilitarlasoperaciones
efectuadasconfrecuenciadurantelaescrituradelcdigodeunaaplicacin.

Seleccindetexto

Como complemento de las funciones clsicas de seleccin de texto y de copiarpegar, el editor de Visual Studio
permitelaseleccindezonasrectangularesdetextoalmantenerpulsadalatecla[Alt]durantelaseleccin.Cuando
seintroducetextoenlaseleccin,eltextoseduplicaencadalneadelaseleccin.

Sedisponeporejemplodelmtodosiguiente,quevisualizaenlaconsolalosdatospersonalesdeunindividuo:

Private Sub visualizacinResultados(ByVal c As Cliente)


Console.Write("Apellido:" + c.Apellido);
Console.Write("Nombre:" + c.Nombre);
Console.Write("Calle:" + c.Calle);
Console.Write("Cdigo Postal:" + c.CdigoPostal);
Console.Write("Ciudad:" + c.Ciudad);
Console.Write("Telfono:" + c.Telefono);
Console.Write("Correo electrnico:" + c.Correo)
End Sub

Para modificar este mtodo y escribir estos datos en un archivo en vez de visualizarlos en la consola, solo es
necesariocrearelarchivoymodificartodaslasinstrucciones.Writeparaqueseapliquenenelarchivocreado.Para
ello,aadasimplementelalneasiguienteparalacreacindelarchivo:

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim archivo As StreamWriter = New StreamWriter("resultados")

Modifiquedespuscadainstruccin.Writeparaescribirhaciaelarchivo,ynohacialaconsola.Seleccioneparaello
unazonarectangularquecontengatodaslaspalabrasconsoleeintroduzcalapalabraarchivo.

SesustituyeentonceslapalabraConsoleentodaslaslneasdelaseleccin.

Tambinesposibleinsertartextosimultneamenteenvariaslneascreandounazonadeseleccinrectangularde
cerocaracteresdeanchoentodaslaslneasdondesedebeefectuarlainsercin.

Acontinuacinseinsertaeltextointroducidoentodaslaslneasdelaseleccin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Resaltarlasreferencias

Al hacer clic en un smbolo en el cdigo fuente, todas las instancias de este smbolo quedan marcadas en el
documento.

FuncionalidadGenerarconeluso

Duranteeldesarrollodeunaaplicacin,avecesocurrequeseintentautilizarunelementoantesdesudeclaracin,
posponiendoestaparamstarde.Sinembargo,estasolucintieneelinconvenientedenopoderrealizarningn
test hasta que todos los elementos utilizados hayan sido definidos. Tambin es deprimente para el desarrollador
verdecenasdelneasdecdigosubrayadasenrojo.

EleditordeVisualStudioescapazdegenerarelcdigonecesarioparaloselementosquefaltan.Cuandoelratn
pasasobreelelementoreferido,apareceunbotndebajodelelemento.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Alhacerclicenestebotn,apareceunmencontextualqueproponelasopcionesquepermitengenerarelcdigo
quepuederesolverlosproblemasdetectados.

Seadaptanlasopcionesdisponiblesenestemencontextualsegnlaubicacindelelementoenelqueesteest
activado. En el ejemplo anterior, el trmino nombre puede corresponder a un nombre de mtodo, propiedad o
variable.Segnloscasos,sepuedevisualizaruncuadrodedilogoparapersonalizarlageneracindelcdigo.Solo
hacefaltacompletarelcuadrodedilogosiguienteparaqueelesqueletodecdigosegenere.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
Zoom

Estafuncionalidadpermiteefectuarunzoomhaciadelanteoatrssobreunaventanadetexto.Sepuedeaccedera
ellaaccionandolaruedadelratnmientrassemantienelatecla[Ctrl]pulsada.

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lassoluciones

1.Presentacin

Paraayudarleenlacreacindeaplicaciones,VisualStudioleproponevarioselementosquesirvenparaagruparlos
componentesdeunaaplicacin.Elcontenedordemsaltoniveleslasolucinenlaquepodrubicarunoovarios
proyectos.Estosproyectoscontendrn,asuvez,todosloselementosparaqueelcompiladorseacapazdegenerar
el archivo ejecutable o dll del proyecto. El explorador de soluciones nos va a permitir manipular todos estos
elementos.

2.Creacindeunasolucin

La creacin de una solucin es automtica cuando se empieza un nuevo proyecto en Visual Studio. Durante la
creacindelnuevoproyecto,selepedirinformacinalrespecto.

Atravsdelcuadrodedilogo,podrfacilitarlosdatossiguientes:

l LaversindelFrameworknecesarioparautilizarlaaplicacin.

l Ellenguajeutilizadoparadesarrollarelproyecto.

l Eltipodeproyectoquesevaacrear.

l Elnombredelproyecto.

l Eldirectorioprincipaldondeestarnalmacenadoslosarchivos.

l Elnombredelasolucin.

l Lacreacindeundirectorioparalasolucin.

Despusdevalidarestecuadrodedilogo,elexploradordesolucioneslepresentalanuevasolucinenlaquevaa
podertrabajar.Todoslosarchivosquelacomponenyaestncreadosyguardadosensudisco,enlaubicacinque
ustedhaespecificado.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Unasolucincontendr,almenos,losarchivossiguientes:

l Unarchivoconlaextensin.sln,queeselarchivodeconfiguracindelasolucin.Estearchivocontiene,entreotros,
lalistadetodoslosproyectosquecomponenlasolucin.Secompletaamedidaqueseaadennuevosproyectosala
solucin.

l Un archivo con la extensin .suo, donde se guardan las opciones asociadas a la solucin. Este archivo permite
encontrarestasopciones.

l Un archivo para el proyecto, con la extensin .vbproj. Este archivo contiene todos los datos de configuracin del
proyecto,juntoconlalistadelosarchivosqueloconstituyen,lalistadelasreferenciasutilizadasenl,lasopcionesa
utilizarparalacompilacindelproyecto,etc.

l Numerososarchivosconlaextensin.vb,quecontendrnelcdigofuentedetodaslasclases,hojasymdulosque
constituyenelproyecto.

l Unarchivo.resxasociadoacadahojadesuaplicacin.EstearchivoenformatoXMLcontiene,entreotras,lalistade
losrecursosutilizadosenestahoja.

l Alfinal,unasolucincontieneotrosmuchosarchivosenfuncindeloselementosutilizadosensuproyecto(accesoa
unabasededatos,archivosHTML...).

3.Modificacindeunasolucin

Lassoluciones,comocontenedoresqueson,permitengestionarsuselementos.Esposibleaadir,suprimir,cambiar
elnombredeelementosenlasolucin.

a.Aadirunproyecto

Hayvariasposibilidadesdisponiblesparaaadirunproyecto:

Si desea crear un nuevo proyecto, elija la opcin Nuevo Proyecto del men Archivo Agregar. Un
cuadrodedilogoleproponeentoncesconfigurarlascaractersticasdelnuevoproyectoy,enparticular,
definir un directorio por defecto para guardar el proyecto. Si este directorio no corresponde a la
ubicacin donde usted desea guardar el proyecto, puede seleccionar una nueva. Esta operacin se
deberrealizarparacadaproyectoquedeseeaadir.Puedeserinteresantemodificarlarutapropuesta
por defecto para guardar los proyectos. Para hacerlo, abra el men Herramientas Opciones, en el
cuadro de dilogo elija la opcin Proyectos y soluciones y modifique la seccin Ubicacin de los
proyectos.

Si usted desea aadir un proyecto ya existente, elija la opcin Abrir proyecto del men Archivo
Agregar.Uncuadrodedilogodeseleccindearchivoslepermiteentonceselegirelarchivo.vbprojdel
proyectoquequiereaadiralasolucin.

Tengaencuentaqueelproyectosequedaensuubicacindeorigeneneldisco.

b.Suprimirunproyecto

Para suprimir un proyecto, utilice el men contextual del explorador de soluciones efectuando un clic
sobreelnombredelproyectoquedeseasuprimirdelasolucin.

Sehaeliminadoelproyectodelasolucin,peroquedagrabadoeneldisco.Parasuprimirlodemaneradefinitiva,
utiliceelexploradordeWindowsparasuprimirlosarchivosdeesteproyecto.Sinoborralosarchivos,sepuede
aadirdenuevoelproyectoaunasolucinenotromomento.

c.Cambiarelnombredeunproyecto

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Paracambiarelnombredeunproyecto,utiliceelmencontextualdelexploradordesolucioneshaciendo
clicconelbotnsecundariodelratnenelnombredelproyectoquedeseacambiar.

Elnombredelproyectoseconvierteentoncesenmodificableenelexploradordesoluciones.Estamodificacinse
refierenicamentealnombredelarchivo.vbprojasociadoalproyecto.Nomodificaenningncasoelnombredel
directorioenelqueseencuentranlosarchivosdelproyecto.

d.Descargarunproyecto

Cuando desee excluir de manera temporal un proyecto del proceso de generacin o impedir la edicin de sus
componentes,puededescargarelproyectodelasolucinusandolaopcinDescargarelproyecto.

Noseretiraunproyectodescargadodelasolucin,sinoquesimplementequedamarcadocomoNodisponible.

Porsupuesto,sepuederehabilitarelproyectoenlasolucinutilizandolaopcinVolveracargarelproyectodel
mencontextual.

4.Organizacindeunasolucin

Si est trabajando con una solucin que contiene varios proyectos, puede aadir un nuevo nivel de jerarqua
creandocarpetasdesolucin.Estaspermitenlaagrupacinlgicadeproyectosdentrodeunasolucin.

Paraello,creeprimerolascarpetasenlasolucin,ydespusorganicelosproyectosenestascarpetas.

Las carpetas de solucin no crean carpetas fsicas en el disco, solo son contenedores lgicos en el interior de la
solucin.

a.Creacindeunacarpetadesolucin

Sepuedecrearunacarpetadesolucinusandodosmtodos.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Enambos,seleccionelasolucinenelexploradordesoluciones.

A continuacin utilice el men Proyecto Agregar nueva carpeta de solucin o el men contextual
disponiblehaciendoclicconelbotnsecundariodelratnenelnombredelasolucin.

Seacualseaelmtodoutilizado,debefacilitarunnombreparalacarpetacreada.

b.Crearunproyectoenunacarpeta

Lacreacindeunproyectoenunacarpetadesolucinesidnticaalacreacindeunproyectodirectamenteenla
solucin.

Previamente,bastaconqueseleccionelacarpetaenlaquedeseacrearelproyecto.

c.Desplazarunproyectoaunacarpeta

Amenudoesnecesarioorganizarunasolucinconcarpetacuandoyaexistenproyectosenlasolucin.

En este caso hay que crear las carpetas y despus arrastrarsoltar los proyectos a las carpetas
correspondientes.

5.LacarpetaElementosdesolucin

Lassolucionescontienenprincipalmenteproyectos,aunqueesposibletenerenunasolucinarchivosgestionados
de manera independiente de un proyecto particular, pero asociados a la solucin. Es el caso, por ejemplo, de un
archivoiconoquequierautilizarenvariosproyectosdelasolucin.Estosarchivossellamanelementosdesoluciny
seencuentranenunacarpetaespecficadeesta.

Para aadir un nuevo elemento de solucin, utilice el men contextual en el nombre de la solucin
seleccionandolaopcinAgregarNuevoelementoolaopcinAadirElementoexistente.

EntonceselnuevoelementoseaadeenlacarpetaElementosdesolucin.Tengaencuentaque,pordefecto,este
archivonoexisteenunasolucin,sinoquesecreaautomticamentedurantelainclusindelprimerelementode
solucin. Luego se pueden modificar los elementos de solucin con un editor especfico para el tipo de archivo
creado.

6.LacarpetaArchivosvarios

A veces puede querer visualizar el contenido de un archivo mientras est trabajando en una solucin, como por
ejemploelactadeunareunin.Estearchivonodebeperteneceralasolucindemanerapermanente.Puedeabrirlo
conuneditorexternoypasardeVisualStudioaesteeditorexterno,peroresultamsprcticovisualizarelarchivo
directamenteenelentornoVisualStudio.

UtilicelaopcinAbrirarchivodelmenArchivo.

El cuadro de dilogo le permite elegir el archivo que desea abrir. En funcin del tipo de archivo, se le asociar
automticamente un editor por defecto, para permitir su modificacin. A veces puede resultar til elegir el editor
asociadoaunarchivo.Paraello,elbotnAbrirdelcuadrodedilogodisponedeunmenqueproponelaopcin
Abrircon,quepermitelaeleccindeleditorasociadoalarchivo.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Elcuadrodedilogosiguienteleproponelalistadeeditoresdisponibles.

Seleccioneeleditorasociadoalarchivoconelquedeseatrabajaryvalide.

ElarchivoestahoradisponibleenlacarpetaArchivosvariosdelasolucin.Delamismamaneraquelacarpeta
Elementos de solucin, la carpeta Archivos varios no existe por defecto en la solucin, sino que se crea
automticamentealabrirunarchivo.

SoloservisibleenelexploradordesolucionessiseactivalaopcincorrespondienteenelentornoVisualStudio.
Para ello, abra el men Herramientas Opciones. Luego, en el cuadro de dilogo, elija la opcin Entorno
Documentos y active la opcin Mostrar archivos varios en el Explorador de soluciones. Como la carpeta

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Elementosdesolucin,estaesunacarpetalgicaynocorrespondeaningunaubicacineneldisco.

7.Configuracindeunasolucin

Las soluciones disponen de propiedades que permiten configurar sus comportamientos durante la generacin o
ejecucindelaaplicacin.Estasdiferentespropiedadesestnagrupadasenuncuadrodedilogoaccesibleconla
opcinPropiedadesdelmencontextualdeunasolucin.Haycincocategorasdepropiedadesdisponibles:

l Proyectodeinicio.

l Dependenciasdelproyecto.

l Parmetrosdeanlisisdelcdigo.

l Depurararchivosdecdigofuente.

l Propiedadesdeconfiguracin.

Miremosendetallecadaunadeellas.

a.Configuracindelproyectodeinicio

Estapginadepropiedadesdelasolucindetermina,entrelosproyectosdisponibles,culoculessonlanzados
alarrancarlasolucin.

Haytresopcionesdisponibles:

Seleccinactual

Estaopcinindicaqueelproyectoseleccionadoenelexploradordesolucionesseejecutarcuando
seinicielasolucin.

Proyectodeinicionico

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Uncomboproponelalistadelosproyectosdisponiblesenlasolucinyentrelosquesedebeelegir
elqueserejecutadoaliniciarlasolucin.Elnombredeesteproyectosesealaennegritaenel
exploradordesoluciones.Estaseleccintambinsepuedehacerconelmencontextualdel
exploradordesolucioneseligiendolaopcinEstablecercomoproyectodelanzamiento.

Proyectosdeiniciomltiples

Unatablapresentalalistadetodoslosproyectosdisponiblesenlasolucin.Paracadaunodeellos,
sedebeindicarlaaccinquesevaaejecutareneliniciodelaaplicacin.Lasopcionesposiblesson:

n Ninguna.

n Iniciar.

n Iniciarsindepurar.

Sieligeiniciarvariosproyectosalavezenelarranquedelasolucin,tambindebeindicarelordenenelquese
iniciarnestosproyectos.Esteordencorrespondeenrealidadalordendelosproyectosenlatabla.Losbotones

y permitenmodificarlo.

b.Dependenciasdelproyecto

Lageneracindealgunosproyectosrequierelageneracinpreviadeotrosproyectos.Eselcaso,porejemplo,si
sepidelageneracindeunproyectoqueutilizaunareferenciahaciaotro:entonces,esteesunadependenciadel
proyectoinicial.

Lasiguientepginadepropiedadespermiteconfigurarestasdependencias.

Enlalistadelosproyectos,seleccioneelproyectoparaelcualdeseaconfigurarlasdependencias.Los
otrosproyectosdelasolucinaparecenenunalistaconunacasilladeverificacinparacadauno.Ala
hora de generar el proyecto, todos los proyectos de los que depende sern automticamente
regeneradossihansidomodificadosdesdelaltimageneracinosinuncahansidogenerados.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Algunasdependenciasnosepuedenmodificarentonces,lacasilladeverificacinapareceengris.

Engeneral,eselcasocuandounproyectoposeeunareferenciaaotroproyectoocuando,
aadiendounadependencia,sepuedecrearunbucle.Porejemplo,elproyecto1dependedel
proyecto2,einversamente.

Tambin se pueden configurar las dependencias de proyecto mediante el men contextual del explorador de
soluciones,conlaopcinDependenciasdelproyecto.

c.Parmetrosdeanlisisdelcdigo

Esta pgina de propiedades permite configurar las reglas que se utilizan cuando se analiza el cdigo de los
diferenteselementosdelasolucin.

Paracadaproyectodelasolucin,puedeindicarlaconfiguracinqueutilizarnlasherramientas deanlisis.

LaopcinTodaslasreglasdeMicrosofteslamsestrictaydetectalamenoranomala,principalmente:

l Losparmetrosdefuncinqueestanousa.

l Lasvariableslocalesquenoseusan.

l Losnombresdeparmetrospocoexplcitos.

l Losidentificadoresquenorespetanlasconvencionesdenomenclaturarespectoalusodemaysculasyminsculas.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
d.Depurararchivosdecdigofuente

Duranteladepuracindeunaaplicacin,elentornoVisualStudionecesitaaccederalarchivofuentedelcdigoque
estdepurando.Estapginadepropiedadespermiteespecificarlosdirectoriosquesernanalizadosdurantela
bsquedadelcdigofuente.

La lista Directorios que contienen cdigo fuente muestra el nombre de los directorios que sern revisados en
bsqueda de cdigo fuente durante la depuracin de una aplicacin. Se puede gestionar esta lista gracias a la
barradeherramientas,cuyosbotonespermiten:

Comprobarlaexistenciadeldirectorio.

Aadirunnuevodirectorio.

Suprimireldirectorioseleccionadodelalista.

Desplazareldirectoriohaciaabajoenlalista.

Desplazareldirectoriohaciaarribaenlalista.

LalistaNobuscarlosarchivosdecdigofuentesiguientesexcluyealgunosarchivosdelabsqueda.

e.Configuracin

Las opciones de configuracin permiten definir cmo se generan varias versiones de una solucin y de los
proyectosquelacomponen.Pordefecto,haydosconfiguracionesdisponiblesparaunasolucinenVisualStudio:
laconfiguracinDebugylaconfiguracinRelease.

Paracadaunodelosproyectospresentesenlasolucin,lasdosconfiguracionestambinestarndisponibles.A
niveldelproyecto,lasconfiguracionespermitendefiniropcionesdecompilacin.SeutilizalaconfiguracinDebug
durante el desarrollo y las pruebas del proyecto. Se utiliza la configuracin Release para la generacin final del

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
proyecto.

Enrealidad,tenemosunsistemadetresniveles:paracadaconfiguracindesolucin,seindicaquconfiguracin
utilizarparacadaproyecto,yparacadaconfiguracindeproyecto,seespecificanlasopcionesdecompilacin.Se
puedenmodificarlasopcionesdecompilacinaniveldelaspropiedadesdelproyecto.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Losproyectos

Los proyectos son los contenedores de segundo nivel en una aplicacin. Se utilizan para organizar lgicamente,
gestionar, generar y depurar los componentes de una aplicacin. La generacin de un proyecto suele producir un
archivoejecutableounabibliotecadll.Unproyectopuedesermuysencilloynocontenermsdedoselementos,un
archivo fuente (.vb) y el archivo de proyecto (.vbproj). En general, los proyectos contienen numerosos archivos
fuente,scriptsdebasesdedatos,referenciashaciaserviciosWeb,recursosgrficos,etc.

VisualStudioproponepordefectounconjuntodeplantillasdeproyectos.Estasplantillasrepresentanunpuntode
partida para la mayora de las necesidades en el desarrollo de una aplicacin. Para casos ms especficos, puede
crearsuspropiasplantillasdeproyecto.

1.Creacindeunproyecto

Para crear un proyecto, active el men Archivo Nuevo proyecto. Un cuadro de dilogo le propone
entonceselegirlascaractersticasdelnuevoproyecto.

Elija primero la versin del Framework para la que desea desarrollar el proyecto. La versin elegida
influyeenlostiposdeproyectosqueustedpuedecrear.

Elijaluegoellenguajeconelquedeseadesarrollarelproyecto.Lasopcionesdisponiblesdependendelos
lenguajesinstaladosenVisualStudio.Porsupuesto,ennuestrocaso,elegiremosVisualBasic.

Luego elija el tipo de proyecto que desea desarrollar. El cuadro de dilogo propone entonces las
diferentesplantillasdeproyectosdisponiblessegneltipodeproyectoelegido.

Despus de haber elegido, indique un nombre para el proyecto, una ubicacin para sus archivos y un
nombre para la solucin. El asistente utiliza la plantilla seleccionada para crear los elementos del
proyecto.

Despusdeunosinstantes,elproyectoestdisponibleenelexploradordesoluciones.

Ahorapersonalicelaplantilla.

a.Lasplantillasdeproyectos

Hay muchas plantillas de proyectos disponibles en Visual Studio. Estas plantillas facilitan los elementos bsicos
necesarios para desarrollar cada tipo de proyecto. Siempre contienen al menos el archivo del proyecto, ms un
ejemplardelelementomsutilizadoparaeltipodeproyectocorrespondiente.Porejemplo,paraunproyectode
biblioteca de clases, se crea un archivo fuente que contiene un boceto de clases. Las plantillas proporcionan
tambin referencias e importaciones por defecto para las bibliotecas y los espacios de nombres ms tiles en
funcindeltipodeproyecto.

AplicacinWindowsForms

Esta plantilla de proyecto es seguramente la ms utilizada. Permite el desarrollo de una aplicacin Windows
estndar.Laplantillaaadeloselementossiguientesalproyecto:

l Un archivoAssemblyInfo.vbutilizadoparaladescripcindelaaplicacin,con,entreotros,losdatosrelativosala
versin.

l Unformulariodebaseconsuarchivofuenteform1.vb.

Lassiguientesreferenciasseaadeneimportanautomticamente:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Deployment

l System.Drawing

l System.Windows.Forms

l System.Xml

l System.Xml.Linq

Bibliotecadeclases

Esta plantilla de proyecto se puede utilizar para crear clases y componentes que luego podrn ser compartidos
conotrosproyectos.Lossiguienteselementosseaadenautomticamentealproyecto:

l Un archivo AssemblyInfo.vbutilizadoparaladescripcindelproyectocon,entreotra,lainformacinrelativaala
versin.

l Unaclasedebaseconsuarchivofuenteclass1.vb.

Lassiguientesreferenciasseaadeneimportanautomticamente:

l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Xml

l System.Xml.Linq

BibliotecadecontrolesWindows

Como la plantilla anterior, este tipo de proyecto permite crear una biblioteca de clases utilizable en otros
proyectos.Estabibliotecaesmsespecfica,yaqueestdedicadaalacreacindecontroles,utilizablesluegoen
una aplicacin Windows. Estos controles amplan el cuadro de herramientas disponible en las aplicaciones
Windows.Lossiguienteselementosseaadenautomticamentealproyecto:

l Unarchivo AssemblyInfo.vbutilizadoparaladescripcindelproyecto,con,entreotras,lainformacinrelativaala
versin.

l Una clase UserControl1 que hereda de la clase System.Windows.Forms.UserControl y que proporciona las
funcionalidadesdebaseparauncontrolWindows,consuarchivofuenteUserControl1.vb.

Lassiguientesreferenciasseaadeneimportanautomticamente:

l System

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Drawing

l System.Windows.Forms

l System.Xml

l System.Xml.Linq

Aplicacindeconsola

Estetipodeaplicacinestdestinadoaserejecutadoapartirdelalneadecomandodeunaventanadelneade
comandos. Por supuesto, est diseada sin interfaz grfica, las entradas/salidas se hacen desde la lnea de
comandoyhacialaconsola.

EstetipodeaplicacinesmuyprcticopararealizarpruebasconVisualBasic,yaquepermiteconcentrarseenun
puntoespecial,sintenerquepreocuparseporelaspectodelapresentacindelaaplicacin.

Muchosejemplosdeestelibrosebasanenunaaplicacindeconsola.Sinembargo,hayqueadmitirque,apesar
desusencillezdecreacin,estetipodeaplicacinhaquedadoobsoleto.

Lossiguienteselementosseaadenpordefectoalproyecto:

l UnarchivoAssemblyInfo.vbutilizadoparaladescripcin,entreotras,deinformacinrelativaalaversin.

l Unaclasedebaseconsuarchivofuenteclass1.vb.

Lassiguientesreferenciasseaadeneimportanautomticamente:

l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Deployment

l System.Xml

l System.Xml.Linq

ServiciodeWindows

Sediseaestetipodeproyectoparalacreacindeaplicacionesqueseejecutancomotareaensegundoplanoen
elsistema.Ellanzamientodeestetiposepuedeefectuarautomticamentealiniciarelsistemaynonecesitaque
unasesindeusuarioestabiertaparapoderejecutarse.

Estetipodeaplicacinestdesprovistodeinterfazdeusuario.Sisedebecomunicarinformacinalusuario,esta
debertransitarporlossucesosdelsistema,quepuedenserconsultadosporelvisordesucesos.Lossiguientes
elementosseaadenalproyecto:

l UnarchivoAssemblyInfo.vbutilizadoparaladescripcincon,entreotras,lainformacinrelativaalaversin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
l Unaclasedebaseconelesqueletodelosprocedimientos OnStarty OnStopllamadosautomticamentealiniciary
alpararelservicio.

Lassiguientesreferenciasseaadeneimportanautomticamente:

l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Deployment

l System.ServiceProcess

l System.Xml

l System.Xml.Linq

AplicacinWPF

EstaplantilladeproyectopermitebeneficiarsedelnuevosistemadevisualizacingrficadeWindows,utilizadoen
WindowsVistayenlasversionesposteriores.

Lossiguienteselementosseaadenautomticamentealproyecto:

l Un archivoAssemblyInfo.vbutilizadoparaladescripcindelaaplicacincon,entreotra,lainformacinrelativaa
laversin.

l Un archivo Application.Xaml y su archivo de cdigo asociado, Application.Xaml.vb, destinado a la gestin de


loseventosdesencadenadosalniveldelaaplicacin.

l UnaventanadebaseWindow1.Xamlysuarchivodecdigoasociado,Window1.Xaml.vb.

Lassiguientesreferenciasseaadeneimportanautomticamente:

l PresentationCore

l PresentationFramework

l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Xaml

l System.Xml

l System.Xml.Linq

l WindowsBase

BibliotecadecontrolesdeusuarioWPF

AligualquelalibreradecontrolesWindows,estetipodeproyectopermiteextenderelcuadrodeherramientasya
disponibleenlasaplicacionesWPF.Seaadenlossiguienteselementosalproyecto:

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
l Un archivoAssemblyInfo.vbutilizadoparaladescripcindelaaplicacincon,entreotra,lainformacinrelativaa
laversin.

l UnarchivoUserControl1.xamlparaladefinicindelaspectogrficodelcontrol.

l UnarchivoUserControl1.xaml.vbparaelcdigoasociadoaestecontrol.

Lasreferenciassiguientesseaadeneimportanautomticamente:

l PresentationCore

l PresentationFramework

l System

l System.Core

l System.Data

l System.Data.DataSetExtensions

l System.Xaml

l System.Xml

l System.Xml.Linq

l WindowsBase

BibliotecadecontrolespersonalizadosdeWPF

Este tipo de proyecto tambin tiene por objetivo extender el cuadro de herramientas disponible para las
aplicacionesWPF.Adiferenciadeltipodeproyectoanterior,loscontrolesnohansidocreadoscompletamente,ya
queestnbasadosencontrolesexistentescuyascaractersticasextienden.

Lasreferenciaseimportacionessonidnticasaltipodeproyectoanterior.

Proyectovaco

Debeutilizarestaplantillacuandodeseecrearsupropiotipodeproyecto.Soloelarchivoproyectoestcreado.A
cambio,noseaadeningnotroelementoautomticamenteynosecreaniimportaningunareferencia.

b.Creacindeunaplantilladeproyecto

Puede crear su propia plantilla de proyecto segn sus costumbres de desarrollo y hacerlo de tal manera que
aparezcaentrelasplantillaspredefinidas.

Deberdisearloselementossiguientes:

l Un archivo de definicin que contenga los metadatos de la plantilla. Visual Studio utiliza este archivo para la
visualizacindelproyectoenelentornodedesarrolloyparalaasignacindepropiedadespordefectoalproyecto.
EstosdatosestncontenidosenunarchivoXMLconlaextensin.vstemplate.

l Unarchivoparaelproyecto(.vbproj).

l Losarchivosfuenteyrecursosincluidospordefectodurantelacreacindeunproyectoapartirdeestaplantilla.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Estosarchivosdebensercomprimidosenunarchivozip.Elarchivozipdebecontenerlosarchivosindividualmente,
ynolacarpetaenlaqueestnubicados.

Elarchivo.vstemplatedebetenerelformatosiguiente:

<VSTemplate Version="3.0.0"
xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateData>
<Name>ApliPerso</Name>
<Description>creacin de un proyecto con una configuracin personalizada
</Description>
<ProjectType>VisualBasic</ProjectType>
<DefaultName>ApliPerso</DefaultName>
</TemplateData>
<TemplateContent>
<Project File="ApliPerso.vbproj">
<ProjectItem>AssemblyInfo.vb</ProjectItem>
<ProjectItem>Hoja1.vb</ProjectItem>
<ProjectItem>Hoja1.Designer.vb</ProjectItem>
<ProjectItem>Hoja1.resx</ProjectItem>
</Project>
</TemplateContent>
</VSTemplate>

Enestearchivoencontramos:

EnlaseccinName

Elnombrevisualizadoporelcuadrodedilogodecreacindeunnuevoproyecto.

EnlaseccinDescription

Unadescripcindetalladadelproyecto.

EnlaseccinProjectType

Elnombredelacarpetaenlaqueseclasificaresteproyectoenelcuadrodedilogodecreacinde
proyecto.

EnlaseccinDefaultName

Elnombreutilizadopordefectoparatodoslosproyectoscreadosdesdeestaplantilla.Secompleta
estenombreconunsufijonumricoenlacreacindelproyecto.

EnlaseccinProjectFile

Elnombredelarchivodeproyectoasociadoalaplantilla.Estearchivodebeestarpresenteenel
archivozipdelaplantilla.

EnlasseccionesProjectItem

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Loselementosqueformanpartedelproyecto.Estoselementostambindebenestardisponiblesen
elarchivozip.

c.Modificacindeunaplantillaexistente

Lamodificacindeunaplantillaconsisteenutilizarunarchivozipexistentequecontieneloselementosnecesarios
paraelproyectoyaadirelementosadicionales.Siseaadenarchivosalaplantilla,sedebenubicarenelarchivo
zipytambinreferenciarlosenelarchivo.vstemplate.LasplantillaspredefinidasdeVisualStudiosecolocanenel
directorioC:\ProgramFiles\MicrosoftVisualStudio10.0\Common7\IDE\ProjectTemplates\VisualBasic.Paraquese
tenganencuentalasmodificaciones,sedebeactualizarlacachutilizadaporVisualStudio.Paraello:

AbraunaventanadecomandoVisualStudio.

Introduzca el comando devenv /setup. Sea paciente, ya que este comando tarda bastante en
ejecutarse.Despusdelaejecucindelcomando,susmodificacionesestndisponiblesenlaplantillade
proyecto.

d.Utilizacindeunproyectoexistentecomoplantilla

Puedequesealasolucinmssencillaparaconstruirunaplantilladeproyecto.

Enunprimermomento,creelaplantillacomounproyectoordinario.

Unavezfinalizadosuproyecto,exprtelocomoplantilla.ElmenArchivoExportarplantillalanzaun
asistenteparaguiarledurantelacreacindelaplantilla.

Esteprimercuadrodedilogoleproponeelegirelproyectoquequiereexportar,juntoconlaseccindelcuadrode
dilogodecreacindeproyectoenlaquesecolocarlafuturaplantilla.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Estesegundocuadrodedilogoleinvitaaelegiruniconoparasuplantilladeproyecto,unnombreparalaplantilla
y una descripcin. Dos opciones adicionales le permiten tener en cuenta inmediatamente la nueva plantilla en
VisualStudioypresentarelresultadodelageneracinalmostrarleelcontenidodelarchivozipcreado.Despus
devalidaresteltimocuadrodedilogo,lanuevaplantilladeproyectoestdisponibleenVisualStudio.

Este mtodo es muy sencillo para construir una nueva plantilla de proyecto y evita darle vueltas a la sintaxis del
archivo.vstemplate.

Enelmarcodeundesarrolloenequipo,puederesultarinteresantecompartirlasplantillaspersonalizadasentre
todoslosmiembrosdelequipo.

Copieotravezlosarchivoszipenunaredcompartida.

ConfigureelentornoVisualStudioparapermitirleaccederalasplantillas.Estamodificacinseefecta
graciasalcuadrodedilogodisponibledesdelaopcindelmenHerramientasOpciones.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
2.Modificacindeunproyecto

Las plantillas de proyectos son muy tiles para crear rpidamente las bases de una aplicacin, pero a menudo
necesitarnlainclusindenuevoselementosalproyecto.Estasinclusionessehacenpormediodelmencontextual
delexploradordeproyectos.

ActivelaopcinAgregarNuevoelementoparaelegireltipodeelementoquedeseaaadiralproyecto.
El cuadro de dilogo propone un nmero impresionante de elementos que se pueden aadir a un
proyecto.

Indiqueunnombreparaelarchivoquecontieneelnuevoelemento.

Enfuncindelostiposdeproyecto,hayopcionesadicionalesdisponiblesenelmencontextualquepermitenaadir
conrapidezunnuevoelemento.Sevisualizansimplementeenelcuadrodedilogoanteriorconeltipodeelemento
correspondienteyapreseleccionado.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Tambinesposibleretomarunelementoexistenteenotroproyectoyaadirloaunproyecto.Utiliceenestecasola
opcin Agregar Elemento existente del men contextual del explorador de proyectos. Un cuadro de dilogo le
proponelaseleccindelarchivoquedeseaincluirenelproyecto.

El botnAgregar de este cuadro de dilogo dispone de un men que permite aadir el archivo normalmente (se
lleva a cabo en ese momento una copia local del archivo) o crear un vnculo en el archivo (se utiliza el archivo
original).Hayqueserprudenteconestaposibilidad,yaqueelarchivonopertenecerealmentealaaplicacin,y
se puede compartir entre varias aplicaciones. Si se suprime el archivo del disco, no se podr compilar las
aplicacionesqueloutilizan.

Lagestindelosarchivosenelexploradordesolucionesesidnticaalagestindelosarchivosenelexploradorde
Windows. Los archivos se pueden copiar y pegar o desplazar arrastrndolos de una carpeta a otra. El uso de las
teclas[Ctrl],[Mays]y[Ctrl][Mays]duranteelarrastremodificalaaccinrealizada.Sisehaceclicyarrastrardentro
deunmismoproyecto,serealizaundesplazamientodearchivo.Siserealizaentredosproyectos,entoncesseefecta
una copia del archivo. Este comportamiento se puede modificar utilizando la tecla [Mays] mientras se arrastra. Para
efectuar una copia de archivo dentro de un proyecto, se usa la tecla [Ctrl] mientras se arrastra. Se puede crear un
enlaceutilizandolacombinacindeteclas[Ctrl][Mays]mientrassearrastra.

Paraquitarunelementodeunproyecto,haydosopcionesaccesiblesatravsdelmencontextualdelexplorador
desoluciones:

l LaopcinSuprimirsuprimeelarchivodelproyectoytambindeldisco.

l La opcin Excluir del proyecto quita el archivo del proyecto, pero no lo suprime del disco. Esta opcin es til si
otrosproyectosutilizanestearchivomedianteunvnculo.

3.Propiedadesdelosproyectos

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Los proyectos son elementos fundamentales en la creacin de una aplicacin con Visual Basic. Poseen muchas
propiedades que permiten modificar sus comportamientos en el momento del diseo o de la ejecucin de la
aplicacin.Elconjuntodelaspropiedadesestaccesibleatravsdeuncuadrodedilogoquepresenta,mediante
pestaas,lasdiferentesseccionesdeconfiguracindeunproyecto.

Active este cuadro de dilogo con la opcin Propiedades del men contextual del explorador de

solucionesoconelbotn delabarradeherramientasdelexploradordeproyecto.

a.Propiedadesdeaplicacin

Laspropiedadespresentesenestapestaavanapermitirconfigurarelcomportamientodelaaplicacin.

Nombredelensamblado

Esta propiedad determina el nombre utilizado para el archivo resultante de la compilacin de la aplicacin. Por
defecto, este archivo lleva el mismo nombre que el proyecto, pero se pueden modificar los dos de manera
independienteelunodelotro.Laextensinasociadaalarchivodependedeltipodelproyecto.

Versinde.NETFrameworkdedestino

EstapropiedadindicalaversindelFrameworknecesariaparaejecutarlaaplicacin.Demanerapredeterminada,
estevaloresigualalseleccionadodurantelacreacindelproyecto.

Tipodeaplicacin

Estapropiedaddeterminaeltipodeaplicacingeneradaporlacompilacindelproyecto.Laplantillaelegidaenel
momento de la creacin del proyecto suele determinar esta propiedad, que se modifica pocas veces, ya que
depende mucho del cdigo de su proyecto (si dise su aplicacin como una aplicacin Windows y desea

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
considerarlacomounaaplicacinparaconsola,searriesgaatenermuchocdigointil!).

Formulariodeinicio

Estapropiedaddeterminaelpuntodeentradaenlaaplicacindurantesuejecucin.Normalmente,correspondea
laventanaprincipaldelaaplicacinoaunprocedimientoSub Main.Estapropiedadsoloestdisponibleparalos
proyectosquesepuedenejecutardemaneraautnoma.Esintilparalosproyectosdetipobiblioteca.

Espaciodenombresdelaraz

Todosloselementosdelproyecto,accesiblesdesdeotroproyecto,pertenecenalespaciodenombresdefinidopor
estapropiedad.Estavieneaaadirsealosposiblesespaciosdenombresdefinidosaniveldelpropiocdigo.Por
defecto,estapropiedadcorrespondealnombredelproyecto,perosepuedemodificardemaneraindependientea
este.Inclusopuedeestarvaca,loquelepermitegenerarespaciosdenombresdirectamenteenelcdigo.

Icono

Estapropiedadconfiguraeliconoasociadoalarchivocompiladodelproyectocuandosevisualizaenelexplorador
deWindowsocuandolaaplicacinapareceenlabarradetareasdeWindows.

Informacindeensamblado

Estaopcinpermitefacilitardatossobreelcdigogeneradoporlacompilacindelproyecto.Uncuadrodedilogo
permiterellenardiferentesseccionesrelativasaladescripcindelproyecto.

El usuario de su cdigo podr consultar estos datos visualizando las propiedades del archivo compilado en el
exploradordeWindows.

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
VerconfiguracindeWindows

Estaopcinlepermitedeterminarelniveldeejecucinrequeridoporlaaplicacin.Dichainformacinesutilizada
por el mecanismo User Account Control (UAC) de Windows. Indica bajo qu identidad correr el cdigo de la
aplicacin.Haytresvaloresposibles:

l asInvoker:laaplicacinseejecutaconlaidentidadactualdelusuarioynorequiereaumentodeprivilegios.

l highestAvailable:laaplicacinseejecutaconelmayorniveldeprivilegiosdelusuario.

l requireAdministrator: la aplicacin se debe ejecutar con el privilegio administrador, y UAC puede pedirle su
consentimientoparaaumentarsusprivilegios.

Habilitarmarcodetrabajodelaaplicacin

Estaopcindeterminasiquiereactivarunainteraccinmsdesarrolladaentrelaaplicacinyelsistemaoperativo.
Siestaopcinestactiva,elelementodeiniciodelaaplicacindebeserunahoja.Elusodeestaopcinhaceque
lassiguientespropiedadespasenaestardisponibles.

HabilitarestilosvisualesdeXP

SiestaopcinseactivaylaaplicacinseejecutaenunsistemaoperativoWindowsXP,lainterfazdeusuariodela
aplicacinseadaptaralformatoWindowsactivo.

Convertiraplicacindeinstancianica

Por defecto, puede lanzar todas las instancias de una misma aplicacin que quiera en una nica mquina. Sin
embargo, a veces puede ser til autorizar el funcionamiento de una sola instancia de la aplicacin en un
determinado momento (problema de licencia de usuario, conservacin de los recursos de la mquina...). La
activacindeestaopcingarantizaquenohayamsdeunainstanciadelaaplicacinenejecucinenlamquina.
Si se lanza una nueva instancia cuando ya hay otra en el sistema operativo, el foco se pasa directamente a la
instanciaexistente.Aniveldelaaplicacin,eleventoStartupNextInstancetambinsedesencadenar.

GuardarMy.Settingsalcerrar

Esta opcin indica si las propiedades personalizadas de la aplicacin se guardan cuando se cierra la aplicacin.
Estopermite,porejemplo,grabarlaspreferenciasdelusuario.

Mododeautenticacin

Por defecto, las aplicaciones Visual Basic utilizan la autenticacin de Windows para identificar el usuario de la
aplicacin.Siquieregestionarustedmismoestaidentificacin,debeutilizarlaopcinDefinidoparalaaplicacin.

Mododeapagado

Esta opcin determina el comportamiento de la aplicacin cuando se cierra. Por defecto, la ejecucin de la
aplicacin se para cuando se cierra la ventana de inicio de la aplicacin, aunque haya otras ventanas activas
(siempre que no sea una ventana modal). La opcin Al cerrar el ltimo formulario produce el cierre de la
aplicacin en el momento del cierre de la ltima ventana activa de la aplicacin o cuando se llaman las
instruccionesMy.application.exitoendexplcitamenteenelcdigo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Pantalladepresentacin

Las pantallas de inicio se utilizan a menudo para proporcionar informacin al usuario durante el inicio de la
aplicacin.VisualStudioproponeunaplantilladepantalladeiniciopersonalizable.Estapantallaaparecemientras
secargalaventanaprincipaldelaaplicacin.

Vereventosdeaplicaciones

Esta opcin permite acceder a los gestores de eventos del objeto de la aplicacin. Los gestores de eventos
permitenreaccionarfrenteadiferentessituaciones:

Startup

Laaplicacinarranca.

StartUpNextInstance

Seacabadelanzarunanuevainstanciadelaaplicacin.

Shutdown

Laaplicacinsecierra.

UnHandledException

Seacabadeproducirunaexcepcinnocontrolada.

NetworkAvailabilityChanged

Seacabademodificarelaccesoalared(elcablehasidoenchufadoodesenchufado).

b.Referenciaseimportacionesdeunproyecto

Para poder utilizar elementos externos disponibles en un ensamblado, tiene que aadir una referencia a este
ensamblado.

Lasiguientepginadepropiedadesrecogetodalainformacinrelativaalasreferenciasdeunproyecto.

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Enestapginadepropiedades,lalistaReferenciaspresentatodoslosensambladosactualmentereferenciados
enelproyecto.

EstalistasepuedeactualizarconlosbotonesAgregar,QuitaryActualizar,quepermitenrespectivamenteaadir
unareferencialocalounareferenciaWeb,eliminarunareferenciaoactualizarunareferenciaWeb.

El botn Rutas de acceso de referencia permite indicar los directorios adicionales que contienen ensamblados
disponibles. Estos directorios se analizan al abrir el cuadro de dilogo para aadir referencias, y los eventuales
ensambladosquecontienenseaadenalalistadeensambladosdisponibles.Cuandoseaadeunareferenciaa
un ensamblado, en la primera ejecucin de la aplicacin se utiliza el archivo original. Puede utilizar la creacin
automticadeunacopialocaldeestearchivoeneldirectoriodelaaplicacin.Paraello:

SeleccionelareferenciaencuestinymodifiquelapropiedadCopy Localenlaventanadepropiedades
deVisualStudio.

ElbotnReferenciassinutilizarmuestralalistadetodaslasreferenciasnoutilizadasenelcdigoylepropone
eliminarlasdelproyecto.

Los elementos disponibles en los ensamblados referenciados son, sin duda, parte de un namespace. Para
poderlosutilizarfcilmente,esposibleimportarautomticamentealgunosespaciosdenombres.LalistaEspacios
de nombres importados recoge los espacios de nombre importados automticamente en todos los cdigos del
proyecto.Puedecompletarestalistaeligiendoenelcuadrodetextoelnombredelespaciodenombresimportado
yvalidandoconelbotnAgregarimportacindelusuario.

c.Propiedadesdedepuracin

Laspropiedadespresentesenestapginadeterminanelcomportamientodelproyectodurantesudepuracin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Accindeinicio

Esta propiedad determina el comportamiento del proyecto durante el inicio de la depuracin. Hay tres opciones
posibles:

l Proyectodeinicioindicaqueelpropioproyectodebeserejecutado.Solosepuedeutilizarparalosproyectosde
aplicacinWindowsoparalosproyectosdeaplicacindeconsola.

l Programa externo de inicio permite provocar la ejecucin de una aplicacin externa que se va a encargar de
realizarllamadasalcdigodenuestroproyecto.Seutilizaestaopcinparaladepuracindelaslibrerasdeclases.

l Iniciar explorador con la direccin URL es idntica a la opcin anterior, excepto que la aplicacin iniciada es
unaaplicacinWeb.

Opcionesdeinicio

Argumentos de la lnea de comandos precisa los argumentos pasados a la aplicacin durante su ejecucin por
Visual Studio. El cdigo puede utilizar estos argumentos para determinar la accin que hay que acometer: por
ejemplo,lanzarlaaplicacinenmododemantenimiento.

Directoriodetrabajopermiteespecificareldirectorioactivodurantelaejecucindelaaplicacin.

Usarmquinaremotaautorizaladepuracindeunaaplicacinqueseejecutaenotramquina.Enestecaso,se
debeindicarelnombredelamquinaremotaenlacualsevaaejecutarelcdigo.

Habilitardepuradores

Estas opciones determinan los diferentes tipos de depuradores activos, como complemento del depurador de
cdigogestionadodeVisualStudio.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
d.Propiedadesdecompilacin

Laspropiedadesdeestapginaserefierenalfuncionamientodelcompiladoryasueventualoptimizacin.

Rutadeaccesodelosresultadosdelacompilacin

Esta propiedad indica el directorio en el que se copia el archivo resultante de la compilacin del proyecto. Por
defecto,setratadelsubdirectoriobindeldirectorioenelqueseencuentraelproyecto.

OptionExplicit

Esta opcin permite exigir o no que se declare cualquier variable antes de su utilizacin. Se aplica a todos los
archivos fuente de un proyecto. Es posible, sin embargo, modificar esta opcin para un archivo en concreto,
aadiendoladirectivaOption Explicit OnuOption Explicit Offalprincipiodeunarchivo.

OptionStrict

Esta opcin permite controlar las conversiones realizadas. Si se intenta realizar una conversin restrictiva, el
compiladorgeneraunerror.Comolaanterioropcin,estaseaplicaatodoslosarchivosfuentedeunproyectoy
sepuedemodificarparaunarchivoenconcretoconelcomandoOption Strict OnuOption Strict Off.

OptionCompare

Estaopcindeterminacmoserealizalacomparacindecadenasdecaracteresenunaaplicacin.Conelvalor
Binary,laaplicacinhaceunadistincinentreloscaracteresenminsculayenmaysculaenunacomparacin.El
valorTextpermiteevitarestadistincin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
Optioninfer

Estaopcinindicasilainferenciadetiposdevariableslocalesestactiva.Concadaopcin,elmismocompilador
determinaeltipodevariabledeacuerdoconeltipoqueseleasigna.

CPUdedestino

Estaopcinespecificaelprocesadorparaelquesedebegenerarelcdigo.Haytresopcionesdisponibles:

l X86:paralosprocesadoresde32bitscompatiblesIntel.

l X64:paralosprocesadoresde64bitscompatiblesIntel.

l AnyCPU:paratodoslosprocesadores.

Preferenciade32bits

Estaopcinindicaquelaaplicacinsiempreseejecutarcomounaaplicacinde32 bits,inclusoenunsistemade
64bits.SoloestdisponiblesilaunidadcentraldedestinoestdefinidacomoAnyCPU.

Configuracindeadvertencias

Elcompiladorescapazdedetectarlospotencialesproblemasdesucdigoydegeneraradvertenciasasociadas.
Puedeconfigurarlaaccindelcompiladorparadiferentescategorasdeproblemas.Lastresaccionesposiblesson:

l Ningunaaccin:elcompiladorignoraelproblema.

l Advertencia:elcompiladorgeneraunaadvertenciaenlalistadetareas.

l Error:elcompiladorgeneraunerrordecompilacin.

PuedetambindeshabilitartodaslasadvertenciasutilizandolaopcinDeshabilitartodaslasadvertenciaso,al
revs,tratarlastodascomoerroresconlaopcinConsiderartodaslasadvertenciascomoerrores.

GenerararchivodedocumentacinXML

Conestaopcinelcompiladorbuscaenelcdigoloscomentariosespecialescolocadosgraciasaloscaracteresy
losutilizaparagenerarelarchivodedocumentacin.Estearchivosecreadentrodeldirectorioenelquesegenera
elarchivocompilado.

Eventosdecompilacin

Estecuadrodedilogopermiteconfiguraruncomandoquesepuedelanzarautomticamenteantesodespusde
lageneracindelproyecto.

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Cadaunodeloscomandossepuedeintroducirenlazonadetextocorrespondiente.LosbotonesEdicinanterior
alacompilacinyEdicinposterioralacompilacinabrenunaventanadeedicinquefacilitalaintroduccindel
comando.

Tambinestecuadrodedilogoproponeunalistademacrosquepermitelarecuperacinyelusoporsucomando
de ciertos parmetros del proyecto. El ejemplo presentado en la figura anterior efecta una copia completa del
directoriodelaaplicacineneldirectorioC:\copiadeseguridad,antesdecadageneracin.

La ejecucin del comando despus de la generacin puede ser condicional y ocurrir solo en caso de generacin
exitosaosilageneracinactualizlasalidadelproyecto.

Siuncomandodebeejecutarunarchivo.batdespusdelageneracin,lallamadadeestedebevenirprecedidade
lapalabraclavecall.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 19 -
Opcionesdecompilacinavanzadas

Estaopcinabreuncuadrodedilogoquepermitelaconfiguracinavanzadadelcompilador.

Estecuadrodedilogopermitelaconfiguracindelassiguientesopciones:

l Quitarcomprobacionesdedesbordamientoconenteros.

l Autorizarlasoptimizacionesdelcdigodurantelacompilacin.

l Especificarladireccinenlaquesecargarlabibliotecadll.

l Indicarsiseaadeinformacindedepuracinalresultadodelacompilacin.

l Definirlasconstantesdecompilacin.

l PedirlageneracindedatosparapermitirlaserializacinXML.

e.Recursosdeunproyecto

Se utilizan los recursos para externalizar ciertos elementos de una aplicacin. Permiten realizar rpidamente
modificacionessencillasenunaaplicacinsintenerquebuscarentremilesdelneasdecdigo.Lautilizacinms
clsica consiste en separar del cdigo las constantes cadena de caracteres. Tambin puede crear recursos de
iconos,imgenes,archivosdetextooaudio.Estecuadrodedilogogestionatodoslosrecursos.

Para cada recurso, indique un nombre y un valor. Por supuesto, el nombre ser utilizado en el cdigo
parapoderrecuperarelvalor.

Enfuncindeltipoderecurso,tieneasudisposicinuneditoradaptadoparamodificarlo.Losrecursospuedenser
relacionadosovinculados,enfuncindesutipo.Unrecursorelacionadoestalmacenadoensupropioarchivoyel

- 20 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
archivo Resources.resx contiene simplemente un vnculo hacia el archivo original. Un recurso vinculado est
almacenado directamente en el archivo Resources.resx de la aplicacin. En todos los casos, se compilarn los
recursosenelejecutabledelaaplicacin.

Veamosahoracmoaccederalosrecursosapartirdelcdigodelaaplicacin.Todoslosrecursossonaccesiblesa
travsdelapropiedadResourcesdelobjetoMy.Elejemplosiguienteutiliza:

l Unrecursocadenadecaracteres(MensajeBienvenidaEs).

l Unrecursoicon(IconApli).

l Unrecursoimagenbitmap(ImagenFondo).

l Unarchivodesonido(Musica).

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)


Handles Me.Load
Me.Icon = My.Resources.IconAppli
Me.BackgroundImage = My.Resources.ImagenFondo
My.Computer.Audio.Play(My.Resources.Musica, AudioPlayMode.BackgroundLoop)
MsgBox(My.Resources.MensajeBienvenidaEs)
End Sub

f.Parmetrosdeaplicacin

Se suelen utilizar los parmetros de aplicacin para almacenar y cargar dinmicamente los parmetros de
configuracindeunaaplicacin,comoporejemplolaspreferenciasdelusuarioolosltimosarchivosutilizadosen
laaplicacin.

Primerosedebencrearlosparmetrosenlasiguientepginadepropiedades:

Paracadaparmetro,debeproporcionarunnombreutilizadoparamanipularelparmetroenelcdigoyuntipo
paraelparmetro.

Tambindebefacilitarunmbitoparaelparmetro.Haydosopcionesposibles:

Usuario

Sepuedemodificarelparmetroduranteelfuncionamientodelaaplicacin.

Aplicacin

Elparmetroesdesololecturadurantelaejecucinysolosepuedemodificarmedianteestecuadro
dedilogo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 21 -
Laltimacosaporhacerconsisteenespecificarunvalorparaelparmetro.

Vamosaestudiarahoracmomanipularlosparmetrosenelcdigo.Debemosrealizartresoperaciones.

l Aliniciarlaaplicacin,debemoscargarlosparmetros.Elaccesoalosparmetrossehaceatravsdelapropiedad
SettingsdelobjetoMy.

My.Settings.Reload()

l Durante la ejecucin de la aplicacin, tenemos acceso a los parmetros tambin a travs de esta propiedad
SettingsdelobjetoMy,alaquevamosaaadirelnombredelparmetro.Estonospermitelalecturadelvalordel
parmetroolaasignacindeunvaloralparmetro.

Me.BackColor = My.Settings.ColorFondo
My.Settings.UltimaUtilizacion = Now

l Alcerrarlaaplicacin,debemosguardarlosparmetrosutilizandoelmtodoSave:

My.Settings.Save()

Paracadausuariodelaaplicacin,seguardaunaversindistintadelosparmetros.

g.Otrosparmetrosdeconfiguracin

Lasotrasseccionesdeconfiguracindelproyectorelativasaldesplieguedelaaplicacinsetratanenuncaptulo
especfico.

- 22 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lasvariables,constantesyenumeraciones

1.Lasvariables

Las variables le permitirn almacenar, durante la ejecucin de su aplicacin, diferentes valores tiles para el
funcionamiento de su aplicacin. Se debe declarar una variable obligatoriamente antes de su uso en el cdigo.
Duranteladeclaracindeunavariable, sefijansuscaractersticas.

a.Nombredelasvariables

Veamoslasreglasquesedebenrespetarparanombrarlasvariables:

l Elnombredeunavariableempiezaobligatoriamenteconunaletra.

l Puedeestarformadoporletras,cifrasoelcarctersubrayado(_).

l Puedecontenerunmximode1023caracteres(enlaprctica,espreferiblelimitarseauntamaorazonable).

l No se distingue entre maysculas y minsculas (la variable EdadDelCapitan es equivalente a la edaddelcapitan),


aunqueotroslenguajesshacenestadistincin,ydebertenercuidadotambinsigeneraunensambladoutilizado
porotrolenguaje.

l Laspalabrasclavesdellenguajenodebenutilizarse(esposiblehacerlo,poniendoelnombredelavariableentrelos
caracteres[y].Porejemplo,unavariablellamadanextdeberutilizarseenelcdigodelasiguientemanera[next]
=56).

b.Tipodelasvariables

Alespecificaruntipoparaunavariable,indicamosqudatosvamosapoderalmacenarenestavariable.

Haydoscategorasdetiposdevariablesdisponibles:

l Lostiposporvalor:lavariablecontienerealmentelainformacin.

l Lostiposporreferencia:lavariablecontieneladireccindememoriadondesealmacenalainformacin.

Los diferentes tipos de variables disponibles estn definidos a nivel del propio Framework. Puede utilizar
igualmentelosaliasdefinidosaniveldeVB,posiblementemsexplcitos.EltipoSystem.Int32definidoaniveldel
FrameworkpuedesersustituidoporeltipointegerenVisualBasic.

Sepuedenclasificarlosdiferentestiposenseiscategoras.

Lostiposnumricosenteros

Tiposenterosconsigno

Sbyte 128 127 8bits

Short 32.768 32.767 16bits

Integer 2.147.483.648 2.147.483.647 32bits

Long 9.223.372.036.854.775.808 9.223.372.036.854.775.807 64bits

Tiposenterossinsigno

Byte 0 255 8bits

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
UShort 0 65.535 16bits

UInteger 0 4.294.967.295 32bits

ULong 0 18.446.744.073.709.551.615 64bits

Enelmomentodeelegiruntipoparasusvariablesenteras,debetenerencuentalosvaloresmnimoymximo
quepiensaalmacenarenlavariableconelfindeoptimizarlamemoriautilizadaporlavariable.Esintilutilizarun
tipoLongparaunavariablecuyovalornosersuperiora50untipoByteesenestecasosuficiente.

El ahorro de memoria parece irrisorio para una variable nica, pero se vuelve interesante en el caso de usar
matricesdegrandimensin.

Siloquesedeseaesoptimizarlavelocidaddeejecucindesucdigo,espreferibleutilizareltipoInteger.

Lostiposdecimales

Single 3.40282347E+38 3.40282347E+38 4bytes

Double 1.7976931348623157E+308 1.7976931348623157E+308 8bytes

Decimal 79.228.162.514.264.337.593. 79.228.162.514.264.337.593. 16bytes


543.950.335 543.950.335

Se deben tener en cuenta las mismas consideraciones de optimizacin que para las variables enteras. En este
caso,lavelocidaddeejecucinmximaseobtieneconeltipoDouble.EltipoDecimalesmsrecomendablepara
clculosfinancieros,enloscualesseprohbenloserroresderedondeo,endetrimentodelavelocidaddeejecucin
delcdigo.

Lostiposdecarcter

EltipoChar(carcter)seutilizaparaalmacenarunnicocarcter.UnavariabledetipoCharutilizadosbytespara
almacenar el cdigo Unicode del carcter. En el juego de caracteres Unicode, los primeros 128 caracteres son
idnticos al juego de caracteres ASCII, los caracteres siguientes hasta 255 corresponden a los caracteres
especialesdelalfabetolatino(porejemplo,loscaracteresacentuados)elrestoseutilizaparasmbolosoparalos
caracteresdeotrosalfabetos.

Parapoderalmacenarcadenasdecaracteres,convieneutilizareltipoString,querepresentaunaseriedeceroa
2.147.483.648caracteres.Lascadenasdecaracteressoninvariablesyaque,durantelaasignacindeunvalora
unacadenadecaracteres,sereservaalgodeespacioenmemoriaparaelalmacenamiento.Siestavariablerecibe
luegounnuevovalor,elsistemaleasignaunanuevaubicacinenmemoria.Afortunadamente,estemecanismoes
transparente para nosotros y la variable siempre har referencia de forma automtica al valor que le est
asignado.Conestemecanismo,lascadenasdecaracterespuedenteneruntamaovariable.Elespacioocupado
enmemoriaseajustaautomticamentealalongituddelacadenadecaracteres.

Para asignar una cadena de caracteres a una variable, el contenido de la cadena se debe introducir entre " ",
comoenelejemplosiguiente:

Ejemplo

NombreDelCapitan = "Garfio"

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Haymuchasfuncionesquepermitenmanipularlascadenasdecaracteresyserndetalladasmsadelanteeneste
captulo.ExisteuntipoStringenformadeclasequetambinpermitelamanipulacindecadenasdecaracteres.En
este caso, la manipulacin se har mediante los mtodos disponibles en la clase String. Estos tambin se detallarn
msadelanteenestecaptulo.

EltipoBooleano

EltipoBooleanopermiteutilizarunavariablequepuedetenerdosestados:verdadero/falso,s/no,on/off.

SuasignacinserealizadirectamenteconlosvaloresTrueoFalse,comoenelejemplosiguiente:

Disponible=True
Modificable=False

TambinesposibleasignarunvalornumricoaunavariabledetipoBooleano.Enestecaso,unvalorigualacero
se considera como un booleano False y cualquier otro valor positivo o negativo ser considerado como un
booleanoTrue.

EltipoDate

EltipoDatepermitealmacenar,enunavariable,datosdefechayhora.

Suasignacinserealizaponiendolosvaloresentrelossignos#,comoenelejemplosiguiente:

Hoy=#02/28/2011 14:58:23#

El formato utilizado para asignar un valor a una variable de tipo Date ser siempre #mes/da/ao
horas:minutos:segundos# independientemente del formato de fecha configurado en su sistema operativo. Las
horassepuedenespecificarenformatode12horaso24 horas.Detodasformas,elentornodedesarrollovalida
larecogidadedatosytransformarsiemprelafechaalformato12 horas.Elejemploprecedentesermodificado
porelentornodedesarrollodelasiguientemanera:

Hoy=#02/28/2005 2:58:23 PM#

Si asigna a una variable de tipo Date un valor con solo la hora, Visual Basic considerar que se trata del 1 de
enerodelao1alahoraquehabrindicado.

Ejemplo

Da=#12:35:30#

Correspondeal1deenerodelao1alas12horas35minutos30segundos.

Inversamente,siasignaaunavariabledetipoDateunvalorconsololafecha,VisualBasicconsiderarquese
tratadeldaquehaindicado,amedianoche!

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
EltipoObject

EstepuedesereltipomsuniversaldeVisualBasic.EnunavariabledetipoObject,sepuedealmacenarcualquier
cosa. En realidad, este tipo de variable no almacena nada. La variable no contendr el propio valor, sino la
direccin,enlamemoriadelamquina,dondesepodrencontrarelvalordelavariable.Tranquilcese,todoeste
mecanismoestransparente,ynuncatendrquemanipularlasdireccionesdememoriadirectamente.

Una variable de tipo Object podr hacer referencia, por tanto, a cualquier otro de tipo de valor, incluidos tipos
numricossimples.Sinembargo,elcdigosermenosrpidoenrazndelusodeunareferencia.

LostiposNullables

Avecesocurrequeenalgunascircunstanciasunavariablenotieneunvalorbiendefinido.Es,porejemplo,elcaso
durante la recuperacin de informacin procedente de una base de datos si, para algunos campos, no se ha
asignadoningnvalorenlabase.CmorepresentarestasituacinutilizandolasvariablesdeVisualBasic?Una
solucin consiste en utilizar un valor que no tiene ningn significado para la aplicacin. Por ejemplo, para una
variablenumricaquerepresentauncdigopostalenlaaplicacin,sepuedeconsiderarasignaraestavariableun
valornegativoencasodequeelcdigonoestindicado.Elrestodelcdigodebe,porsupuesto,tenerencuenta
esta convencin. Para cierto tipo de datos, esta solucin no se puede considerar. Pongamos el caso de una
variabledeltipoBooleanoenlacualsolohay2valorespermitidos, trueo false.Cmorepresentarqueel
valordelavariablenohasidoasignado?

Paraencararesteproblema,VisualBasicproponelostiposNullables,quepermitenquelasvariablesdetipovalor
no contengan ninguna informacin. Para activar esta funcionalidad en una variable solo hace falta utilizar el
carcter ?acontinuacindelnombredelavariableoalfinaldeladeclaracindeltipo,comomuestraelejemplo
siguiente.

Dim CodigoPostal ? as integer

Dim CodigoPostal as integer?

Encambio,hayqueserprudentedurantelautilizacindeunavariabledeestetipoyverificarantesdeusarlasi
contienerealmenteunvalor.Paraello,puedeconsultarlapropiedadHasValuedelamismavariableconobjetode
determinarlo.Sieselcaso,estevalorestdisponiblegraciasalapropiedadValuedelavariable.Estapropiedad
esdesololectura,yaquelaasignacindeunvalorsehacedirectamenteenlavariable.

CodigoPostal = 17000
If CodigoPostal.HasValue Then
Console.WriteLine(CodigoPostal)
Else
Console.WriteLine(Cdigo postal vaco)
End If

EsindispensableprobarlapropiedadHasValueantesdeusarlapropiedadvalue,yaque,silavariablenocontiene
ningnvalor,seactivaunaexcepcin.Eselcasodelejemplosiguiente,yaqueunavariablenullable,alcontrario
queunavariablenormal,nocontieneningnvalorpordefecto.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Unavariablequecontieneunvalorpuedepasaralestadonoasignadasiseleasignaelvalornothing.

Elusodevariablesdeltipobooleanonullableconlosoperadoreslgicosandyorescomplicado.Acontinuacin,
semuestralatabladeverdaddeestosdosoperadoresconvariablesnullables.

B1 B2 B1andB2 B1orB2

nothing nothing nothing nothing

nothing true nothing true

nothing false false nothing

true nothing nothing true

true true true true

true false false true

false nothing false nothing

false true false true

false false false false

Porltimo,cabeaclararelusodeunbooleanonullableenunaestructuracondicional.Observeelcdigosiguiente:

Dim condicion As Booleano?


...
If condicion Then
Console.WriteLine("resultado positivo")
Else
Console.WriteLine("resultado negativo")
End If

Lainstruccinifconsideraqueelresultadoespositivonicamentesilavariablecontieneelvalortrue.Paralos
otrosdoscasos,valorfalseovalornoasignado,elresultadoesnegativoyelcdigodelbloqueelseseejecuta.

c.Conversionesdetipos

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Las conversiones de tipos consisten en transformar una variable de un tipo a otro tipo. Las conversiones se
puedenefectuarhaciauntiposuperioroinferior.

Siseutilizaunaconversinhaciauntipoinferior,hayriesgodeprdidadeinformacin.Porejemplo,laconversin
deuntipoDoublehaciauntipoLongcausarlaprdidadelapartedecimaldelvalor.

Ejemplo

Dim x As Double
Dim y As Long
x = 21.123456789012344
y = x
Console.WriteLine("valor de x: " & x)
Console.WriteLine("valor de y: " & y)

Semuestra:

valor de x: 21,1234567890123
valor de y: 21

Unaopcindelcompiladorpermiteverificarlaexistenciadeestetipodeconversin.

Dependiendodelaconfiguracindeestaopcin,siseintentarealizarciertaconversinsegeneraunavisooun
errordecompilacin.

Pueden tambin ser implcitas o explcitas segn el cdigo utilizado. Las conversiones implcitas se realizan
simplementeasignandounavariabledeuntipoaunavariabledeotrotipo.Lasconversionesexplcitasnecesitan

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
elusodepalabrasclavesconcretas,quesueletenerelformatoCxxxoxxx,yquecorrespondealtipoenelquese
convertirelvalor.

Lasiguientetablaresumeestosdiferentesoperadores.

Operador Tipodedestino

CBool Booleano

CByte Byte

CChar Char

CDate Date

CDbl Double

CDec Decimal

CInt Integer

CLng Long

CObj Object

CSByte SByte

CShort Short

CSng Single

CStr String

CUint UInteger

CULng ULong

CUShort UShort

Otro operador (CType) permite la conversin hacia un tipo estndar de lenguaje, pero sobre todo hacia un tipo
personalizado,comoporejemplounaclase.

Esteoperadoresmsgeneralynecesitadosparmetros:

l Lavariablequesequiereconvertir.

l Eltipohaciaelquesequiererealizarlaconversin.

Siseintentaunaconversinrestrictiva,lautilizacindeestosoperadoresnocausaerroresdecompilacin,yaque
elcompiladorconsideraquelarealizaaconciencia.

Lasconversionesdesdecadenasdecaracteresyhaciacadenasdecaracteressonmsespecficas.

Conversinhaciaunacadenadecaracteres

La funcin format permite elegir el formato del resultado de la conversin de cualquier valor a una cadena de
caracteres.Estafuncinrecibecomoargumentoselvalorquehayqueconvertiryelformatoenelquesedeseael
resultado. Este segundo parmetro tiene forma de cadena de caracteres y muestra el resultado en el aspecto
deseado.

Algunosformatosestndaresestnpredefinidos,perotambinesposiblepersonalizarelresultadodelafuncin
format.Acontinuacinsepresentanlosparmetrosdeestafuncin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Formateodevaloresnumricos

Currency

Formatomonetariotalcomoestdefinidoenlasopcionesregionalesydeidiomadelpaneldecontrol
delsistema.

Ejemplo:format(12.35,"Currency")

Resultado: 12,35

Fixed

Utilizaalmenosuncarcterparalaparteenterayalmenosdoscaracteresparalapartedecimalde
unnmero.Elseparadordecimalaparecetalcomoestdefinidoenlasopcionesregionalesyde
idiomadelpaneldecontroldelsistema.

Ejemplo:format(.2,"Fixed")

Resultado: 0,20

Percent

Multiplicaelvalorindicadoporcienydespusaadeelsmbolo%.

Ejemplo:format(.2,"Percent")

Resultado: 20,00%

Standard

Formatonumricotalcomoestdefinidoenlasopcionesregionalesydeidiomadelpaneldecontrol
delsistema.

Ejemplo:format(245813.5862,"Standard")

Resultado: 245.813,59

Scientific

Notacincientficacondoscifrassignificativas.

Ejemplo:format(245813.58,"Scientific")

Resultado: 2,46E+05

Notacincientficaconseiscifrassignificativas.

Ejemplo:format(245813.5862,"E")

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Resultado: 2,458136E+005

Formatohexadecimal.Utilizablenicamenteparalosvaloresenteros.

Ejemplo:format(245813,"X")

Resultado: 3C035

Yes/No

True/False

On/Off

DevuelveNo,False,Offsielvaloresigualacerosino,devuelveYes,True,Onparaelrestodelos
valores.

Cadenadeformateopersonalizadaparavaloresnumricos

Reservaunaubicacinparauncarcternumrico.Loscerosnosignificativossevisualizan.

Ejemplo:format(245813.12,"00000000000.0000")

Resultado: 00000245813,1200

Reservaunaubicacinparauncarcternumrico.Loscerosnosignificativosnosevisualizan.

Ejemplo:format(245813.12,"###########.####")

Resultado: 245813,12

Reservaunaubicacinparaelseparadordecimal.Elcarcterrealmenteutilizadoenelresultado
dependedelaconfiguracindelasopcionesregionalesydeidiomadelpaneldecontroldelsistema.

Reservaunaubicacinparaelseparadordemillares.Elcarcterrealmenteutilizadoenelresultado
dependedelaconfiguracindelasopcionesregionalesydeidiomadelpaneldecontroldelsistema.

Permiteutilizaruncarcterconunsignificadoespecialcomocarcterordinarioenunacadenade
formateo.Enelsiguienteejemplo,elcarcter\hacequeelcarcter#pierdasusignificadoespecial.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Ejemplo:format(325,"comandoN\#0000")

Resultado: comando N#0325

Formatosdefechayhora

FormatodeFechacortoyformatodeHoratalycomoestdefinidoenlasopcionesregionalesyde
idiomadelpaneldecontroldelsistema.

Ejemplo:format(now,"G")

Resultado 17.10.05 11:10:42

FormatodeFechalargotalycomoestdefinidoenlasopcionesregionalesydeidiomadelpanelde
controldelsistema.

Ejemplo:format(now,"D")

Resultado lunes 17 de octubre de 2005

FormatodeFechacortotalycomoestdefinidoenlasopcionesregionalesydeidiomadelpanelde
controldelsistema.

Ejemplo:format(now,"d")

Resultado 17/10/05

FormatodeHoratalycomoestdefinidoenlasopcionesregionalesydeidiomadelpaneldecontrol
delsistema.

Ejemplo:format(now,"T")

Resultado 11:45:30

Formatoordenable.

Ejemplo:format(now,"s")

Resultado: 2005-10-17T11:47:30

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Cadenadeformateopersonalizadoparavaloresdefechayhora

dDadelmessinceronosignificativo

ddDadelmesconceronosignificativo

dddNombredeldadelasemanaabreviado

ddddNombredeldadelasemanacompleto

MNmerodelmessinceronosignificativo

MMNmerodelmesconceronosignificativo

MMMNombredelmesabreviado

MMMMNombredelmescompleto

hHorasinceronosignificativo(formato12H)

hhHoraconceronosignificativo(formato12H)

HHorasinceronosignificativo(formato24H)

HHHoraconceronosignificativo(formato24H)

mMinutosinceronosignificativo

mmMinutoconceronosignificativo

sSegundosinceronosignificativo

ssSegundoconceronosignificativo

yAoenunacifra.Sieselnicocarcterdelacadenadeformateo,enestecasosedebeutilizar%y

aayyAoendoscifras

yyyyAoencuatrocifras

zzzDiferenciahorariaconrelacinaltiempouniversal(GMT)

Conversindeunacadenadecaracteres

LafuncinValpermitelaconversindeunacadenadecaracteresavalornumrico.Leelacadenacomoparmetro
hastaqueencuentrauncarcterquenoseaunacifra,unespacio,unatabulacinounpunto.Transformadespus
estaporcindecadenaenvalornumrico,teniendoencuentaloseventualesparmetrosdeformateodefinidosa
niveldelsistema,comoporejemploelseparadordemillares.Loscaracteres&Ho&Ocolocadosalprincipiode
lacadenaindicanqueelvalorseexpresaenhexadecimaloenoctal.

Ejemplo:val("&H7FFF")

devuelve

32767.0

d.Declaracindelasvariables

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Pordefecto,elcompiladorVisualBasicconsideraquetodavariablequeapareceenunaaplicacindebehabersido
declarada.Puedemodificarestaopcindelcompiladoraadiendolalneasiguientealcdigo:

Option Explicit Off

Estaopcindebeserlaprimeralneadelarchivofuente,yseraplicadaatodoelcdigodelarchivo.

Conestaopcin,yanoexistelaobligacindedeclararunavariableantesdeutilizarla.Aunqueparezcacmoda,
estasolucinpuedeproducirerroresenelcdigodifcilesdeencontrar.Observeelcdigosiguiente:

Function CalcularIVA(ByVal Precio As Single) As Single


Dim ValorTemporal As Single
ValorTemporal = Precio * 1.18
Return ValorTempor
End Function

Ningnproblemaalcompilar,ysinembargolafuncinnosdevuelvesiempreunvalorigualacero.Sinosfijamos
mejorenelcdigo,nosdamoscuentadequehayunerrorenlalneaReturn ValorTempor:faltandosletrasenel
nombre de la variable ValorTemporal. A la hora de compilar, Visual Basic considera que se trata de una nueva
variableyporlotantolainicializaacero.Perdidoentrecientosdelneasdecdigo, estetipodeerrorespuedeser
muydifcildeencontrar.Dejandolaopcinde declaracindevariablescomoobligatoria,habradetectadoelerror
alcompilarlaaplicacin.

VeamoscmodeclararlasvariablesenVisualBasic.Lainstruccinbsicaparaladeclaracindeunavariableesla
instruccinDim.

Lasintaxisgeneraldedeclaracindeunavariableeslasiguiente:

Dim NombreVariable1[,NombreVariable2,NombreVariableN] [As Tipo de


la Variable]
[= Valor inicial]

Losparmetrosentrecorchetessonopcionalesenladeclaracin.Siseomiteeltipodevariable,seleasignarpor
defectoeltipoObjectqueofreceVisualBasic.

Si se omite el valor inicial, la variable se inicializar a cero si corresponde a un tiponumrico, a una cadena de
caracteresvacasiesdetipoString,alvalorNothingsiesdetipoObjectyafalsesiesunBooleano.

Siseespecificanvariosnombres,todaslasvariablescorrespondientesserndeltipoindicado.

e.Inferenciadetipos

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Hemos visto en las secciones precedentes que es recomendable declarar las variables antes de su uso. Sin
embargo,enalgunoscasos,sepuedeconsiderardejarqueelcompiladorrealiceunapartedeltrabajo.Graciasa
lainferenciadetipos,elcompiladorpuededeterminareltipoquesedebeutilizarparaunavariablelocaldeclarada
sinlaclusulaas.Paraello,sebasaeneltipodelaexpresinutilizadaparainicializarla variable.Enelejemplo
siguientelavariableesconsideradacomounacadenadecaracteres.

Dim nombre = ngel

Paraasegurarsedequeestavariableesconsideradarealmentecomounacadenadecaracteres,bastaconpedir
aIntelliSensequnosproponeparautilizarestavariable.

Enefecto,aqutenemosanuestradisposicinlosmtodosypropiedadesdeltipoString.

Paraquelainferenciadetipofuncionecorrectamente,esobligatoriorespetaralgunasreglas:

l Lainferenciadetipossolofuncionaparavariableslocales,esdecir,aquellasdeclaradasdentrodeunprocedimiento
ofuncin.

l Lainicializacindebehacerseenlamismalneadecdigoqueladeclaracin.Enelejemplosiguientelavariablese
consideradetipoObject.

l Lavariablenopuedeserdeclaradaesttica.Siesteeselcaso,seconsiderardetipoObject.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
f.mbitodelasvariables

Elmbitodeunavariableeslaporcindecdigoapartirdelacualsepuedemanipulardichavariable.Depende
dedndeestsituadaladeclaracinydelapalabraclaveusadaenladeclaracin.

mbitoaniveldebloque

Solamenteelcdigodelbloquepodrtrabajarconlavariable(porejemplo,enunbuclefor next).Sinembargo,si
elmismobloquedecdigoseejecutavariasvecesdurantelaejecucindeunprocedimientoofuncin,encasode
unbucleDo Loopporejemplo,lavariablesolosercreadalaprimeravezqueseejecutaelcdigo,conservandosu
valordeunapasadaaotra.Paramodificarestefuncionamiento,bastaconinicializarlavariableenelmomentode
su declaracin. Solo puede utilizarse la palabra clave Dim para declarar una variable dentro de un bloque de
cdigo.

Ejemplo

Dim i As Integer
For i = 0 To 5
Dim j As Integer
Dim k As Integer = 0
j = j + 1
k = k + 1
Console.WriteLine("valor de j:{0}", j)
Console.WriteLine("valor de k:{0}", k)
Next
Muestra:
valor de j:1
valor de k:1
valor de j:2
valor de k:1
valor de j:3
valor de k:1
valor de j:4
valor de k:1
valor de j:5
valor de k:1
valor de j:6
valor de k:1

mbitoaniveldeprocedimiento

Solamenteelcdigodelprocedimientoodelafuncindondesedeclaralavariablepodrmodificarsucontenido.
Este tipo de variable tambin se llama variable local. nicamente la palabra clave Dim puede utilizarse para
declararunavariabledentrodeunprocedimientoofuncin.

mbitoaniveldemdulo

Este mbito corresponde a una variable declarada en el exterior de un procedimiento o funcin, es decir, en un
mdulo,enunaclaseoenunaestructura.Ladeclaracinpuedeaparecerencualquiersitiodelcdigo(siempre
quenoseaenunprocedimientoofuncin).Sinembargo,esaconsejableagruparlasdeclaracionesparafacilitarel
mantenimientodelcdigo.

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
mbitoaniveldeespaciodenombres

La variable se podr utilizar en el cdigo del espacio de nombres incluso si el cdigo est situado en distintos
mdulos. Si no declara explcitamente ningn espacio de nombres en su cdigo, siempre existir el espacio de
nombrespordefecto,ysepodrhablarenesecasodembitodeproyecto.

g.Niveldeaccesodelasvariables

El nivel de acceso de una variable se combina con el alcance de la variable y determina qu porcin de cdigo
puedeleeryescribirenlavariable.Unconjuntodepalabrasclavespermitecontrolarelniveldeacceso.Seutilizan
enellugardelapalabraclaveDimalahoradeladeclaracindelavariable.

Public

Los elementos declarados con la palabra clave Public sern accesibles desde cualquier parte del cdigo del
proyectoenelquesondeclarados,ydesdecualquierotroproyectoquereferencieelproyectoenelquesehan
declarado.Lapalabraclave Publicnopuedeutilizarseparadeclararunavariabledentrodeunprocedimientoo
funcin.

Protected

Estapalabraclavesolosepuedeutilizarenelinteriordeunaclase.Permiterestringirelaccesoalavariable,al
cdigodelaclaseyalcdigodetodaslasclasesqueheredandeella.

Friend

Los elementos declarados con esta palabra clave sern accesibles desde el ensamblado en el que han sido
declaradas.Nopuedeutilizarseestapalabraclaveenelinteriordeunprocedimientoofuncin.

ProtectedFriend

EsteniveldeaccesoeslaunindelosnivelesdeaccesoProtectedyFriend.Hacevisiblelavariablealconjuntodel
ensambladoenelcualestdeclaradayatodaslasclasesqueheredandeaquellaenlaqueestdeclarada.

Private

Esta palabra clave restringe el acceso de la variable al mdulo, a la clase o a la estructura en el que ha sido
declarada.Nosepuedeutilizarenelinteriordeunprocedimientoofuncin.

La palabra clave Dim puede utilizarse en cualquier parte del cdigo para la declaracin de una variable.
Recordemosque,enelcasodeunadeclaracinaniveldemdulo,esequivalentealapalabraclavePrivate.Para
facilitarelmantenimientodelcdigo,utilicelapalabraclavePrivateaniveldemdulo,yreservelapalabraclave
Dimparaladeclaracindevariableslocales(enelinteriordeprocedimientosofunciones).

h.Ciclodevidadelasvariables

Elciclodevidadeunavariablenospermitedeterminarhastaqumomentodelaejecucindelcdigovaaestar
disponiblenuestravariable.

Para una variable declarada en un procedimiento o funcin, el ciclo de vida corresponde a la duracin de la

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
ejecucin del procedimiento o funcin. En el momento de finalizar la ejecucin del procedimiento o funcin, se
eliminalavariabledelamemoria.Sevolveracreardurantelaprximallamadaalprocedimientoofuncin.Para
modificarestaformadefuncionar,bastacondeclararlavariableconlapalabraclavestaticenlugardeDim.En
estecaso,cuandosellamaporprimeravezalprocedimientoofuncin,secrealavariableenmemoria,yyanose
eliminaalfinalizarelprocedimientoofuncin.Sisevuelveallamaralprocedimientoofuncin,seutilizarelmismo
emplazamientoenmemoriaparalavariable,yestacontendrelvaloranterior.

2.Lasconstantes

En una aplicacin, a menudo ocurre que se utilicen valores numricos o cadenas de caracteres que no sern
modificadosduranteelfuncionamientodelaaplicacin.Parafacilitarlalecturadelcdigo,seaconsejadefinirestos
valoresenformadeconstantes.

Ladefinicindeunaconstanteserealizaconlapalabraclaveconst.

Ejemplo

Const ValorMaxi = 100


Const Mensaje="Demasiado grande"

Entoncessepuedeutilizarlaconstanteenelcdigoenlugardelvalorquerepresenta.

If resultado> ValorMaxi then


Console.WriteLine(Mensaje)

Avecessernecesarioespecificaruntipoparalaconstante(enelcasodequeelcompiladorestconfiguradoen
modoStrict).Ladeclaracindelaconstantetendrenesecasolaforma:

Const ValorMaxi as integer =100

Lasreglasrelativasaltiempodevidayalmbitodelasconstantessonidnticasalasrelativasalasvariables.

Elvalordeunaconstantetambinsepuedecalculardesdeotraconstante.

Ejemplo

Public Const total As Integer = 100


Public Const mitad As Integer = Total / 2

Enestecaso,hayqueserprudenteynocrearunareferenciacircularqueprovocaraunerrordecompilacin.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
MuchasconstantesestnyadefinidasaniveldeVisualBasic.Elnombredeestasconstantessuelecomenzarpor
vb...

Veamosenlatablasiguientelasmsutilizadas:

Nombredelaconstante Valordelaconstante

vbCr Retornodecarro(carcterN13)

vbLf Saltodelnea(carcterN10)

vbCrLf CombinacindeRetornodecarro+saltodelnea

vbNullChar CarcterNull(carcterN0)

vbTab Tabulacin(carcterN9)

vbBack Atrs(carcterN8)

3.Lasenumeraciones

Una enumeracin nos va a permitir definir un conjunto de constantes que estn vinculadas entre ellas. La
declaracinseefectadelasiguientemanera:

Enum dias
Domingo
Lunes
Martes
Miercoles
Jueves
Viernes
Sabado
End Enum

Pordefecto,elprimervalordelaenumeracinseinicializaacero.Luegolasconstantessiguientesseinicializancon
unincrementodeuno.Ladeclaracinanteriorhubierapodidoescribirse:

Const Domingo = 0
Const Lunes = 1
Const Martes = 2
Const Miercoles = 3
Const Jueves = 4
Const Viernes = 5
Const Sabado = 6

Sepuedeinterrumpirlasecuenciadeincrementacinautomticaenunaenumeracin,einclusonoutilizarla,como
enelejemplosiguiente:

Enum dalton
Joe = 158
Jack = 163
William = 173

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
Averell = 185
End Enum

Sinembargo,hacefaltaquelosvaloresutilizadosenlaenumeracinseanvaloresenteros.

Unavezdefinidaunaenumeracin,selapuedeutilizarcomountipodevariableespecfico.

Dim Altura as Dalton

LosnicosvaloresquesepuedenasignaralavariableAlturasonlosdefinidosenlaenumeracin.

Altura Dalton.Joe
Console.WriteLine(Altura)
Altura =45 Invlido

Cuandohacereferenciaaunelementodesuenumeracin,debeestarprecedidoporelnombredelaenumeracin,
comoenelejemploanterior.Paraevitarlo,hayqueespecificarenelcdigoquequiereutilizarlaenumeracin.Esto
seconsigueimportndola,conlaayudadelainstruccinsiguiente:

Imports Application.dalton

Hechoesto,sepuedenutilizardirectamentelosvaloresdelaenumeracin.

Altura = Joe

Esos,habrquetenercuidadoconlosnombresdeconstantesquepuedanserigualesenotrasenumeraciones.

Ladeclaracindeunaenumeracinnopuederealizarsedentrodeunprocedimientoofuncin.

El mbito de una enumeracin sigue las mismas reglas que las variables (utilizando las palabras claves Public,
Private,Friend,Protected).

4.Lasmatrices

Lasmatricesnosvanapermitirhacerreferenciaaunconjuntodevariablesconelmismonombreyutilizarunndice
para diferenciarlas. Una matriz puede tener una o varias dimensiones (hasta 32, pero ms all de 3 es difcil
representarelcontenidodelamatriz).Elprimerelementodeunamatrizsiemprellevacomondicecero.

Elndicemximodeunamatrizseespecificaenelmomentodelacreacindelamatriz.Elnmerodeelementosde
unamatrizser,pues,elndicemayormsuno.

Matricesdeunadimensin

Ladeclaracinserealizaigualqueparaunavariableclsica,peroaadiendoelndicemayordespusdelnombre.

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim CifraNegocio(11) as Decimal

Esta declaracin crear una matriz con doce casillas numeradas de 0 a 11. Los elementos de la matriz son
accesiblesdelamismaformaqueparalasvariablesclsicas.Bastaconaadirelndicedelelementoquequeremos
modificar.

CifraNegocio(1)=12097

Hay otra solucin disponible para la creacin de una matriz. Permite de manera simultnea crear una matriz e
inicializarsucontenido.Lasintaxiseslasiguiente:

Dim tasaIVA() As Decimal = {0, 4, 8, 18}

En este caso, no es necesario precisar un tamao para la matriz. El dimensionamiento se har de manera
automticaenfuncindelnmerodevaloresubicadosentrelasllaves.

Matricesdevariasdimensiones

La sintaxis para su declaracin es similar a la de las matrices de una dimensin. Simplemente se debe indicar un
valorparaelndicemsgrandedecadaunadelasdimensiones,separndolosporunacoma.

Dim Cubo(4, 4, 4) As Integer

Elaccesoaunelementodelamatrizseefectademaneraidnticaindicandolosndicesquepermitenidentificarla
casilladelamatrizreferida.

Cubo(0,1,1)=52

La sintaxis que permite inicializar una matriz de varias dimensiones en el momento de su declaracin es un poco
mscompleja.

Dim Matriz(,) As Integer = {{1, 2}, {3, 4}}

Esteejemplocreaunamatrizdedosdimensionesdedoscasillaspordoscasillas.

Conestatcnica,lacreacindematricesdegrantamaodevariasdimensionespuedeserpeligrosa.

Redimensionarunamatriz

El tamao de las matrices no es fijo, puede modificarse durante el funcionamiento de la aplicacin. La instruccin
Redimpermitehacerlo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 19 -
Redim CifraNegocio(52)

Tenemos ahora 53 casillas disponibles para almacenar informacin en nuestra matriz. Sin embargo, si tenamos
informacin almacenada en la matriz, esta se ha perdido al realizar la redimensin. Para conservar su contenido,
hayqueindicarloponiendolapalabraclavePreservejuntoconlainstruccinRedim.

Redim Preserve CifraNegocio(52)

Enestecaso,elcontenidoinicialdelamatrizseconserva,yseaadencasillasnuevastraslasyaexistentes,sin
asignarsucontenido.

En el caso de las matrices de ms de una dimensin, solo la ltima de ellas puede ser modificada si se desea
conservar el contenido de la matriz. El nmero de dimensiones de una matriz no se puede modificar con la
instruccinRedim.

LainstruccinRedimtambinpuedeusarseparaindicareltamaoinicialdeunamatriz.Enesecaso,noharafalta
indicareltamaodelamatrizenelmomentodesudeclaracinniutilizarlainstruccinRedim para dimensionarlo.
SeranecesarioutilizarlainstruccinRedimantesdecualquieraccesoalcontenidodelamatriz.

Manipulacionescorrientesdelasmatrices

Cuandosetrabajaconmatrices,amenudohayalgunasoperacionesquedebenrealizarse.Esteapartadodescribe
lasoperacionesmsfrecuentesconmatrices.

Obtenereltamaodeunamatriz

BastaconutilizarlapropiedadLengthdelamatrizparaconocerelnmerodeelementosquepuede
contener.Enelcasodeunamatrizmultidimensional,elresultadocorrespondealnmerototalde
casillasdelamatriz,osea,elproductodeltamaodecadaunadelasdimensiones.Nosetratadel
espaciodememoriaocupadoporlamatriz,sinodelnmerototaldecasillasdelamatriz.

Dim Matriz(,) As Integer = {{1, 2}, {3, 4}}


Console.WriteLine("tamao total de la matriz: {0}", Matriz.Length)

Para obtener la ocupacin de memoria de la matriz, hay que multiplicar su tamao por el nmero de bytes con
objetodecrearunacasillabsicadelamatriz.

Obtenereltamaodelasdimensionesdeunamatriz

ElmtodoGetLengthesperacomoparmetroladimensindelamatrizparalaquesedeseaobtenerel
tamao:

- 20 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim MiMatriz(,) As Integer = {{1, 2}, {3, 4}, {5, 6}}
Console.WriteLine("tamao de la primera dimensin: {0}", MiMatriz.GetLength(0))
Console.WriteLine("tamao de la segunda dimensin: {0}", MiMatriz.GetLength(1))

Muestraelresultadosiguiente:

tamao de la primera dimensin: 3


tamao de la segunda dimensin: 2

Obtenerladimensindeunamatriz

LapropiedadRankdeunamatrizdevuelvedirectamenteladimensindelamatriz:

Dim MiMatriz(,) As Integer = {{1, 2}, {3, 4}, {5, 6}}


Console.WriteLine("esta matriz tiene {0} dimensiones",
MiMatriz.Rank)

Semuestraelresultadosiguiente:

esta matriz tiene 2 dimensiones

Buscarunelementoenunamatriz

La funcin IndexOf de la clase Array permite efectuar una bsqueda en una matriz. Acepta como parmetros la
matrizenlaquesehacelabsquedayelelementobuscadoenlamatriz.Elvalordevueltocorrespondealndice
dondeelelementohasidoencontradoenlamatrizo1sielelementonoseencuentraenlamatriz.

Dim probar() As String = {"pan", "mantequilla", "mostaza", "mermelada"}


Console.WriteLine(Array.IndexOf(probar, "mostaza"))

Ordenarunamatriz

ElprocedimientoSortdelaclaseArrayaseguralaordenacindelamatrizquerecibeenparmetro.Laordenacin
seefectaporordenalfabticoparalasmatricesdecadenadecaracteresyporordenascendenteparalasmatrices
devaloresnumricos.

Dim probar() As String = {"pan", "mantequilla", "mostaza", "mermelada"}


Dim plato As String
Array.Sort(probar)
For Each plato In probar
Console.WriteLine(plato)
Next

Semuestraelresultadosiguiente:

mantequilla
mermelada
mostaza

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 21 -
pan

5.Lascadenasdecaracteres

Las variables de tipo String permiten la manipulacin de cadenas de caracteres por su aplicacin. Podemos elegir
entredosposibilidadesparatrabajarconcadenasdecaracteres:

l UtilizarlasfuncionesdeVisualBasic.

l UtilizarlosmtodosdelaclaseSystem.String.

Vamosamirarcmorealizarlasoperacionesmscorrientesenlascadenasdecaracteres.

Asignacindeunvaloraunacadena

Hemosvistoque,paraasignarunvaloraunacadena,tenemosqueponerestevalorentre"y".Estoplanteaun
problemasiqueremosincluirelcarcter"enlacadena.Paraquenoseainterpretadocomocarcterdeprincipioo
findecadena,debemosdoblarelcarcter"comoenelejemplosiguiente.

Dim Cadena as String


Cadenas= "l dijo: "" ya basta! """
Console.WriteLine(Cadena)

Obtenemosalavisualizacin: ldijo: yabasta!

Paralossiguientesejemplos,vamosatrabajarcondoscadenas.

cadena1 = "este invierno ser lluvioso"


cadena2 = "este invierno ser fro"

Extraccindeuncarcterparticular

Para obtener el carcter presente en una posicin dada de una cadena de caracteres, se puede considerar la
cadenacomounamatrizdecaracteresyporlotantoalcanzarelcarcterdeseadoporunndice.

Console.WriteLine("El tercer carcter de la cadena1 es: {0}", cadena1(2))

Otrasolucin,peroestavezutilizandolapropiedadCharsdelaclaseString:

Console.WriteLine("El tercer carcter de la cadena1 es: {0}",


cadena1.Chars(2))

Resultado:

El tercer carcter de la cadena es: t

Enlosdoscasos,lanumeracindeloscaracterescomienzaacero,comoenunamatriz.

Obtenerlalongituddeunacadena

- 22 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Paraobtenerlalongituddeunacadena,tenemosdosopciones,lapropiedadLengthdelaclaseStringolafuncin
LendeVisualBasic.Lasdosdevuelvenelnmerodecaracteresquetienelacadena.

Console.WriteLine("la cadena1 contiene {0} caracteres", cadena1.Length)


Console.WriteLine("la cadena2 contiene {0} caracteres", Len(cadena2))

Resultado:

La cadena 1 contiene 27 caracteres.


La cadena 2 contiene 23 caracteres.

Particindecadenas

Tenemosvariasposibilidadesenfuncindelapartedelacadenaquequeramosrecuperar.

Elprincipiodelacadena

LafuncinLeftdevuelvelosxprimeroscaracteresdelacadena.

Console.WriteLine("los cinco primeros caracteres de la cadena1 son {0}",


Left(cadena1,5))

Resultado:

Los cinco primeros caracteres de la cadena1 son este .

Elfinaldelacadena

LafuncinRightdevuelvelosxltimoscaracteresdelacadena.

Console.WriteLine("los cinco ltimos caracteres de la cadena1 son {0}",


Right(cadena1,5))

Resultado:

Los cinco ltimos caracteres de la cadena1 son vioso.

Unapartecualquieradelacadena

LafuncinMidoelmtodoSubstringdelaclaseStringdevuelvenunapartedelacadenaenfuncin
delaposicindepartidayelnmerodecaracteresparadevolverqueselespasanporparmetro.La
funcinMidnecesitaademslacadenadelaquesequiereobtenerunaparte.

Console.WriteLine("Una parte de la cadena1 {0}", Mid(cadena1, 2, 5))


Console.WriteLine("Una parte de la cadena2 {0}", cadena2.Substring(2, 5))

Obtenemoscomovisualizacin:

Una parte de la cadena1 ste i


Una parte de la cadena2 te in

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 23 -
CuidadoconlafuncinMid:lanumeracindeloscaracteresempiezacon1.

Comparacindecadenas

Hayvariassolucionesposiblessegnelobjetivoquesequierealcanzarconlacomparacindelasdoscadenas.Silo
nicoquequeremosescomprobarsidoscadenassoniguales,podemosutilizareloperador=olafuncinEqualsde
laclaseString.

If cadena1 = cadena2 Then


Console.WriteLine("son iguales")
Else
Console.WriteLine("no son iguales")
End If

If cadena1.Equals(cadena2) Then
Console.WriteLine("son iguales")
Else
Console.WriteLine("no son iguales")
End If

Siqueremossaberculdelasdosesmslarga,debemosutilizarelmtodoComparedelaclaseStringolafuncin
StrComp.Enlasdosopciones,lascadenasquesequierencomparardebenpasarsecomoparmetros.Elresultado
de la comparacin se devuelve con la forma de un entero inferior a cero, si la primera cadena es inferior a la
segunda igual a cero si las dos cadenas son idnticas, y superior a cero si la primera cadena es superior a la
segunda.

Select Case cadena1.CompareTo(cadena2)


Case Is < 0
Console.WriteLine("la cadena1 es ms corta que la cadena2")
Case 0
Console.WriteLine("la cadena1 es igual que la cadena2")
Case Is > 0
Console.WriteLine("la cadena1 es ms larga que la cadena2")
End Select

Insercinenunacadena

ElmtodoinsertdelaclaseStringpermiteinsertarunacadenadentrodeotra.Esperacomoargumentounentero
yunacadenaynosdevuelvelacadenadesalidaenlaqueseencuentrainsertadalacadenapasadaenparmetro
enlaposicinespecificada.

Dim cadena3 As String


cadena3 = cadena2.Insert(19, "muy ")
Console.WriteLine(cadena3)

Lainstruccinanteriornosmuestralalneacorrespondiente:

- 24 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
este invierno ser muy fro

Supresindeespacios

l Alprincipiodelacadena:Console.WriteLine(ltrim cadena1))

oConsole.WriteLine(cadena1.TrimStart())

l Alfinaldelacadena:Console.WriteLine(rtrim(cadena1))

oConsole.WriteLine(cadena1.TrimEnd())

l Alprincipioyalfinal:Console.WriteLine(trim(cadena1))

oConsole.WriteLine(cadena1.Trim())

Cambioamaysculasominsculas

l Todoenmaysculas:Console.WriteLine(Ucase(cadena1))

oConsole.WriteLine(cadena1.ToUpper())

l Todoenminsculas:Console.WriteLine(Lcase(cadena1))
oConsole.WriteLine(cadena1.ToLower())

Bsquedaenunacadena

La funcinInStr o el mtodoIndexOf de la claseString permiten la bsqueda de una cadena dentro de otra. El


primerparmetrocorrespondealacadenaenlaquesevaaefectuarlabsquedayelsegundocorrespondeala
cadenabuscada.Lafuncindevuelveunenteroqueindicalaposicinenlaquesehaencontradolacadena,ocero
silacadenanohasidoencontrada.Pordefecto,labsquedaempiezaalprincipiodelacadena.Puedeutilizarotra
versindelafuncinInStroIndexOfqueesperatresparmetros,siendoelprimeroparaestafuncinlaposicinde
salidadelabsqueda,ysiendolosotrosdosrespectivamentelacadenaenlaquesevaaefectuarlabsquedayla
cadenabuscada.Lanumeracindeloscaracteresesapartirde1paralafuncinInStr.

Dim busqueda As String


Dim posicion As Integer
busqueda = "e"
posicion = InStr(cadena1, busqueda)
While (posicion > 0)
Console.WriteLine("cadena encontrada en la posicin {0}", posicion)
posicion = InStr(posicion + 1, cadena1, busqueda)
End While
Console.WriteLine("fin de la bsqueda")

Obtenemoscomovisualizacin:

cadena encontrada en la posicin 1


cadena encontrada en la posicin 4
cadena encontrada en la posicin 10
cadena encontrada en la posicin 16
fin de la bsqueda

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 25 -
Sustitucinenunacadena

Avecesesdeseablepoderbuscarunacadenadentrodeotra,comoenelejemploanterior,perotambinsustituir
las porciones de cadenas encontradas. La funcin Replace permite especificar una cadena de sustitucin para la
cadenabuscada.Esperauntotaldecincoparmetros:

l Lacadenaenlaquesevaaefectuarlabsqueda.

l Lacadenabuscada.

l Lacadenadesustitucin.

l Laposicindesalidadelabsqueda.

l Elnmerodesustitucionesdeseado(1paratodaslascoincidenciasdelacadenabuscada).

cadena3 = Replace(cadena1, "invierno", "verano", 1, -1)


Console.WriteLine(cadena3)

Obtenemoscomovisualizacin:

este verano ser lluvioso

6.Lasestructuras

Lasestructurasofrecenlaposibilidaddecombinardatosdediferentestiposparacrearunnuevotipocompuesto.
EstenuevotipopodrusarsedespusenladeclaracindevariablescomountipoestndardeVisualBasic.

Lasestructurassonmuyprcticascuandosedeseamanipulardatosquetienenunvnculoentres.Porejemplo,en
una aplicacin contable, los datos relativos a los clientes (cdigo cliente, apellido, nombre, direccin) se pueden
gestionarmsfcilmenteconlaformadeunaestructuraquecomovariablesindividuales.

a.Declaracindeunaestructura

LadeclaracindeunaestructuraserealizaentrelaspalabrasclavesStructureyEnd Structure.Entreestasdos
palabras claves, se debe introducir al menos un miembro de la estructura. Los miembros de la estructura son
variables,procedimientosofuncionesdeclaradasenelinteriordelaestructura.Comoencualquierotroelemento
declaradoenVisualBasic,tienelaposibilidaddeindicarunniveldeaccesoparacadamiembrodelaestructura.Sin
informacinespecfica,elmiembroesconsideradopblico.Porelcontrario,esimposibleinicializarlosmiembrosde
unaestructuraenelmomentodeladeclaracin.

Ejemplo

Public Structure Cliente


Public Codigo As Integer
Public Apellidos As String
Public Nombre As String
Public DatosDeContacto As String
End Structure

Los miembros de una estructura tambin pueden ser variables de tipo estructura. En el ejemplo anterior, la
variablededatosdecontactosepuededescomponercomounaestructuradetipodireccin.

- 26 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Ejemplo

Public Structure Direccion


Public Numero As Integer
Public Calle As String
Public CodigoPostal As Integer
Public Ciudad As String
End Structure
Public Structure Cliente
Public Codigo As Integer
Public Apellidos As String
Public Nombre As String
Public DatosDeContacto As Direccion
End Structure

Lasestructurastambinaceptanprocedimientosofuncionescomomiembros.Sesuelenutilizarparamanipularlas
variablesmiembrosdelaestructura.

Ejemplo

Public Structure Direccion


Public Numero As Integer
Public Calle As String
Public CodigoPostal As Integer
Public Ciudad As String
Public Function getDireccion () As String
Return Calle & " " & Numero & vbCrLf & CodigoPostal & vbTab &
Ciudad.ToUpper
End Function
End Structure

b.Utilizacindelasestructuras

Lasestructurasseutilizancomotiposdedatosclsicos.Convienedeclararpreviamenteunavariabledeltipodela
estructura.

Dim Cliente1 As Cliente

Deaquenadelante,estavariablepermiteaccederasusmiembrosgraciasaloperador.llamadooperadorde
acceso.

Ejemplo

Cliente1.Codigo = 999
Cliente1.Apellidos = "losApellidos"
Cliente1.Nombre = "elNombre"

Siunodelosmiembrosdelaestructuraeselmismodetipodeestructura,deberigualmenteutilizareloperador
deaccesoparapodermanipularlosmiembrosanidados.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 27 -
Ejemplo

Cliente1.DatosDeContacto.Numero = 26
Cliente1.DatosDeContacto.Calle = "calle Miguel Servet "
Cliente1.DatosDeContacto.CodigoPostal = 50008
Cliente1.DatosDeContacto.Ciudad = "Zaragoza"

Los tipos estructura son tipos de datos por valor, es decir, que la variable contiene realmente los datos de la
estructura (en oposicin con las variables de tipo referencia, donde la variable solo contiene la ubicacin en la
memoriadondeseencuentranlosdatos).

Estonospermiteasignaraunavariabledetipoestructuraelcontenidodeotravariabledelmismotipo.Eneste
caso,seproducedenuevolacopiadedatosdecadamiembrodelavariablefuentealmiembrocorrespondiente
delavariabledestino.

Ejemplo

Dim Cliente2 As Cliente


Cliente2 = Cliente1
Console.WriteLine("Cliente1: " & vbCrLf & Cliente1.etiqueta)
Console.WriteLine("Cliente2: " & vbCrLf & Cliente2.etiqueta)

Semuestraelresultadosiguiente:

Cliente1: Sr. elNombre losApellidos


calle Miguel Servet 26
50008 Zaragoza

Cliente2: Sr. elNombre losApellidos


calle Miguel Servet 26
50008 Zaragoza

Sin embargo, hay que desconfiar de este mecanismo si un miembro de la estructura es un tipo referencia (una
matrizporejemplo),yaqueenestecasolasdosvariablesserepartirnlamismamatriz.

- 28 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Losoperadores

Los operadores son palabras claves del lenguaje que permiten la ejecucin de operaciones sobre el contenido de
ciertos elementos, en general variables, constantes, valores literales o resultados de funciones. La combinacin de
uno o varios operadores y elementos en los cuales los operadores van a apoyarse se llama una expresin. Estas
expresionessevaloranenelmomentodesuejecucin,enfuncindelosoperadoresyvaloresquetienenasociados.

Losoperadoressepuedenrepartirenseiscategoras.

1.Losoperadoresdeasignacin

Elnicooperadordisponibleenestacategoraeseloperador=.Permiteasignarunvaloraunavariable.Elmismo
operadorseutilizaseacualseaeltipodelavariable(numrica,cadenadecaracteres...).

2.Losoperadoresaritmticos

Losoperadoresaritmticospermitenefectuarclculosenelcontenidodelasvariables:

Operador Operacinrealizada Ejemplo Resultado

+ Suma 6+4 10

Resta 126 6

* Multiplicacin 3*4 12

/ Divisin 25/3 8.3333333333

\ Divisinentera 25/3 8

Mod Mdulo(restodeladivisinentera) 25mod3 1

Potencia 53 125

3.Losoperadoresbinarios

Estos operadores solo efectan operaciones sobre enteros (Byte, Short, Integer, Long). Trabajan a nivel de bit
sobrelasvariablesquemanipulan.

Operador Operacinrealizada Ejemplo Resultado

And YBinario 45and255 45

O r OBinario 99or46 111

Xor Oexclusivo 99xor46 77

Not Negacin Not23 24

4.Losoperadoresdecomparacin

Los operadores de comparacin se utilizan en las estructuras de control de una aplicacin (if then, do loop...).
Devuelven un valor de tipo booleano en funcin del resultado de la comparacin efectuada. A continuacin este
valorserutilizadoporlaestructuradecontrol.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Operador Operacinrealizada Ejemplo Resultado

= Igualdad 2=5 False

<> Desigualdad 2<>5 True

< Inferior 2<5 True

> Superior 2>5 False

<= Inferioroigual 2<=5 True

>= Superioroigual 2>=5 False

Like Cadenasdecaracteresiguales "pepe"like"p*" True

Is Comparacindedosvariables O1IsO2 TruesiO1yO2hacenreferenciaal


objeto mismoobjeto

IsNot Comparacindedosvariables O1IsNotO2 TruesiO1nohacereferenciaal


objeto mismoobjetoqueO2

TypeOf...Is... Comparacindeltipodela TypeOfO1IsClient TruesilavariableO1referenciaun


variableconeltipodado objetocreadoapartirdeltipo
Cliente

Algunainformacinadicionalconcernientealoperadorlike:

l Comoeloperador=,likepermiteprobarlaigualdaddedoscadenasdecaracteres,peropermiteademslautilizacin
decaracterescomodn.

l Elcarcter*permitereemplazarcualquiercombinacindecaracteres.Laexpresinapellido like "t*"nospermite


comprobar si la variable apellido contiene un valor que empiece por t y que tenga un nmero cualquiera de
caracteres.

l Elcarcter?permitereemplazaruncarcterdelaexpresinquehayquecomprobar.Paracomprobarsilavariable
apellido contiene un valor que empiece por t y tenga 4 caracteres utilizaremos la siguiente expresin: Apellido
like"t???"

Hayquetenercuidadoconlascomparacionesdecadenasdecaracteres,yaquelosresultadosobtenidospueden
variarenfuncindelasopcioneselegidasenelcompilador.Lasopcionesdelcompiladorpuedenmodificarseenel
cuadrodedilogodepropiedadesdelproyecto.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LapropiedadOption Comparepermiteespecificarelmtododecomparacinutilizadoporelcompilador.

l ConlaopcinText,elcompiladornohardistincinentreminsculasymaysculasenunacomparacin.

l LaopcinBinaryexigirunaestrictaigualdadparaobtenercomoresultadotrue.

5.Losoperadoresdeconcatenacin

Sepuedenutilizardosoperadoresparalaconcatenacindecadenasdecaracteres:+y&.Sinembargo,lafinalidad
del primer operador, +, es la suma de valores numricos. Su funcionamiento es bastante complejo al usarlo con
cadenasdecaracteres.Seaplicanlassiguientesreglas:

l Silosdosoperadoressonnumricos,sesuman.

l SilosdosoperadoressondetipoString,seconcatenan.

l SiunoperadoresnumricoyelotroesdetipoString,entoncesentraenjuegootroparmetro.Sielcompiladorest
configurado con la opcin Strict On, se genera un error de compilacin. Si el compilador est configurado con la
opcin Strict Off, la cadena de caracteres se transforma implcitamente en Double y se suma al otro valor. Si la
cadenadecaracteresnopuedeconvertirseenDouble,segeneraunaexcepcin.

Paraevitartodasestascuestiones,utiliceeloperador&.Conesteoperador,siunodelosdosoperandosnoesde
tipoString,setransformaautomticamenteaestetipoparapoderserconcatenado.

El inconveniente del operador & es que no es muy rpido. Si tiene que realizar muchas concatenaciones en una
cadena,espreferibleutilizarlaclaseStringBuilder.

Ejemplo

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Dim duracion, i As Integer
Dim liebre As String
Dim tortuga As String
Dim principio, fin As Date
principio = Now
For i = 0 To 100000
tortuga = tortuga & " " & i
Next
fin = Now
duracion = DateDiff(DateInterval.Second, principio, fin)
Console.WriteLine("duracin para la tortuga:
{0} segundos", duracion)
principio = Now
Dim sb As New StringBuilder
For i = 0 To 100000
sb.Append(" ")
sb.Append(i)
Next
liebre = sb.ToString
fin = Now
duracion = DateDiff(DateInterval.Second, principio, fin)
Console.WriteLine("duracin para la liebre:
{0} segundos", duracion)
If liebre.Equals(tortuga) Then
Console.WriteLine("las dos cadenas son idnticas")
End If

Resultadodelacarrera:

duracin para la tortuga: 107 segundos


duracin para la liebre: 0 segundos
las dos cadenas son idnticas.

Esteresultadononecesitacomentario!

6.Losoperadoreslgicos

Losoperadoreslgicospermitencombinarlasexpresionesenestructurascondicionalesodebucle.

Operador Operacin Ejemplo Resultado

and yLgico If(test1)And(test2) verdaderositest1ytest2sonverdaderos

O r Olgico If(test1)Or(test2) verdaderositest1otest2esverdadero

x o r Oexclusivo If(test1)Xor(test2) verdaderositest1otest2esverdadero,


perofalsosilosdossonverdaderos
simultneamente

Not Negacin IfNottest Invierteelresultadodeltest

AndAlso yLgico If(test1)AndAlso(test2) demylgicoperotest2soloser


valoradositest1esverdadero

OrElse Olgico If(test1)OrElse(test2) demolgicoperotest2soloser


valoradositest1esfalso

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Conviene tener cuidado con los operadores AndAlso y OrElse, ya que la expresin que testea en segundo lugar
(test2 en este caso) no ser siempre ejecutada. Si esta segunda expresin modifica una variable, esta ser
modificadasoloenlossiguientescasos:

l ElprimertestesverdaderoenelcasodeAndAlso.

l ElprimertestesfalsoenelcasodeOrElse.

7.Ordendeevaluacindelosoperadores

Cuandovariosoperadoressecombinanenunaexpresin,sonvaloradosenunordenmuypreciso.Lasoperaciones
aritmticasseejecutanprimero,luegolasoperacionesdecomparacinyfinalmentelosoperadoreslgicos.

Los operadores aritmticos tambin tienen entre ellos un orden de evaluacin en una expresin. El orden de
evaluacineselsiguiente:

l Potencia()

l Negacin()

l Multiplicacinydivisin(*,/)

l Divisinentera(\)

l Mdulo(Mod)

l Sumayresta(+,),concatenacindecadenas(+)

l Concatenacindecadenas(&)

Sinecesitaunordendeevaluacindiferenteparasuexpresin,coloquelasporcionesquesedebenevaluarprimero
entreparntesis,comoenlasiguienteexpresin:

X= (z * 4) (y * (a + 2))

Ustedpuedeutilizartantosnivelesdeparntesiscomodeseeenunaexpresin.Esimportante,sinembargo,quela
expresincontengatantosparntesisdecierrecomoparntesisdeiniciodelocontrarioelcompiladorgenerarun
error.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Lasestructurasdecontrol

Lasestructurasdecontrolpermitenmodificarelordendeejecucindelasinstruccionesensucdigo.Haydostipos
deestructurasdisponibles:

l Lasestructurasdedecisin:encarrilanlaejecucindelcdigoenfuncindelosvaloresquepodrtenerunaexpresin
detest.

l Lasestructurasdebucle:harnejecutarunaporcindesucdigounciertonmerodeveceshastaquesecumplauna
condicinomientrassecumplaunacondicin.

1.Estructurasdedecisin

Haydossolucionesposibles:

a.EstructuraIf

SepuedenutilizarcuatrotiposdesintaxisparalainstruccinIf.

If condicin then instruccin

Silacondicinescierta,lainstruccinseejecutaenestecaso,condicindebeserunaexpresinquedevuelve
un booleanotrue ofalse. Con esta sintaxis, solo se ejecuta la instruccin situada tras elthen, siempre que la
condicinseaverdadera.

Parapoderejecutarvariasinstruccionesenfuncindeunacondicin,sedebeutilizarlasiguientesintaxis:

If condicin then
Instruccin 1
...
Instruccin n
End if

Enestecaso,silacondicinesverdadera,seejecutarntodaslasinstruccionessituadasentrethenyEnd If.

TambinpuedeespecificarunaovariasinstruccionesdetrsdelElse,quesernejecutadassilacondicinesfalsa.

If condicin then
Instruccin 1
...
Instruccin n
Else
Instruccin 1
...
Instruccin n
End if

Tambinpuedeanidarunaestructuradentrodeotra:

If condicin1 then
Instruccin 1

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
...
Instruccin n
ElseIf Condicin 2 then
Instruccin 1
...
Instruccin n
ElseIf Condicin 3 then
Instruccin 1
...
Instruccin n
Else
Instruccin 1
...
Instruccin n
End if

Enestecaso,comprobamoslaprimeracondicin.Siesverdadera,seejecutaelbloquedecdigocorrespondiente
sino,comprobamoslasiguiente,etc.Sinosecumpleningunacondicin,seejecutaelcdigoqueseencuentra
traselse.Lainstruccinelsenoesobligatoriaenestaestructura.Enesecaso,siningunadelascondicionesse
cumple,noseejecutaningunainstruccin.

b.EstructuraSelectcase

La estructura select case permite un funcionamiento equivalente, pero de una forma ms clara y sencilla. La
sintaxiseslasiguiente:

Select case variable


Case valor1
Bloque de cdigo 1
Case valor2
Bloque de cdigo 2
Case valor3
Bloque de cdigo 3
Case else
Bloque de cdigo 4
End select

El valor de la variable se evala al principio de la estructura (en elSelect case). Despus, se compara el valor
obtenidoconelvalorespecificadoenelprimercase(valor1).

Silosdosvaloressoniguales,seejecutaelbloquedecdigo1ylaejecucindelcdigosiguetraselEnd select.

Sino,elvalorobtenidosecomparaconelvalordelcasesiguientesihaycorrespondencia,elbloquedecdigose
ejecutayassucesivamentehastaelltimocase.

Siningnvalordeloscaseconcuerdaconelobtenidoinicialmente,seejecutaelbloquedecdigodelcase else.

Elvalorquedebecomprobarsepuedeestarcontenidoenunavariable,perotambinpuedeserelresultadodeun
clculo.Enesecaso,elclculoseefectasolounavez,alprincipiodelselect case.Eltipodelvalorcomprobado
puedesernumricoocadenadecaracteres.Porsupuesto,eltipodelavariablecomprobadadebecorresponderal
tipodelosvaloresenlosdiferentescase.

Losvaloresqueesprecisocomprobarenlosdistintoscasepuedenagruparsecomoenelsiguienteejemplo:

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Select case respuesta
Case "si","SI"
console.writeline("respuesta positiva")
Case "no","NO"
Console.writeline("respuesta negativa")
Case else
Console.writeline("respuesta indefinida")
End select

Otambindefinirseenformadeintervaloocomparacin:

Select case hora


Case 8 to 13
Console.writeline("Maana")
Case 14 to 17
Console.writeline("Medioda")
Case 18 to 21
Console.writeline("Tarde")
Case is >=22
Console.writeline("Noche")
Case else
Console.writeline("hora invlida")
End select

Tambinexistentresinstruccionesequivalentesalif then elseoalselect case,peroenunasolainstruccin:

l Lainstrucciniifpermitereemplazarunif then elseconlasintaxissiguiente:

iif (condicin, valor devuelto si verdadero, valor devuelto si falso)

Ejemplo

resultado = iif (respuesta="si", "YES", "NO")

l Lainstruccinswitchpermiteindicarunconjuntodeexpresionesyvaloresasociadosydevuelveelvalorasociadoa
laprimeraexpresinverdadera.

Ejemplo

resultado=switch(respuesta="si","YES",respuesta="no","NO")

l La instruccin choose permite elegir un valor de una lista de parmetros en funcin del valor de un ndice. El
ejemplosiguientenospermiteelegirelIVAenfuncindeuncdigo(de1a4).

Ejemplo

tasaIva = Choose(codigo, 0, 4, 10, 21)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
2.Lasestructurasdebucle

Haycuatroestructurasanuestradisposicin:

While ... End While


Do ... Loop
For ... Next
For Each ... Next

Todastienencomoobjetivoejecutarunbloquedecdigounciertonmerodevecesenfuncindeunacondicin.

a.EstructuraWhile...EndWhile

While condicin
Bloque de cdigo
End While

Esta sintaxis permite ejecutar el bloque de cdigo si la condicin es verdadera. Se evala la condicin incluso
antesdelprimerpasoporelbucle.Porlotanto,elbloquedecdigopodrnoejecutarsenuncasilacondicines
falsadesdeelprincipio.Encasodequeseaverdaderaenlaprimerapasada,elbloquedecdigoseejecutala
condicin se evala, si es de nuevo verdadera, se ejecuta el bloque de cdigo si no, la siguiente instruccin
ejecutada ser la que venga despus de End While. Se puede forzar una salida prematura del bucle con la
instruccinExit While.LaejecucincontinaconlainstruccinsiguientealEnd While.

b.EstructuraDo...Loop

LaestructuraDo Looptienecuatrovariantes:

Do While condicin
Bloque de cdigo
Loop

ElfuncionamientodeestasintaxisesexactamenteigualaldelaestructuraWhileEndWhile.

Do
Bloque de cdigo
Loop While condicin

Esta sintaxis nos permite garantizar que el bloque de cdigo se ejecutar al menos una vez ya que la condicin
sercomprobadaalfinaldelbloquedecdigo.

Lasinstruccionesanterioresrealizanunbuclesiunacondicinesverdadera.Lasdossintaxissiguientesefectan
unbuclemientraslacondicinsiguesiendoverdadera.

Do until condicin
Bloque de cdigo
Loop

Enestecaso,elbucleseejecutahastaquelacondicindejedeserverdadera.Siesverdaderadesdeelprincipio,
elbloquedecdigonoseejecuta.Paragarantizaralmenosunaejecucindelbloquedecdigo,convieneutilizar

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
lasiguientesintaxis,quecompruebalacondicinalfinaldelbloquedecdigo.

Do
Bloque de cdigo
Loop until condicin

Elbloquedecdigoseejecutaalmenosunavez,despuscompruebalacondicin,yvuelveaempezarmientrasla
condicin se cumpla. Como en el caso del bucle while, la instruccin Exit Do provocar una salida anticipada e
incondicionaldelbucle.

c.EstructuraFor...Next

Cuando conoce el nmero de iteraciones que se deben realizar en el bucle, es preferible utilizar la estructura
for ... next.Parapoderutilizarla,esnecesariodeclararenelcdigounavariabledecontadorparaelbucle.

Lasintaxisgeneraleslasiguiente:

For Contador=valor inicial To valor Final


Bloque de cdigo
Next

Alprincipiodelbucle,lavariableContadorseinicializaconelvalor inicial,yseejecutaelcdigo.Lainstruccin
nextincrementalavariableContadoryrealizalacomparacindelvalorobtenidoconelvalorFinaldelbucle.Sila
variable contador es inferior o igual al valorFinal, el bloque de cdigo se ejecuta de nuevo si no, la ejecucin
sigueconlainstruccinsiguienteanext.

Pordefecto,elincrementoesdeunosepuedeespecificarunvalorparaelincrementoaadiendolapalabraclave
stepyelvalordelincremento.Estevalorpuedesernegativo,peroenesecasosedebeindicarunvalor inicial
superioralvalorFinal.

Comoenlasotrasestructuras,sepuedesalirinmediatamentedelbuclefornextutilizandolainstruccinexitfor.

d.EstructuraForeach...next

Otrasintaxisdelbucle for nextquepermiteejecutarunbloquedecdigoparacadaelementodeunamatrizo


coleccin.Lasintaxisgeneraldeestainstruccineslasiguiente:

For each elemento in matriz


Bloque de cdigo
Next

No hay contador en esta estructura, ya que ella misma efecta las iteraciones para todos los elementos de la
matrizocoleccin.

La variable element sirve para extraer los elementos de la matriz o de la coleccin para que el bloque pueda
manipularlo.Eltipodelavariableelementdebesercompatibleconeltipodeelementosalmacenadosenlamatriz
o la coleccin. No debe preocuparse por el nmero de elementos, ya que la instruccin for each es capaz de
gestionareldesplazamientoenlamatrizoenlacoleccin.Acontinuacinsemuestraunejemploparaaclararla
situacin.

Conunbucleclsico:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Dim matriz() As String = {"rojo", "verde", "azul", "blanco"}
Dim cpt As Integer
For cpt = 0 To UBound(matriz)
Console.WriteLine(matriz(cont))
Next

Conelbuclefor each:

Dim matriz() As String = {"rojo", "verde", "azul", "blanco"}


Dim s As String
For Each s In matriz
Console.WriteLine(s)
Next

Como en el caso del bucle for next, puede provocar una salida del bucle antes de haber recorrido toda la matriz
utilizandolainstruccinexitfor.

e.Otrasestructuras

Hayotrasdosestructurasdisponibles,destinadasmsbienasimplificareldesarrollo:

EstructuraUsingEndUsing

Estaestructuraenglobaunbloquedecdigoqueutilizaunrecursoexterno,comoporejemplounaconexinaun
servidordebasededatos.Estaestructuraseencargaautomticamentedeliberarelrecursoalfinaldelbloquede
cdigo. El recurso se puede crear en la estructura o bien existir previamente y pasarse bajo el control de la
estructura.Alfinaldelaestructura,elrecursoseliberallamandoalmtodoDispose.

Ejemplo

Dim ctn As New .SqlConnection


ctn = New SqlConnection("Data Source=TG;Initial Catalog=Northwind;
Integrated Security=True")
Using ctn
...
Uso de la conexin
...
End Using
La conexin se libera

EstructuraWithEndWith

Esta estructura permite ejecutar una serie de operaciones sobre un objeto sin tener que usar cada vez su
nombre.Facilitamucholaclaridaddelcdigoymejoratambinelrendimiento.

Bastaespecificar,conlaayudadelapalabraclave With,elnombredelavariablequequeremosusar,yhastala
palabraclaveEnd Withelnombreestarsobreentendido.Losdiferenteselementosdelobjetoestndisponibles

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
sinusarelnombredelavariablecomoprefijo.

Ejemplo

Dim ctn As New SqlConnection


ctn = New SqlConnection("Data Source=TG;Initial Catalog=Northwind;
Integrated Security=True")
With ctn
.Open()
....
....
.Close()
End With

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Losprocedimientosyfunciones

EnunaaplicacinVisualBasic,todaslasinstruccionesdebenirobligatoriamentedentrodeunprocedimientoodeuna
funcin.Estosprocedimientosofuncionesnospermitencrearbloquesdecdigoqueluegopodrnserllamadosen
otraspartesdelaaplicacin.Lallamadaalprocedimientoofuncinsehacesimplementeutilizandoelidentificadordel
procedimientoofuncin.

Paraquelosprocedimientosseanreutilizablesmsfcilmente,tienelaposibilidaddeusarparmetros.Losvaloresde
estosparmetrosseespecificarnenelmomentodelallamadaalprocedimiento.

Duranteeldesarrollo,nodudeencreardistintosprocedimientosyfunciones.Ladivisindesuaplicacinenmuchos
procedimientosyfuncionesfacilitarladepuracin(esmsfcilcomprobar10bloquesdecdigode15lneascada
unoqueuntochode150 lneas).Adems,ciertosprocedimientospuedenutilizarsevariasvecesenlaaplicacin.

l LosprocedimientosSub,quesimplementeejecutanunbloquedecdigoalserllamadossindevolverunresultado.

l Losprocedimientosdeevento,quesonlosquesonllamadosautomticamentecuandoseproduceuneventoduranteel
funcionamientodelaaplicacin(clicdelratn,pulsacindeunatecla...).

l Lasfuncionesqueejecutanunbloquedecdigoydevuelvenelresultadodesuclculoalcdigoquelasllam.

l Losprocedimientosproperty,quepermitenmanipularlaspropiedadesdelosobjetoscreadosenlaaplicacin.

l Losprocedimientosoperador,utilizadosparamodificarelfuncionamientodeunoperadorcuandoseaplicaaunaclaseo
unaestructura.

Veamosahoracmodeclararprocedimientosyfunciones.

1.ProcedimientoSub

El cdigo de un procedimiento debe estar situado entre las palabras claves Sub y End Sub. Se debe nombrar el
procedimiento.Seutilizarestenombredurantelallamada.Lasintaxisgeneraldedeclaracineslasiguiente:

Sub MuestraResultado()
Instruccin 1
...
console.System.Writeline( "Funciona!!!") ")
...
Instruccin n
End Sub

Losparntesisdespusdelnombreseutilizanparaespecificarlascaractersticasdelosparmetrosquesepasarn
durante la llamada. Los parntesis son obligatorios en la declaracin incluso si no se requiere ningn parmetro
paraelprocedimiento.

Hay muchas palabras claves que se pueden utilizar en la declaracin de un procedimiento para modificar las
posibilidadesdereutilizacindelprocedimiento.Lamayoradeellasestnvinculadasalaprogramacinorientadaa
objetos y se estudiarn en otro captulo. Para modificar su visibilidad, puede utilizar las palabras claves que ya
hemos usado para la declaracin de variables (Private, Public, Friend). Sin especificacin, se considerar un
procedimientopblico.

Para pedir la ejecucin de su procedimiento en el cdigo, basta con especificar su nombre. Otra manera sera
usandolapalabraclaveCall.Lasintaxiseslasiguiente:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Call MuestraResultado()

Sisuprocedimientonoesperaparmetros,lautilizacindelosparntesisesopcional(elentornodedesarrollolos
aadirdetodasformas).

2.Procedimientodeevento

Doselementosdistinguenunprocedimientoclsicodeunprocedimientodeevento:

l Lallamadaalprocedimientoserealizaautomticamentecuandoeleventogeneradoporelprocedimientoseproduce
enlaaplicacin.

l El nombre del procedimiento es la concatenacin del nombre del elemento para el que se gestiona el evento, el
carcter subrayado (_) y el nombre del evento gestionado. Por ejemplo, el siguiente procedimiento se ejecutar
cuandoseproduzcaeleventoclickenelbotnBpOK.

Sub BpOk_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles


Button1.Click

LapalabraclaveHandlesindicaelobjetoyeleventoparaloscualesseejecutarelprocedimiento.

3.Funcin

Unafuncinsedeclarasegnelmismoprincipioqueunprocedimiento:utilizandolaspalabrasclavesFunctionyEnd
Function.Encambio,sedebeproporcionarundatoadicional.Comolafuncindebedevolverunvaloralcdigoque
lallama,debeindicareltipodeestevalor.Lasintaxisdedeclaracines,portanto,lasiguiente:

Function calculo() As Integer


Instruccin 1
...
...
Instruccin n
End Function

Enelcdigodesufuncin,deberespecificarquvalorserdevueltoporsufuncin.Paraello,haydosopciones:

l La utilizacin de la palabra clave Return indicando el valor que quiere devolver. En este caso, Return provoca
inmediatamentelasalidadelafuncin,aunquenosealaltimainstruccin.

l Tambin puede utilizar el nombre de la funcin como variable y asignarle el valor de retorno de la funcin. En este
caso,laejecucindelafuncincontinahastalaltimainstruccin.

Acontinuacinsepuedeutilizarunafuncinenelcdigoenlugardeunvalordelmismotipoqueeldevueltoporla
funcin. Puede igualmente utilizarse como un procedimiento Sub en ese caso simplemente ignoramos el valor
devuelto.

Console.WriteLine(calculo())
calculo()

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
4.ProcedimientosProperty

Los procedimientos Property permiten agregar una propiedad a una clase, un mdulo o una estructura. Estos
procedimientos se denominan, a veces, accesores. Se utilizan cuando se modifica (Set) o se utiliza (Get) la
propiedad.Suusoparecesimilaralusodeunavariablesepuedeasignarunvaloraunapropiedadoleerelvalor
de una propiedad. Sin embargo, existen diferencias abundantes e importantes entre las variables y las
propiedades:

l Las variables necesitan una sola lnea de cdigo para la declaracin, mientras que las propiedades requieren un
bloquedecdigoparaladeclaracin.

l Elaccesoaunavariableseefectadirectamente,mientrasqueelaccesoaunapropiedadimplicalaejecucindeun
fragmentodecdigo.

l El contenido de una variable siempre se recupera tal cual, mientras que el contenido de una propiedad se puede
modificarconelcdigoduranteelaccesoalapropiedad.

Lasintaxisgeneraldecreacindeunapropiedadeslasiguiente:

Property nombrePropiedad () as tipoDeLaPropiedad


Get
...
Return ...
End Get

Set
...
End Set (...)
End Property

Enestadeclaracin:

l nombrePropiedadcorrespondealnombreporelquesepuedemanipularlapropiedadenelcdigo.

l TipoDeLaPropiedadcorrespondealtipodedatosasociadoalapropiedad.Puedeutilizarcualquiertipodedatospara
unapropiedad(lostiposbsicosdellenguajeountipopersonalizado,comoporejemplounaclase).

l ElbloquesituadoentreGetyEnd Getcontieneelcdigoejecutadocuandoseleelapropiedad.

l El bloque situado entre Set y End Set contiene el cdigo ejecutado cuando se asigna la propiedad. El parmetro se
usa,comoenelcasodeunprocedimientoclsico,parapasarinformacinalbloquedecdigo.

ComoparacualquierotroelementodeclaradoenVisualBasic,puedeindicarunniveldeaccesoparalapropiedad.
SeaplicatantoalbloqueGetcomoalSet.Tambinpuedeaadirunmodificadordelniveldeaccesoparacadauno
delosbloquesGetySet.Enestecaso,debensermsrestrictivosqueelindicadoaniveldelapropiedad.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Las propiedades tambin pueden ser de solo lectura o de solo escritura. Para ello, debe aadir ReadOnly o
WriteOnlydelantedelnombredelapropiedad,eliminando,claroest,elbloquedeSetenelcasodeunapropiedad
desololectura,oelbloqueGetenelcasodeunapropiedaddesoloescritura.

5.Losprocedimientosoperador

Este tipo de procedimiento permite redefinir un operador estndar del lenguaje para utilizarlo en tipos
personalizados(claseoestructura).Tomemosunejemploconlaestructuraclienteyautilizada.

Public Structure Cliente


Public Codigo As Integer
Public Apellidos As String
Public Nombre As String
End Structure

Probamoselsiguientecdigo:

Visiblemente,elcompiladornoescooperativoconlaideadesumardosclientes.

Para que este cdigo funcione, debemos indicarle el procedimiento que es preciso seguir para realizar esta
operacin.Porlotanto,debemosredefinireloperador+parautilizarlocondosclientes.

Public Structure Cliente


Public Codigo As Integer
Public Apellidos As String

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Public Nombre As String
Public Shared Operator +(ByVal c1 As Cliente, ByVal c2 As
Cliente) As Cliente
Dim c As Cliente
c.Codigo = c1.Codigo + c2.Codigo
c.Apellidos = c1.Apellidos & c2.Apellidos
c.Nombre = c1.Nombre & c2.Nombre
Return c
End Operator
End Structure

Despusdeestamodificacin,elcompiladorsemuestramscooperativoylaejecucindelprocedimientoanterior,
test,muestraelsiguienteresultado:

325
cliente1cliente2
nombre1nombre2

6.Losargumentosdelosprocedimientosyfunciones

Para que el cdigo sea reutilizable ms fcilmente, los valores manipulados por los procedimientos y funciones
puedenpasarsecomoparmetrosenelmomentodelallamadadelprocedimientoofuncin.Duranteladeclaracin
del procedimiento, deber especificar la lista de los parmetros que se esperar. Esta lista se sita entre los
parntesis de la declaracin del procedimiento. Debe indicar, para cada parmetro, su nombre y su tipo. Si se
esperanvariosparmetros,convienesepararlosconunacoma.

Enelcdigodelprocedimiento,losparmetrosseconsiderancomovariablesdeclaradaslocalmente.

Cuando se llama al procedimiento, se deber indicar un valor para cada uno de los parmetros esperados.
Tomemosunejemplodedeclaracinydeutilizacin:

Function CalculoIVA(PBruto as double, iva as double) as double


CalculoPNeto = PBruto * (1 + (iva / 100))
End function

PBruto = 100
PNeto = CalculoPNeto (PBruto,8)
Console .Writeline (PNeto)

Para pasar una variable como parmetro a un procedimiento (el PBruto del ejemplo anterior), existen dos
posibilidades:

l El paso por valor: en este caso, la informacin transmitida al procedimiento simplemente ser el contenido de la
variablepasadacomoparmetro.ElpasoporvaloreslaopcinpordefectoenVisualBasic.

l Elpasoporreferencia: enestecaso,lainformacintransmitidaalprocedimientoyanoeselcontenidodelavariable,
sinolaubicacindondeestalmacenadalavariable,enlamemoriadelamquina.Elcdigodelprocedimientovaa
buscarelvalorquenecesitaenestaubicacin.Elcdigodelprocedimientopuedetambinmodificarelcontenidodela
variabley,enestecaso,lasmodificacionessernvisiblesenelcdigoquehallamadoalprocedimiento.Parautilizar
este modo de paso, tiene que emplear la palabra clave ByRef delante del parmetro en la declaracin del
procedimiento.

Aunquenoseanecesario,lapalabraclaveByValtambinestdisponibleparaindicarunpasoporvalor.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Puede indicar en la lista de parmetros de un procedimiento que algunos de ellos sern opcionales poniendo la
palabraclaveoptionaldelantedelnombredelparmetro.Losparmetrosopcionalesdebenrespetarciertasreglas:

l Paracadaparmetroopcional,debeestablecerseenladeclaracindelprocedimientounvalorpordefecto.

Function CalculoPNeto(PBruto as double, Optional IVA as double = 21)


as double

l Cuando se declara un parmetro opcional, todos los declarados a continuacin deben ser tambin
opcionales.Ladeclaracinsiguientenoesvlida,yaqueeltercerparmetrodebeseropcional:

Function CalculoPNeto(PBruto as double, Optional IVA as double =


21 divisa as string) as double

Lasintaxiseslasiguiente:

Function CalculoPNeto(PBruto as double, Optional IVA as double =


21, optional divisa as string = "") as double

Cuandosellamaalprocedimiento,haydosposibilidadesparaindicarelvalorutilizadoporcadaparmetro:

l Elpaseporposicin:losvaloresdelosparmetrosdebenaparecerenelmismoordenquehansidodeclaradosenel
procedimiento.Siquiereomitirunvalorparaunparmetro,debereservarsusitioenlallamadadelprocedimiento.

Resultado=calculoPNeto(250,,"$")

l Elpasopornombre:enestecaso,sedebeindicarenlallamadaelnombredecadaparmetroysuvalor.Elordende
losparmetrosnoesimportante,peroestobligadoaindicarunvalorparalosparmetrosnoopcionales.

Resultado=calculoPNeto(divisa := "$",PBruto := 250)

Otraposibilidadpermitecrearunprocedimientoquepodrrecibirunnmerocualquieradeparmetros.Indiquela
palabraclaveParamArrayparadeclararunamatrizdeparmetros.

Enelsiguienteejemplo,vamosacrearunafuncinquecalculalamediadetodoslosparmetrosquerecibe.

Function media(ByVal ParamArray notas() As Double) As Double


Dim nota As Double
Dim suma As Double
For Each nota In notas
suma = suma + nota
Next
media = suma / notas.Length
End Function

Luegosepuedellamarlafuncinconunnmerocualquieradeparmetros.

Resultado=media(1,6,23,45)

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Resultado=media(12,78)

7.Funcionesasncronas

Las funciones asncronas permiten mejorar la reactividad de una aplicacin. Es frecuente tener que realizar
operaciones relativamente largas en una aplicacin. Con un modelo de desarrollo clsico, el conjunto de
modificaciones se bloquea hasta que terminan las operaciones, Esta situacin afecta al usuario, ya que este no
sabe realmente lo que hace la aplicacin. Si desea parar la aplicacin durante este periodo de bloqueo, la nica
opcin que tiene es utilizar el administrador de tareas de Windows. Para evitar esta situacin, ahora es posible
definir funciones asncronas. La palabra clave async aadida a la firma de una funcin provoca su ejecucin de
maneraasncrona.Paraqueestemecanismosearealmenteeficaz,ademsesnecesarioindicar,dentrodeestetipo
de funciones, al menos una ubicacin donde la ejecucin de la funcin se podr suspender a la espera de que
termine una operacin. La palabra clave await delante de una expresin indica estos puntos de interrupcin.
Cuando la operacin termina, se evala la expresin y se retoma la ejecucin de la funcin. Para que este
mecanismofuncione,esnecesarioquelaexpresingenereuntipoTask<...>.

Veamosalgunosejemplosprcticos.Partimosdeunafuncinquecompruebasiunnmeroesprimoono:

Public Function esPrimo (nb As Integer) As Boolean


If nb < 2 Then
Return False
End If
If nb = 2 Then
Return True
End If
If nb Mod 2 = 0 Then

Return False
End If
Dim i As Integer
i = 3
Do While (i * i <= nb)
If nb Mod i = 0 Then
Return False
Else
i = i + 1
End If
Loop
Return True
End Function

Esta funcin no tiene nada de especial, excepto que puede llegar a necesitar mucho tiempo de ejecucin si se le
pasacomoargumentounenteroconunvalormuyelevado.Estefenmenoseamplificar,contodaseguridad,sise
llamavariasveces.Esloquevamosaresaltarconlasiguienteaplicacin,quepermitebuscarlosnmerosprimos
entre0yunvalorconcreto.

Vamos a aadir una nueva funcin que cuente cuntos nmeros primos hay entre 0 y el valor que recibe como
argumento.

Public Function contarPrimos(maxi As Integer) As Integer


Dim i As Integer

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Dim nb As Integer
nb = 0
For i = 0 To maxi
If esPrimo(i) Then
nb = nb + 1
End If
next
Return nb
End Function

SolofaltaaadirunmtodoMainparaterminarnuestraaplicacin.

Public Sub Main()


Console.Write("Indique el valor mximo para el clculo: ")
Dim maxi As Integer
maxi = Console.ReadLine()
Dim resultado As Integer
resultado = contarPrimos(maxi)
Console.WriteLine(resultado)
Console.ReadKey()
End Sub

Ahoracomprobemosqueestofuncionacorrectamente.

Nohayningnproblemayobtenemosrpidamenteelresultado.Sinembargo,silointentamosconunlmitemucho
mselevado(100.000.000porejemplo),habrquesermuypacienteporquelosclculossernmuylargos.Sino
tienepacienciaparaesperarelresultado,debesalirdelaaplicacincerrandolaconsoladirectamenteoatravsdel
administrador de tareas de Windows. Esta solucin no es muy limpia. Podemos mejorarla proponiendo al usuario
unamaneraparafinalizarlaejecucindelaaplicacin.

Para esto, podemos aadir en nuestro mtodo Main un simple bucle Do While en el que realizamos nuestro
tratamientoysolicitamosalusuarioqueintroduzcauncarctersparaterminarlaaplicacin.

Public Sub Main()


Console.Write("Indique el valor mximo para el clculo: ")

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim maxi As Integer
maxi = Console.ReadLine()
Dim resultado As Integer
Dim respuesta As Char
Do
resultado = contarPrimos (maxi)
Console.WriteLine(resultado)
reponse = Console.ReadKey().KeyChar
Loop While (respuesta <> "s")
End Sub

Durantelapruebanohayningunamejora.Dehecho,lasinstruccionespresentesenelbucledo whileseejecutan
de manera secuencial y en este caso la instruccin respuesta = Console.ReadKey().KeyChar solo se
ejecutar despus de haber mostrado el resultado, es decir, la final del clculo. La funcin contarPrimos sigue
estandobloqueada,nohaynadaquesepuedaejecutarenlaaplicacinhastaquetermine.Lasolucinconsisteen
transformarlafuncincontarPrimosenunafuncinasncrona.Paraello,bastaconaadirlapalabraclaveasyncen
sufirma.

public static async int contarPrimos(int maxi)

Aadirestapalabraclaveimplicaotramodificacinenlafirma.

Portanto,esnecesariomodificarlafuncinparaquedevuelvauntipoTask(Of Integer).

Public Async Function contarPrimos(maxi As Integer) As Task(Of Integer)

Ahoranuestrafuncinsepuedeconvertirenunafuncinasncrona,perotodavanoloes.Estoesloquenosindica
VisualStudio.

La operacin que hay que realizar en la funcin asncrona se debe pasar como argumento, como una expresin
lambda,almtodoRundelaclaseTask.Eselresultadodelaejecucindeestaexpresinlambdalaqueseutiliza
comovalorderetornodelafuncinasncrona.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Public Async Function contarPrimos (maxi As Integer) As Task(Of Integer)
Dim resultado As Integer
resultado = Await Task.Run(Of Integer)(Function()

Dim i As Integer
Dim nb As Integer
nb = 0
For i = 0 To maxi
If esPrimo (i) Then
nb = nb + 1
End If
Next
Return nb
End Function)
Return resultado
End Function

Lapenltimaetapaconsisteenusarestafuncindemaneraasncrona.Paraestovamosacrearunafuncinnueva
que va a llamar a la funcin contarPrimos. Para que la funcin contarPrimos se ejecute de manera asncrona,
tenemosqueutilizarlapalabraclaveawaitdurantesullamada.

Async Function operacion(maxi As Integer) As Task(Of Integer)


Dim resultado As Integer
resultado = Await contarPrimos (maxi)
Console.WriteLine(resultado)
Console.WriteLine("*****************")
End Function

Paraterminar,modificamoslafuncinMainparainterrumpirelclculo.

Public Sub Main()


Dim maxi As Integer
Console.Write("Indique el valor mximo para el clculo: ")
maxi = Console.ReadLine()
operacion(maxi)
Console.WriteLine("pulse un tecla para detener la aplicacin
antes de terminar el clculo ")
Console.ReadKey()
End Sub

VisualStudionosindicaunaanomaladurantelallamadadelafuncinoperacin.

Estewarningnotieneconsecuenciasparaelfuncionamientodenuestraaplicacinyademseselobjetivodetodas
estasoperaciones.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Ensamblados,espaciosdenombresyatributos

1.Losensamblados

Visual Basic est concebido en torno al Framework .NET, lo que le permite beneficiarse de numerosas ventajas,
sobretodoencuandoaseguridad,enelmomentodelaejecucinydelagestindememoria.Estarelacintambin
permite asegurar la compatibilidad entre el cdigo escrito en los distintos lenguajes disponibles. As es posible
utilizarenVisualBasicelementoscreadosenotroslenguajes(yalrevs),demaneratotalmentetransparente,sin
tenerquepreocuparsedellenguajeconelquesehadesarrollado elelemento.

El elemento bsico de esta reutilizacin en el Framework .NET es el ensamblado. Se puede considerar como la
agrupacindetipos,recursosyfuncionalidadesdiseadosparafuncionarjuntos.

Los ensamblados se almacenan en archivos .exe o .dll segn el tipo. Se generan simplemente al compilar el
proyectocorrespondiente.

Sonautodescriptivos,yaquecontienenlosdatosnecesariosparasuutilizacinenotroproyecto.Estosdatosestn
contenidosenelmanifiestodelensamblado.Elmanifiestocontieneentreotrascosas:

l Laidentidaddelensamblado(sunombreysuversin).

l Una lista de archivos utilizados por el ensamblado (por ejemplo, los otros ensamblados utilizados por este, los
recursosbitmap,etc.).

Para poder utilizar un ensamblado en un proyecto, aada simplemente una referencia hacia el ensamblado. Para
ello,utiliceelmencontextualdelacarpetadereferenciadelproyecto.

Elsiguientecuadrodedilogopermiteentonceselegirlasreferenciasquedeseamosaadiralproyecto.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Lasdiferentesopcionespermitenelegir,segnlacategora,eltipodereferenciaquequeremosagregaralproyecto:

Ensamblados

ElconjuntodeloscomponentesdelFramework.NETydesusextensionesdisponibles.

Solucin

Losotrosproyectosdelasolucinactual.

COM

LoscomponentesCOMyActiveXregistradosenelsistema.

Examinar

Bsquedadeunarchivo(dll,ocx...)quecontienelosrecursos.

Reciente

Muestralasreferenciasaadidasrecientemente.

Es posible aadir varias referencias de manera simultnea utilizando la tecla [Ctrl] durante la seleccin en este
cuadrodedilogo.

Despus de haber realizado estas dos operaciones, los recursos presentes en el ensamblado son accesibles
directamenteenelcdigodelproyecto.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
2.Losespaciosdenombres

Losespaciosdenombresorganizandemaneralgicalosobjetosdisponiblesenunensamblado.Seutilizanpara
resolver las ambigedades cuando, en un proyecto, se aaden referencias en unos ensamblados que contienen
elementosconnombresidnticos.

Por ejemplo, la clase ListBox existe en los ensamblados System.Web y System.Windows.Forms. Si se aaden
referenciasenunproyectohaciaestosensamblados,elcompiladorsearriesgaanopoderdeterminarculdeestas
clasesdesearealmenteutilizar.

La utilizacin del nombre plenamente cualificado, incluyendo el espacio de nombres en el cual se define la clase,
permiteresolverestetipodeproblema.

Puedeutilizar,porejemplo,elsiguientecdigo:

Ejemplo

Dim listaWindows As System.Windows.Forms.ListBox


Dim listaWeb As System.Web.UI.WebControls.ListBox.

Sinembargo,lautilizacindelnombreplenamentecualificadopuedehacerpesadalaescrituradelcdigo.Sepuede
utilizar la palabra clave imports para aligerar el cdigo. Indica al compilador que ciertos espacios de nombres se
sobreentienden.

Por ejemplo, la instruccin Imports System.Data.SqlClient autoriza la utilizacin de la siguiente declaracin: Dim
ctn As SqlConnection,quesinlaimportacindelespaciodenombreshabraprovocadounerrordecompilacin:

LasinstruccionesImportsdebenserlasprimeraslneasdecdigoenunarchivofuenteVisualBasic.

Sinembargo,estatentoparanovolveracaerenelproblemaanterior.

La instruccin Imports propone una solucin elegante creando un alias durante la importacin del espacio de
nombres.

Imports ctrlWin = System.Windows.Forms


Imports ctrlWeb = System.Web.UI.WebControls
Module TestConta
Dim listaWindows As ctrlWin.ListBox
Dim listaWeb As ctrlWeb.ListBox

Estasolucinautorizalautilizacindenombresdeunalongitudrazonableevitandolosconflictos.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Cabe observar tambin que, segn el tipo de proyecto en el que est trabajando, se realizan referencias e
importacionespordefecto.

Puede repasar estas referencias y modificarlas si fuera necesario visualizando las propiedades del proyecto
medianteelmencontextualdisponibleenelexploradordesoluciones.

Lasimportacionespordefectosernactivadasencadamdulodesuproyecto.

LosespaciosdenombressedeclararnenelcdigoconlaayudadelaspalabrasclavesNamespaceyEnd Namespace.

Todosloselementosdeclaradosentreestasdospalabrasclavessernaccesiblesutilizandoelnombredelespacio
denombrescomoprefijo.

Namespace Facturacion
Public Class Tarificacion
Public Shared Function calculoPNeto(PBruto As Decimal, tasaIva As Decimal)
As Decimal
Return PBruto * (1 + tasaIva / 100)
End Function
End Class
End Namespace

Enelejemploanterior,lafuncincalculoPNetodefinidaenlaclaseTarificacionesaccesiblealdarleunprefijocon
elnombredelespaciodenombres.Elnombredelespaciodenombresrazespecificadodeberagregarseanivelde
laspropiedadesdelproyecto,separndolodelosotrosnombresdeespaciodenombresporunpunto.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Ennuestroejemplo,lafuncincalculoPnetoesaccesibleconelsiguientecdigo:

Sub Main()
precioNeto = Conta.Facturacion.Tarificacion.calculoPNeto(100, 8)
End Sub

Utilicelamismatcnicaenelcasodeunespaciodenombresanidados,comoenelsiguienteejemplo:

Namespace Gestion
Namespace Pago
Public Class Sueldo
....
End Class
End Namespace
Namespace Facturacion
Public Class Factura
....
End Class
End Namespace

End Namespace

LaclaseSueldoseraccesibleconelnombreConta.Gestion.Pago.Sueldo.

3.Losatributos

Losatributossonmarcasquepuedecolocarensucdigoconelfindeaadirdatosadicionalesaloselementosde

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
suaplicacin.

Seguardanenlosmetadatosdelensambladodurantelacompilacindelproyecto.Elruntimeutilizalosmetadatos
paragestionarladepuracin,elseguimientodelasversiones,lacompilacinyotrosdatosrelativosalautilizacin
desucdigo.Losatributospuedenaplicarseaunensamblado,unmduloounaporcindecdigomspequea,
comounprocedimientoounafuncin.Avecespodrnaceptarargumentosparamodificarsusignificado.

Los atributos se sitan en el cdigo entre los smbolos < y >, como las etiquetas HTML. Si se utilizan varios
atributos, deben ir separados con comas. Los posibles parmetros de un atributo estarn ubicados entre
parntesis.

El alcance de un atributo tambin puede extenderse con las palabras claves Assembly: o Module: ubicadas antes
delatributo.Lasintaxisdeutilizacindeunatributoes,porlotanto:

<[Assembly o Module:] Atributo1([parmetro1,parmetro2]),Atributo2

a.LosatributosmscomunesenVisualBasic

Entrelosatributosdisponibles,algunosseusanconmuchafrecuenciaeneldesarrolloconVisualBasic.Vamosa
estudiarsuutilizacineilustrarlaconunejemplo.

VBFixedStringAttribute

Este atributo fuerza la creacin de una variable de tipo cadena de caracteres de tamao fijo. Se utiliza en la
declaracindeunaestructura,usadaparaguardarenunarchivolneasdetamaoconstante.

Ejemplo

Structure Cliente
<VBFixedString(15)> public nombre as String
<VBFixedString(15)> public apellidos as String
End Structure

ComClassAttribute

Esteatributopidealcompiladorlageneracindecdigoadicionalparahacercompatibleunaclaseconelmodelo
COM. De esta manera, la clase ser compatible con antiguos lenguajes de programacin incompatibles con la
plataforma.NET.

Ejemplo

<ComClass()> Public Class Impuestos

Public Sub New()


MyBase.New()
End Sub

Function CalculoImpuestos(ByVal sueldo As Integer)


Return sueldo * 0.3
End Function

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Class

Paracompilarestecdigo,esnecesarioactivarlaopcinaniveldepropiedadesdelproyectoRegistrarparaCom
Interop.

Despus de la compilacin, la clase puede utilizarse en un lenguaje compatible COM, referenciando la biblioteca
DLLgenerada.

LafigurasiguientemuestraelusodesdeVB6.0.

SerializableAttribute,NonSerializedAttribute

Estosdosatributoscontrolanlaserializacindeunaclaseydesusmiembros.Laserializacinpermiteelregistro
deunainstanciadeclaseenunarchivoasegurandoaslapersistenciadelosdatos.Elarchivogeneradopuede
estar en formato binario o XML en este caso, facilita el intercambio de datos entre aplicaciones. Para que una
claseseautilizableporelmecanismodeserializacin,estadebemarcarseconelatributoSerializableAttribute.
Durante la operacin de serializacin, el contenido de cada uno de los miembros de la instancia de la clase se
guarda en el archivo. Si algunos de ellos no deben guardarse en el archivo, se deben marcar con el atributo
NonSerializedAttribute.

ElejemplosiguientedefinelaclasePersonacondosmiembros(ApellidosyNombre)quesernserializadosyun
miembro(Edad)quenoserserializado.Secreaunainstanciadelaclaseyseguardaenunarchivodeformato
XML.

Ejemplo

Imports System
Imports System.IO
Imports System.Runtime.Serialization
Imports System.Runtime.Serialization.Formatters.Soap

<Serializable()> Public Class Persona


Public Nombre As String
Public Apellidos As String
<NonSerialized()> Public Edad As Integer

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Public Sub New()
End Sub
End Class
Module test
Public Sub Main()
Dim UnaPersona As New Persona()
UnaPersona.Nombre = "Pablo"
UnaPersona.Apellidos = "Garca"
UnaPersona.Edad = 25
Dim stream As Stream = File.Open("datos.xml", FileMode.Create)
Dim formatear As New SoapFormatter()
formatear.Serialize(stream, UnaPersona)
stream.Close()
End Sub
End Module

LaejecucindeestecdigogeneraelsiguientearchivoXML:

<SOAP-ENV:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:


xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.
org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope
" xmlns:clr="http://schemas.microsoft.com/soap/encoding/clr/1.0" SOAP-ENV:
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<SOAP-ENV:Body>
<a1:Persona id="ref-1" xmlns:a1="http://schemas.microsoft.com/clr/nsassem/
serializable/serializable%2C%20Version%3D1.0.0.0%2C%20Culture%
3Dneutral%2C%20
PublicKeyToken%3Dnull">
<Nombre id="ref-3">Pablo</Nombre>
<Apellidos id="ref-4">Garca</Apellidos>
</a1:Persona>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

EncontramosenelarchivonuestrainstanciadelaclasePersonaconsusdosmiembros,NombreyApellidos,y,taly
comohabamosindicadoenladefinicindelaclase,elmiembroEdadnosehaguardado.

DllImportAttribute

Se utiliza este atributo para indicar que una funcin se importa desde una biblioteca de cdigo no gestionado.
Permiteenparticularlautilizacindefuncionesdefinidasenunabibliotecadelsistema.Enelsiguienteejemplo,la
funcinMoveFilesepuedeutilizarcomounafuncinclsica.

Ejemplo

<DllImport("KERNEL32.DLL")>Public Function MoveFile(ByVal src As String,


ByVal dst As String) As Boolean
End Function

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Obsolete

Sepuedeutilizaresteatributoparaindicarqueunelemento,clase,mtodoopropiedadyanoseutiliza.Siapesar
de todo se utiliza este elemento en una aplicacin, el compilador genera un aviso o un error en funcin de la
configuracin del atributo. Una cadena de caracteres puede ser pasada como parmetro a este atributo para
representarelmensajevisualizadoporelcompilador.Unsegundoparmetrodetipobooleanopermiteespecificar
silautilizacindelelementomarcadoconesteatributogeneraunavisoounerrordecompilacin.

<Obsolete("Este mtodo ya no se utiliza", False)>


Public Sub Guardar()
Dim unaPersona As Persona
unaPersona = New Persona()
unaPersona.apellido = "Garca"
unaPersona.elnombre = "Pablo"
unaPersona.edad = 25
Dim flux As Stream
flux = File.Open("c:\datos.xml", FileMode.Create)
Dim formador As SoapFormatter
formador = New SoapFormatter()
formador.Serialize(flux, unaPersona)
flux.Close()
End Sub

Lautilizacindeestemtodoenunaaplicacinprovocaelsiguienteavisodurantelacompilacin.

Si este atributo viene definido con un segundo parmetro igual a True, el compilador activa un error cuando se
utilizaelelemento.

<Obsolete("Esta propiedad no debe ser utilizada ms", True)>


Property Apellido As String
Get
Return _Apellido
End Get
Set(ByVal value As String)
_Apellido = value
End Set
End Property

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Introduccin

ConVisualBasic.NET,lanocindeobjetoesomnipresenteyrequiereunmnimodeaprendizaje.Vamosaverprimero
el principio de la programacin orientada a objetos y el vocabulario asociado, luego veremos cmo ponerlo en
aplicacinconVisualBasic.

En un lenguaje de procedimiento clsico, el funcionamiento de una aplicacin est organizado por una sucesin de
llamadasalosdiferentesprocedimientosyfuncionesdisponiblesenelcdigo.Nohayningnvnculoentrelosdatosy
losprocedimientosquelosmanipulan.Alcontrario,enestelenguajeorientadoaobjetos,vamosintentaragruparal
mximolosdatosyelcdigoparamanipularlos.Lasclasessonlarepresentacinsimblicadelosobjetos.Describen
los campos, propiedades, mtodos y eventos de la misma manera que el plano de un arquitecto describe las
diferentespartesdeunedificio.

Prosigamos nuestra analoga entre una clase y un plano de un edificio. Sabemos que es posible construir varios
edificiosapartirdelmismoplano.Delamismamanera,variosobjetospuedenserconstruidosapartirdelamisma
clase.Sepuedeutilizarunaclaseparacreartantasinstanciascomoseanecesario.

Enelplanodeunedificio,algunaszonaspuedentenerunaccesolimitadoaciertaspersonas.Delamismamanera,
enunaclase,ciertoselementospuedentenerunaccesorestringido.Eselprincipiodelaencapsulacin.

Lostrminosclaseyobjetoamenudoseconfunden,perosetrataenrealidaddeelementosmuydistintos.Unaclase
representalaestructuradeunelemento,mientrasqueelobjetoesunejemplarcreadoapartirdelaplantilladeesta
estructura.Lamodificacindeunelementoenunobjetonocambiaenabsolutolosotrosobjetoscreadosapartirde
lamismaplantilla(clase).Ennuestroejemplodeplanodeunedificio,elhechodeaadirunanuevahabitacinaun
edificio existente no cambia para nada los otros edificios construidos segn el mismo plano. Por el contrario, la
modificacindelplano(delaclase)conllevamodificacionesentodoslosnuevosedificios(todoslosnuevosobjetos).

Las clases estn constituidas por campos, propiedades, mtodos y eventos. Los campos y las propiedades
representan los datos contenidos en los objetos. Los campos se consideran como variables, y es posible leer su
contenido o directamente asignarles un valor. Por ejemplo, si tiene una clase que representa un cliente, puede
guardarsunombreenuncampo.

Las propiedades se manipulan de la misma manera que los campos, pero se activan desde los procedimientos de
propiedadGetySet.Estootorgamscontrolsobrecmoleeroasignarvaloresypermitelavalidacindelosdatos
antesdesuutilizacin.

Losmtodosrepresentanlasaccionesqueunobjetopuedeasignar.Seaplicancreandoprocedimientosofunciones
enunaclase.

Loseventossondatosqueunobjetorecibeotransmitedesdeohaciaotroobjetooaplicacin.Loseventospermiten
alosobjetosejecutaraccionescuandounasituacinparticularseverifica.ComoWindowsesunsistemaoperativode
eventos,loseventospuedenprocederdeotrosobjetos,delsistemaodelasaccionesdelusuariosobreelratnyel
teclado.

Estoessolounafacetadelaprogramacinorientadaaobjetos.Tambinsonfundamentalesotrostreselementos:

l Laencapsulacin.

l Laherencia.

l Elpolimorfismo.

Laencapsulacineslacapacidaddecrearycontrolarelaccesoaungrupodeelementos.Lasclasesfacilitanelmedio
ms fiable para asegurar la encapsulacin. Si tomamos el ejemplo de una cuenta bancaria, en una programacin
clsicanecesitaremosmuchasvariablesyprocedimientosofuncionesparamanipularlosdatos.Lasituacinseraaun

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
ms compleja si tuviramos que gestionar de manera simultnea varias cuentas bancarias. Habra que trabajar
entoncesconmatricesyhacermalabarismosconlosndices.Laencapsulacinpermiteagruparlosdatosyelcdigo
manipulndolosenunaclase.Sidebetrabajarconvariascuentasbancariasdemanerasimultnea,entoncestendr
variasinstanciasdelamismaclase,limitandoaselriesgodeerrores.Laencapsulacinaseguratambinuncontrol
sobre la utilizacin de datos y procedimientos o funciones. Puede utilizar los modificadores de acceso, tales como
PrivateoProtected,pararestringirelaccesoaciertosmtodos,propiedadesocampos.Unareglafundamentaldela
encapsulacin estipula que los datos de una clase solo deben ser manipulados por el cdigo de la clase
(procedimientos de propiedades o mtodos). A veces esta tcnica se llama disimulacin de datos. Asegura la
seguridaddefuncionamientodesucdigoalenmascararlosdetallesinternosdelaclase,evitandoasqueseutilicen
de manera inadecuada. Autoriza tambin la modificacin de una parte del cdigo sin alterar el funcionamiento del
restodelaaplicacin.

La herencia permite la creacin de una nueva clase, basada en una clase existente. La clase que sirve de plantilla
paralacreacindeotraclasesellamaclasebase.Laclaseascreadaheredadeloscampos,propiedades,mtodosy
eventos de la clase base. La nueva clase puede personalizarse al agregarle campos, propiedades, mtodos y
eventos. Las clases creadas a partir de una clase base se llaman clases derivadas. As se puede definir una clase
baseyreutilizarlavariasvecesparacrearclasesderivadas.

Elpolimorfismoesotranocinimportantedelaprogramacinorientadaaobjetos.Graciasaello,esposibleutilizar
variasclasesdemaneraintercambiableinclusosiestasclasesimplementansuspropiedadesymtodosdemanera
diferente.Estaspropiedadesymtodossepuedenusarconelmismonombre,sinimportarlaclaseapartirdelacual
sehaconstruidoelobjeto.

Existen otros tres conceptos igualmente asociados al polimorfismo. La sobrecarga, la sustitucin y la ocultacin de
miembros permiten la definicin de miembros de una clase con el mismo nombre. Sin embargo, existen algunas
diferenciasentreestastrestcnicas.

Seutilizalasobrecargaparadisearpropiedadesomtodosquellevanelmismonombreperoquetienenunnmero
deparmetrosdiferentesotiposdeparmetrosdiferentes.

La sustitucin permite la redefinicin de mtodos o propiedades heredadas de una clase base. Los miembros
sustituidospuedenaceptarelmismonmeroytipodeparmetrosqueelmtodoopropiedaddelaclasebase.

La ocultacin sirve para sustituir localmente, en una clase, un miembro de una clase. Cualquier tipo de miembro
puedeocultarotromiembro.Porejemplo,unapropiedadpuedeocultarunmtodoheredado.Laocultacinsehace
nicamenteatravsdelnombre.Losmiembrosocultadosnosonheredables.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
AplicacinconVisualBasic
En este captulo, vamos a trabajar con la clasePersona, cuya representacin UML (Unified Modeling Language) est
disponibleacontinuacin.

UMLesunlenguajegrficodedicadoalarepresentacindelosconceptosdeprogramacinorientadaaobjetos.Para
msinformacinsobreestelenguaje,puedeconsultarellibroUML2Iniciacin,ejemplosyejercicioscorregidos,de
lamismacoleccin.

1.Creacindeunaclase

Lacreacindeunaclasepasaporladeclaracindelapropiaclaseydetodosloselementosquelaconstituyen.

a.Declaracindelaclase

LadeclaracindeunaclaseserealizautilizandolaspalabrasclavesClassyEnd Class.Entreestasdospalabras
claves,seencuentranlasdeclaracionesdevariables,quesernloscamposdelaclase,ylosprocedimientos,que
sernlosmtodosdelaclase.

Portanto,lasintaxisgeneraldedefinicindeunaclaseeslasiguiente:

[ Public | Private | Protected | Friend | Protected Friend ]


[ MustInherit | NotInheritable ]
Class nombre de la clase
[ Inherits nombre de la clase base]
[ Implements nombre de la interfaz]

End Class

Hay muchas palabras claves que permiten personalizar una clase. En el momento de su declaracin, se puede
especificarlavisibilidaddelaclase.Sepuedenutilizarlassiguientespalabrasclaves:

Public

Sepodrutilizarlaclaseentodosuproyecto,perotambinenotrosproyectos.

Friend

Elaccesoalaclaseestlimitadoalproyectoenelqueestdefinida.

Private

Solosepuedeutilizarlaclaseenelmduloenelqueestdefinida.

Protected

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Solosepuedeutilizarlaclaseenunasubclasedelaclaseenlaqueestdefinida.Estapalabraclave
solosepuedeutilizarenunaclasedefinidadentrodeotraclase.

Protected Friend

Idnticaalaunindelosmbitosdeprotectedyfriend.

Tambinpudeindicarcmosuclasesevaacomportarconrespetoalaherencia.Dosopcionessonposibles:

MustInherit

Indicaquelaclasesirvedeclasebaseenunarelacindeherencia.Nosepuedencrearinstanciasde
estaclase.Engeneral,enestetipodeclase,solosedefinenlasdeclaracionesdelosmtodos.Har
faltaescribirenlasclasesderivadaselcontenidodeestosmtodos.

NotInheritable

Estaclaseserlaltimadelajerarqua.Porlotantonoserposibleutilizarestaclasecomo
superclasedeotraclase.

Paraindicarquesuclaserecuperalascaractersticasdeotraclasemedianteunarelacindeherencia,debeusar
lapalabraclaveInheritsseguidaporelnombredelaclasebase.Tambinpuedeimplementarensuclaseunao
variasinterfaces.Msadelanteenestecaptulo,severnendetalleestasdosnociones.

ElprincipiodeladeclaracindenuestraclasePersonaes,portanto,elsiguiente:

Public Class Persona


Dim apellidos As String
Dim nombre As String
Dim fecha_naci As Date
End Class

b.Claseparcial

La definicin de una clase puede repartirse entre mltiples declaraciones usando la palabra clavePartial. Esta
tcnicaautorizaladefinicindelaclaseenvariosarchivosfuentes.SeutilizamuchoenVisualStudioparapermitir
la personalizacin automtica de las clases generadas. El cdigo generado se almacena generalmente en un
archivoconextensin.designer.vbque,enprincipio,nodebemodificarsedirectamente.Durantelacompilacin,el
compilador agrupa todas las definiciones parciales para obtener el cdigo fuente de la clase. En cambio, las
diferentespartesdeladefinicindeunaclasedebenestarenelmismoproyectoyformarpartedelmismoespacio
denombres.

Tambinexisteunapequeatrampaquehayquetenerencuenta.Observeelcdigosiguiente:

Namespace Contab
Partial Public Class Persona
Public Sub procedure1()
End Sub
End Class
Module Module1

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Partial Public Class Persona
Public Sub Procedure2()
End Sub
End Class
End Module
End Namespace

Aprimeravista,nadailegalyaqueelcompiladorgeneracorrectamenteelcdigo.Peronotienelamismavisinde
lascosasquenosotros.Miremosloquenospresentalavistadeclases.

HaydosclasesPersonaenelexplorador.Elcompiladorhaconsideradoquenuestrasdosdefinicionesdeclaseno
sonpartedelmismoespaciodenombres.Enefecto,unadeellasestsituadadentrodelmdulo,yelnombrede
esteseaadeautomticamentecomoprefijodelaclase.

c.Creacindepropiedades

Se pueden crear variables simples para almacenar los datos de su clase, pero los procedimientos de propiedad
proporcionan ms flexibilidad y control sobre el almacenamiento de los datos en una clase. Permiten a la clase
protegeryvalidarsuspropiosdatos.UnprocedimientodepropiedadsedefineentrelaspalabrasclavesProperty
yEnd Property.Entreestasdospalabrasclaves,sedefinendosbloquesdecdigoconlaayudadelaspalabras
claves Get, End Get y Set End Set. El bloque de cdigo Get se ejecuta durante la lectura de la propiedad y el
bloquedecdigoSetseejecutadurantelaasignacindeunvaloralapropiedad.

NuestraclasePersonasepuedemejorardelasiguientemanera:

Public Class Persona


Private elApellido As String
Private elNombre As String
Private laFecha_naci As Date
Public Property apellido() As String

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Get
Return elApellido
End Get
Set(ByVal Value As String)
elApellido = Value
End Set
End Property

Public Property nombre() As String


Get
Return elNombre
End Get
Set(ByVal Value As String)
elNombre = Value
End Set
End Property

Public Property fecha_naci() As Date


Get
Return laFecha_naci
End Get
Set(ByVal Value As Date)
laFecha_naci = Value
End Set
End Property
End Class

La creacin de las propiedades permite ahora acceder de manera indirecta a los campos de la clase. Podemos
permitirnosmodificarlavisibilidaddeloscamposdelaclaseyconvertirlosenprivados.Dehechoserecomienda
esta prctica para respetar el principio de encapsulacin. As tenemos la posibilidad de ser ms exigentes en
cuantoalosdatosregistradosennuestraclase.Vamosaponerenprcticaalgunasdelassiguientesreglasde
gestin:

l Elapellidosealmacenarenmaysculas.

l Elnombresealmacenarenminsculas.

l Lafechadenacimientonoserinferiora1900.

Losprocedimientosdepropiedadseencarganacontinuacindelaaplicacindeestasreglas.

Property apellido() As String


Get
Return elApellido
End Get

Set(ByVal Value As String)


elApellido = UCase(Value)
End Set
End Property

Property nombre() As String


Get

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Return elNombre
End Get

Set(ByVal Value As String)


elNombre = LCase(Value)
End Set
End Property

Property fecha_naci() As Date


Get
Return laFecha_naci
End Get

Set(ByVal Value As Date)


If Value.Year >= 1900 Then
laFecha_naci = Value
End If
End Set
End Property

Se puede observar que los procedimientos de propiedad tienen un acceso completo a los campos de la clase,
inclusolosdeclaradosprivados.

Sololecturaysoloescritura

Avecespuedeserinteresanterestringirlosposiblesaccesosaunapropiedad.Sepuedendefinircomosololectura
o como solo escritura. Para indicar su intencin, al configurar la propiedad tiene que utilizar las palabras clave
ReadOnlyoWriteOnly.

ElbloquedecdigoGetsedebeomitirparaunapropiedaddesoloescritura.Paraunapropiedaddesololectura,
se tiene que omitir el bloque de cdigo Set. Para insertar todo esto en la aplicacin, vamos a aadir a la clase
Persona una propiedad Contrasea en solo escritura y una propiedad Edad en solo lectura. La edad se puede
deducirdirectamentedelafechadenacimientoylacontraseanodebeseraccesiblealalecturadesdeelexterior
delaclase.

ReadOnly Property edad() As Long


Get
Return DateDiff(DateInterval.Year, fecha_naci, Now())
End Get
End Property
WriteOnly Property contrasea() as String
Set (ByVal Value As String)
laContrasea=value
End Set
End Property

Propiedadpordefecto

Lapropiedadpordefectodeunaclaseeslapropiedadqueseusacuandonoseindicaningunapropiedadespecial
paraunobjeto.Engeneral,setratadelapropiedaddeclasemsutilizada.Permiteteneruncdigomsbreve,

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
evitandolarepeticinfrecuentedelmismonombredepropiedad.

Sinembargo,lapropiedadpordefectodeberespetaralgunasrestricciones:

l Debeaceptaralmenosunparmetro.

l Nopuedeserprivadaocompartida.

l Silapropiedadpordefectoesunapropiedadsobrecargada,entonceselrestodelaspropiedadessobrecargadascon
elmismonombredebenserpropiedadespordefecto.

l No puede haber ms de una propiedad por defecto en una clase. Esta regla se aplica tambin a las propiedades
heredadas.

l Siunapropiedadpredeterminadadeunaclasebaseseocultapormediodeunapropiedadquenoeslapropiedad
predeterminada de una subclase, entonces a la propiedad predeterminada de la clase base siempre se puede
accederatravsdelnombredelobjeto.

Apliquemos este principio aadiendo a la clase Persona la lista de hijos de esta persona y definiendo esta
propiedadcomopropiedadpordefecto.

ElcdigodenuestraclasePersonaseconvierteportantoen:

Public Class Persona


Private elApellido As String
Private elNombre As String
Private laFecha_naci As Date
Private laContrasea As String
Private losHijos(9) As Persona
Property apellido() As String
Get
Return elApellido
End Get

Set(ByVal Value As String)


elApellido = UCase(Value)
End Set
End Property

Property nombre() As String


Get
Return elNombre
End Get

Set(ByVal Value As String)


elNombre = LCase(Value)
End Set
End Property

Property fecha_naci() As Date


Get
Return laFecha_naci
End Get

Set(ByVal Value As Date)


If Value.Year >= 1900 Then

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
laFecha_naci = (Value)
End If
End Set
End Property
ReadOnly Property age() As Long
Get
Return DateDiff(DateInterval.Year, Fecha_naci, Now())
End Get
End Property
WriteOnly Property Contrasea() As String
Set(ByVal Value As String)
LaContrasea = value
End Set
End Property
Default Public Property hijo(ByVal index As Integer) As Persona
Get
Return losHijos(index)
End Get
Set(ByVal value As Persona)
losHijos(index) = value
End Set
End Property
End Class

CabeobservarquetenemoslaobligacindecrearunnuevocampoenlaclasePersonaconelfindeasegurarel
almacenamientodelalistadeloshijos.Demomento,estecampoestconstituidoporunamatrizdepersona,pero
podra ser sustituido de manera ventajosa por una estructura de gestin ms flexible, como por ejemplo una
coleccin.Lapropiedad hijorecibeporparmetrounndicequepermiteespecificarelhijoconelquedeseamos
trabajar.

Elsiguientecdigonospermiteprobarelcorrectofuncionamientodenuestraclase:

Module Principal
Sub Main()
Dim p As New Persona
Dim hijo1 As New Persona
Dim hijo2 As New Persona
p.nombre = "Pablo"
p.apellido = "Garca"
p.fecha_naci = #12/23/1954#
hijo1.nombre = "Carlos"
hijo1.apellido = "Garca"
hijo1.fecha_naci = #10/5/1979#
tambin podemos utilizar el apellido del padre para
inicializar el apellido del hijo
hijo2.nombre = "Marcos"
hijo2.apellido = p.apellido
hijo2.fecha_naci = #4/18/1982#
podemos asignar un hijo a una persona utilizando
la propiedad hijo
p.hijo(0) = hijo1
como es tambin la propiedad por defecto de la clase
podemos utilizar la siguiente sintaxis

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
p(1) = hijo2
comprobemos que nuestros datos son correctos
Console.WriteLine("Sr {0} {1} nacido el {2} tiene 2 hijos",
p.nombre, p.apellido, p.fecha_naci)
Console.WriteLine("{0} {1} que tiene {2} aos", p(0).nombre,
p(0.apellido, p(0).edad)
Console.WriteLine("{0} {1} que tiene {2} aos", p(1).nombre,
(1).apellido, p(1).edad)
Console.WriteLine("pulse una tecla para salir")
Console.ReadLine()
End Sub
End Module

Obtenemosenlaconsolaelsiguienteresultado:

Sr Pablo GARCA nacido el 23/12/1954 00:00:00 tiene 2 hijos

Carlos GARCA que tiene 26 aos

Marcos GARCA que tiene 23 aos

Pulse una tecla para salir.

Podemos aprovechar para verificar que se tiene en cuenta nuestras reglas relativas al apellido y al nombre: el
apellidoestenmaysculas,elnombreestenminsculas.

Propiedadesautoimplementadas

Almenudosucedequeseutilizaunapropiedadconelnicofindehaceraccesibleunavariableinternadesdeel
exteriordeunaclase.ElcdigodeestapropiedadselimitaaunsimpleReturnenelbloquedecdigoGetyauna
simpleasignacinenelbloquedecdigoSet.

Private elNumero As Integer


Public Property numero As Integer
Get
Return elNumero
End Get
Set(ByVal value As Integer)
elNumero = value
End Set
End Property

Enestecaso,sepuededeclararlapropiedadconlasiguientesintaxissimplificada.

Public Property numero As Integer

El compilador genera automticamente una variable interna de la clase que lleva un nombre similar al de la
propiedad,peroquevaprecedidaporelsigno_(underscore).LosbloquesGetySetdelapropiedadefectanun
simpleReturnyunaasignacin.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Estavariableimplcitaesaccesibledesdelaclasecomounavariabledeclaradaexplcitamente.

Tambinsepuedeinicializarlapropiedaddurantesudeclaracin,comosehaceconunavariable.

Public Property numero As Integer = -1

Sinembargo,seaplicaunapequealimitacinaestatcnica,yaquenopermitelacreacindepropiedadescon
parmetros,nitampocolacreacindepropiedadesensololecturaosoloescritura.

d.Creacindemtodos

Losmtodossonprocedimientosofuncionesdefinidosenelinteriordeunaclase.Suelenutilizarseparamanipular
los campos y los propiedades de la clase. Para poder utizar un mtodo, basta con usar el nombre del mtodo
poniendocomoprefijoelnombredelobjetoenelquequierellamarelmtodo.

AadimosalaclasePersonalafuncinCalcula_edad()yelprocedimientoMostrarinsertandoelsiguientecdigo:

Public Function Calcula_edad() As Integer


Return DateDiff(DateInterval.Year, fecha_naci, Now())
End Function
Public Sub mostrar()
Console.Write("Sr {0} {1} nacido el {2}", elNombre, elApellido, fecha_naci)
End Sub

Conviene destacar que en estas lneas de cdigo podemos manipular los campos de la clase incluso si son
declaradosprivados,yaqueestamosenelinteriordelaclase.Tambinesposibleaccederalosdatosdelaclase
utilizandolaspropiedades.Enestecasoseaplicarnlasreglasdegestinrelativasalapellidoyalnombre.

Podemosmodificarnuestrocdigodepruebaparautilizarelprocedimientoylafuncinaadidosalaclase.

p.mostrar()
Console.WriteLine(" tiene 2 hijos")
Console.WriteLine("{0} {1} que tiene {2} aos", p(0).nombre, p(0).apellido,
p(0).Calcula_edad)
Console.WriteLine("{0} {1} que tiene {2} aos", p(1).nombre, p(1).apellido,
p(1).Calcula_edad)
Console.WriteLine("pulse una tecla para salir")
Console.ReadLine()

Sobrecargademtodo

Lasobrecargademtodoeslacreacin,dentrodeunaclase,demtodosquetienenunnombreidnticoperoun
nmerodeparmetrosotiposdeparmetrosdiferentes.Estonospermiteconservarunnombrecoherentepara
diferentesmtodosquetienenelmismoobjetivoperoquepresentanalgunosdetallesdiferentes.Lossiguientes
parmetrosnosetienenencuentaparadistinguirdosmtodossobrecargados:

l Elnombredelosparmetros.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
l Eltipodedevolucindeunafuncin.

l LosmodificadoresByValoByRefaplicadosalosparmetrosdelmtodo.

PodemosporejemplosobrecargarelmtodomostrardelaclasePersonaparatenerencuentaelidiomaenelcual
sedebemostrar.Elparmetroesperadoporelprocedimientopermiteelegirelidioma.

Public overloads Sub mostrar(ByVal idioma As String)


Select Case idioma
Case "es"
Console.Write("Sr {0} {1} nacido el {2}", elApellido, elNombre,
Fecha_naci)
Case "en"
Console.Write("Mr {0} {1} was born the {2}", elApellido, elNombre,
fecha_naci)
End Select
End Sub

Lapalabraclaveoverloadsesopcionaldurantelasobrecargadeunmtododentrodeunaclase.Sinembargo,si
seespecificaparaunmtodosobrecargado,sedebeespecificarparatodoslosotros.

Losmtodosheredadosdeotrasclasestambinsepuedensobrecargar.Conviene,porlotanto,tenercuidado,en
este caso, con la utilizacin o no utilizacin de la palabra clave overloads. Si no se utiliza para la sobrecarga,
entoncestodaslasotrassobrecargasdelaclasebaseserninaccesibles.Alrevs,siseutiliza,todoslosmtodos
sobrecargadosestarndisponibles.Parailustrartodoesto,vamosaimaginarquetenemosunaclaseAsalariado
que hereda de la clasePersona. Veremos un poco ms adelante cmo realizar esta herencia. En nuestra clase
Asalariado,podemossobrecargarelmtodoMostrar().Sinoutilizamoslapalabraclaveoverloads,VisualStudio
nosavisadeunposibleproblema,relativoalainaccesibilidaddelosmtodosMostrar()delaclasebase.

Si,porelcontrario,seutilizalapalabraoverloads,podemosteneraccesodesdelaclase Asalariadoatodoslos
mtodossobrecargados,inclusolosqueestndefinidosenlaclasePersona.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Sustitucindemtodo

Las clases derivadas heredan propiedades y mtodos de su clase base. Los puede reutilizar a partir de una
subclasesinningunamodificacin.Alrevs,sielfuncionamientodeestapropiedadomtodonoseadaptaala
nuevaclase,tienelaposibilidaddesustituirlaporunanuevaimplementacindelaclasederivada.Enestecaso,
hay que usar la palabra clave overrides a la hora de realizar la sustitucin en la clase derivada. Tambin es
imperativo que la clase base haya autorizado esta sustitucin con el uso de la palabra clave Overridable. Sin
indicacinparticular,nosepuedesustituirunmtodoounapropiedad.Engeneral,seutilizalasustitucinpara
asegurarelpolimorfismoentreclases.Porsupuesto,losmtodossustituidosdebentenerelmismonombre,pero
tambinelmismonmeroytipodeparmetrosquelosmtodosdelaclasebasealaquesustituyen.Aspodemos
sustituirenlaclaseAsalariadoelmtodoMostrar.

Public Overrides Sub mostrar()


Console.Write("Sr {0} {1} nacido el {2} gana {3} euros al mes",
nombre, apellido, fecha_naci, Salario)
End Sub

Con esta declaracin, el mtodo Mostrar de la clase Persona ya no es visible para los usuarios de la clase
Asalariado. Solo el mtodo Mostrar de la clase Asalariado es accesible. Sin embargo, el cdigo del mtodo
MostrardelaclaseAsalariadopuedeporlomenosteneraccesoaestemtodoutilizandolapalabraclaveMybase.
Porlotanto,hubiramospodidoescribirparaelmtodoMostrardelaclaseAsalariado:

Public Overrides Sub mostrar()


Llamada del mtodo mostrar de la clase Persona
MyBase.mostrar()
Aadir funcionalidades especficas a la clase Asalariado
Console.WriteLine("gana {0} euros al mes", salario)
End Sub

Encuantounmtodosedeclarasustituibleenunaclase,loserparatodassussubclasesseacualseaelgrado
de parentesco (clase hija, nieta...). Se puede utilizar la palabra clave NotOverridable para bloquear esta
funcionalidadapartirdeundeterminadonivel.Porejemplo,enlaclaseAsalariadohubiramospodidoescribir:

Public NotOverridable Overrides Sub mostrar()


MyBase.mostrar()
Console.WriteLine("gana {0} euros al mes", salario)
End Sub

Estasintaxiscancela,paralassubclasesdelaclaseAsalariado,laautorizacindesustitucinquelaclasePersona
habaestablecido.SiintentamossustituirestemtodoenunaclaseJefequeheredadeAsalariado,obtenemosel
siguientemensaje:

A la inversa, podemos exigir que una clase heredada sustituya un mtodo definido en una clase base. Este

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
mtodo debe estar marcado con la palabra claveMustOverride. Para este tipo de mtodo, no es necesario que
hayaimplementacin,sinosimplementesudefinicin.

Public MustOverride Function estado_civil() As String

Este tipo de mtodo se llama a veces mtodo abstracto. Exige que la clase en la que se define est tambin
marcadacomoabstractaconlapalabraclaveMustInherit.

Ocultacindemtodo

Cuandoelementosdeunprogramacompartenelmismonombre,unodeellospuedeocultarelotro.Entalcaso,el
elementoocultadoyanoesaccesibleyelcompiladorutilizaensulugarelelementoquelooculta.Laocultacin
puede hacerse entre elementos de tipo diferente. Solo se utiliza el nombre del elemento para asegurar la
ocultacin. Cuando se oculta, conviene utilizar la palabra clave Shadows delante del nombre del miembro que
garantiza la operacin. Podemos, por ejemplo, ocultar el mtodo Mostrar en una clase derivada de la clase
Persona.

Public Shadows Sub mostrar()

End Sub

A partir de ahora, para esta clase solo existe un elemento llamado Mostrar. Todo lo que pueda existir como
elemento,enlaclaseolasclasesbasedeestaclaseyquesellamemostrar,estocultoeinaccesible.

Estatcnicasedebeutilizarconprecaucin,yaque,enfuncindelaubicacindondeseencuentraunainstruccin,
elmismonombrepuedehacerreferenciaaelementosdenaturalezadiferente.

Mtodoparcial

Se utilizan los mtodos parciales para permitirnos personalizar el cdigo de una clase parcial generada por una
herramienta de Visual Studio. Se emplean principalmente para dar una notificacin de cambio. La herramienta
genera nicamente el esqueleto del mtodo y lo llama cuando la notificacin debe producirse. El usuario de la
clasepuedesiesprecisodefinirsupropiaversindelmtodoy,enestecaso,estaserllamadaenlugardela
generadaautomticamente.VeamoscmopodemosaplicarestoenlaclasePersona.Primerodebemosdefinirla
clasecomosifueraunaclaseparcialyluegopreverenelinteriordelaclaseunmtodoparcialquerespetelas
siguientesreglas:

l Elmtododebeserunprocedimiento,ynounafuncin.

l Elcuerpodelmtododebeestarvaco.

l Elmtododebeserprivado.

Partial Public Class Persona


Private elNombre As String
Private elApellido As String
Private laFecha_naci As Date

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Partial Private Sub apellidoChanged()
End Sub

Public Property apellido() As String


Get
Return elApellido
End Get
Set(ByVal Value As String)
elApellido = Value
apellidoChanged ()
End Set
End Property
...
...
End Class

Ahora nos falta personalizar esta clase en otro archivo fuente y probar el resultado. Para ello, en un mdulo,
agregueelsiguientecdigo:

Partial Class Persona


Private Sub apellidoChanged()
Console.WriteLine("se ha asignado un nuevo apellido")
End Sub
End Class

Module Module1
Public Sub main()
Dim p As Persona
p = New Persona
p.apellido = "Garca"
Console.WriteLine(p.apellido)
Console.ReadLine()
End Sub
End Module

Alejecutarlo,tenemoselsiguienteresultado:

Se ha asignado un nuevo apellido


Garca

Setrataenefectodenuestraversindelmtodo apellidoChangedqueacabadeejecutarsey,sinembargo,no
hemostocadoelcdigooriginaldelaclasePersona.

Mtododeextensin

Los mtodos de extensin permiten agregar funcionalidades a una clase ya definida sin tener que modificar el
cdigodeestaclase.Seescribensimplementeenmdulosysoninvocadosexactamentedelamismaformaque
losmtodosdisponiblesenlaclase.Sinembargo,sedebenrespetaralgunasreglas:

l Puedenserdetipoprocedimientoofuncin,peronodetipopropiedad.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
l Debenestarmarcadosconelatributo<Extension()>.

l Eltipodelprimerparmetrodelmtododeterminaeltipoextendidoporestemtodo.

l En el momento de la ejecucin, este primer parmetro representa la instancia de la clase en la que se llama el
mtodo.

Enelejemplosiguiente,aadimosunmtodoalaclasePersona.

Module Module1
<Extension()> Public Sub mostrar(ByVal p As Persona)
Console.WriteLine("nombre: {0}", p.nombre)
Console.WriteLine("apellido: {0}", p.apellido)
Console.WriteLine("fecha de nacimiento: {0}", p.fecha_naci)
End Sub

Public Sub main()


Dim p As Persona
p = New Persona
p.nombre = "pablo"
p.apellido = "garca"
p.fecha_naci = #6/7/1955#
p.mostrar()
Console.ReadLine()
End Sub
End Module

LosmtodosextendidostambinpuedenserdefinidosparalostiposdebasedelFramework, comoporejemplola
claseString.ElsiguientecdigoagregaalaclaseStringunmtodoquepermiteconvertirelprimercarcterdeuna
cadenaamaysculas.

<Extension()> Public Function FirstToUpper(ByVal s As String) As String


If IsNothing(s) OrElse s.Length = 0 Then
Return s
ElseIf s.Length = 1 Then
Return s.ToUpper
Else
Return s.Substring(0, 1).ToUpper & s.Substring(1, s.Length - 1)
End If
End Function

SidefinimosahoraunavariabledeltipoString,nuestronuevomtodoestardisponibleyaparecerenlalistade
IntelliSense.

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Observeeliconodistintoutilizadoparadiferenciarunmtododeextensindeunmtodonormaldelaclase.

e.Constructoresydestructores

Los constructores son mtodos particulares de una clase por diferentes aspectos. El constructor de una clase
siempresellamaNew.Enelmomentodecrearunainstanciadeclase,nuncasellamaexplcitamenteelconstructor
enelcdigo,sinoqueselellamademaneraimplcita.Comoparaunmtodoclsico,unconstructorpuedeesperar
parmetros.Elconstructordeunaclasequenoesperaparmetrosesdesignadocomoelconstructorpordefecto
delaclase.Elpapeldelconstructorconsisteprincipalmenteenlainicializacindeloscamposdeunainstanciade
clase.Losconstructorestambinpuedensersobrecargados,pero,enestecaso,nosepuedeutilizarlapalabra
claveoverloads.

AadamosunosconstructoresalaclasePersona.

Public Sub New()


elApellido = ""
elNombre = ""
laContrasea = ""
End Sub
Public Sub New(ByVal apellido As String, ByVal nombre As String, ByVal pwd
As String)
elApellido = apellido
elNombre = nombre
laContrasea = pwd
End Sub

Cuando creamos una clase derivada, tambin puede disponer de sus propios constructores. Si aadimos en la
clasederivadaunconstructorpordefecto,debemosseguiralgunasreglas:

l Sienlaclasebaseexisteunconstructorsobrecargado,debemosllamarexplcitamenteelconstructorpordefectode
laclasebaseenelconstructorpordefectodelaclasederivada.

l Sienlaclasebasesoloexisteelconstructorpordefecto,sullamadaestimplcitaenelconstructorpordefectode
laclasederivada.

l Ennuestrocaso,elconstructorpordefectodelaclaseAsalariadodeberatenerlasiguienteforma:

Public Sub New()


MyBase.New()
elSalario = 0
End Sub

La lnea MyBase.New() provoca la llamada implcita al constructor de la clase Persona. Esta lnea debe ser
obligatoriamentelaprimeradelconstructor.

Los destructores son otros mtodos particulares de una clase. Como los constructores, se llaman de manera
implcitaperonicamenteduranteladestruccindeunainstanciadeclase.Lafirmadeldestructorseimpone.Este
mtodo debe ser protected, debe llamarse finalize y no debe recibir ningn parmetro. Debido a esta firma
impuesta, solo puede haber un nico destructor por clase, y por lo tanto no es posible la sobrecarga de los
destructores.

Ladeclaracindeundestructoresentonceslasiguiente:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Protected Overrides Sub finalize()

End Sub

Lapalabraclaveoverridesesobligatoria,yaqueeldestructorsustituyealdestructorheredadodelaclaseObject.
Elcdigopresenteeneldestructordebepermitirlaliberacindelosrecursosutilizadosporlaclase.Porejemplo,
sepuedeencontrarenellacdigoquecierraunarchivoabiertoporlaclaseoelcierredeunaconexinhaciaun
servidordebasededatos.

Veremosendetalle,enlaseccinUtilizacindeunaclase Destruccindeunainstancia,lascircunstanciasenlas
quesellamaaldestructor.

f.Miembroscompartidos

Los miembros compartidos son campos, propiedades o mtodos que son accesibles por todas las instancias de
unaclase.Sehablatambin,enalgunoslenguajes,demiembrosestticos.

Sonmuytilesalahoradegestionar,enunaclase,datosquenosonespecficosdeunainstanciadeclase,sino
delapropiaclase.Poroposicinalosmiembrosdeinstancia,paralosqueexisteunejemplarporinstanciadela
clase, los miembros compartidos existen en un ejemplar nico. La modificacin del valor de un miembro de
instanciasolomodificaelvalorparaestainstanciadeclase,mientrasquelamodificacindelvalordeunmiembro
compartido modifica el valor para todas las instancias de la clase. Los miembros compartidos son asimilables a
variables globales en una aplicacin. Se pueden usar en el cdigo haciendo referencia a ellos gracias a una
instanciadelaclaseoatravsdelnombredelaclase.

Observequeenestecasoelcompiladornoencuentraestecomportamientolgicoyprovocaunavisoenlalnea
de cdigo correspondiente. Siempre es preferible utilizar el nombre de clase para acceder a un miembro
compartido.

Losmtodoscompartidossiguenlasmismasreglasypuedenservirparacrearbibliotecasdefunciones.Elejemplo
clsicoeslaclaseMath,enlaquesedefinennumerosasfuncionescompartidas.Losmtodoscompartidosposeen
sinembargounalimitacin,yaquesolopuedenutilizarvariableslocalesuotrosmiembroscompartidosdelaclase.
Nuncadebenutilizarmiembrosdeinstanciadeunaclase,yaqueesposiblequeel mtodoseautilizadosinque
existaunainstanciadelaclase.Elcompiladorverificarestetipodeerror.

Los miembros compartidos se deben declarar con la palabra clave Shared. Tambin puede especificar una
visibilidad, tal y como lo hace con cualquier otro miembro de una clase. Sin embargo, una variable local de un
procedimientoofuncinnosepuedecompartir.

2.Utilizacindeunaclase

Lautilizacindeunaclaseenunaaplicacinpasapordosetapas.

l Ladeclaracindeunavariablequepermiteelaccesoalobjeto.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
l Lacreacindelobjeto.

Enalgunoscasos,estasdosetapassepuedenomitir,yaqueelmismoVisualBasiclasrealizaporssolo.Sehabla
entoncesdeobjetosintrnsecos.Eselcaso,porejemplo,delobjetoMy.

a.Creacindeunainstancia

Las variables objeto son variables de tipo referencia. Difieren de las variables clsicas por el hecho de que la
variablenocontienedirectamentedatos,sinounareferenciaalaubicacinenlamemoriadelamquinadondese
encuentran los datos. Como todas las variables, se deben declarar antes de su utilizacin. La declaracin se
realizadelamismamaneraqueunavariableclsica(Integeruotra).

Dim p as Persona

Despus de esta etapa, la variable existe pero no hace referencia a una ubicacin vlida. Contiene el valor
Nothing.

La segunda etapa consiste realmente en crear la instancia de la clase. Para ello, se utiliza la palabra claveNew.
Esperacomoparmetroelnombredelaclaseparalaqueestencargadodecrearunainstancia.EloperadorNew
presenta una peticin al sistema para obtener la memoria necesaria para almacenar la instancia de la clase y
despusinicialavariableconestadireccindememoria.Luegosellamaalconstructordelaclaseparainicializarla
nuevainstanciacreada.

p = New Persona

Lasdosoperacionessepuedencombinarenunasolalnea.

Dim p as New Persona

Enestecaso,sellamaalconstructorpordefecto.Parautilizarotroconstructor,sedebeespecificarunalistade
parmetros y en funcin del nmero y del tipo de parmetros el operador New llamar al constructor
correspondiente.

Dim p as New Persona("Pablo","Garca",#12/24/1953#)

b.Inicializacindeunainstancia

Despus de haber creado una instancia de la clase, puede inicializar los miembros de esta utilizando las
propiedadesdelaclase.Esposiblecombinarestasdosetapasenunasola.Paraello,durantelacreacindela
instancia, debemos facilitar una lista de propiedades y valores que han de asignarse a estas propiedades. A
continuacintenemoslasintaxisexactaquesedebeutilizar:

Dim p as Persona
p = new Persona With {.nombre = Pablo, .apellido = Garca}

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
Nohaylimitacinenelnmerodepropiedadesinicializadasnienelordendeaparicindelaspropiedadesenla
listadeinicializacin.Estanicalneadecdigoeselequivalentealasiguientesintaxis,menoscondensadayms
tradicional:

Dim p As Persona
p = New Persona
With p
.nombre = Pablo
.apellido = Garca
End With

c.Destruccindeunainstancia

Ladestruccindeunainstanciadeclaseesautomticaenunaaplicacin.ElCommonLanguageRuntimevigilaa
intervalosregularesquetodaslasinstanciasdeclases,creadasenlaaplicacin,seantodavaaccesibles.Esdecir,
todava existe en la aplicacin una variable o una propiedad que permite el acceso a esta instancia. Si no se
encuentraningnmediodeaccederaestainstancia,entonceselobjetoesmarcadocomohurfano.Cuandolas
reservasdememoriadelaaplicacinsehacenmuydbiles,elGarbage Collector(recolectordebasura)interviene
yeliminalosobjetoshurfanos.Duranteestaeliminacinescuandosellamaalosdestructoresdecadaunode
los objetos. No existe manera de precipitar las cosas pidiendo la eliminacin inmediata de la memoria de una
instanciaparticulardeclase.Estasituacinavecesesproblemtica,cuandoelobjetoutilizaunrecursoexterno,
como,porejemplo,unaconexinhaciaunservidordebasededatos.Sielcierredelaconexinestprevistoenel
destructor de la clase, puede pasar mucho tiempo entre el momento en que el objeto se hace inaccesible y el
momentoenquesellamaaldestructor.

Parapaliaresteproblema,esposibleponerenmarchaotrasolucin.Elcdigoencargadodelaliberacindelos
recursosestubicadoenotromtodo,yestemtodosellamademaneraexplcitaenelcdigo.Estemtodose
suelellamarDispose.Paraasegurarsedequelosrecursosestnefectivamenteliberados,tambinpuedeprever
unallamadaaestemtodoeneldestructordelaclase.

Entoncespuedesurgirotroproblema:sielmtodofuellamadoexplcitamenteenelcdigodelaaplicacin,loser
de nuevo, de manera implcita, cuando el Garbage Collector entre en accin. Por lo tanto, conviene hacer de tal
maneraqueelcdigodeestemtodoDisposepuedaserejecutadodosvecessincausarerrores.Tambinpuede
indicaralGarbageCollectorquenodebeejecutareldestructordeestainstanciadeclase.Paraello,enelmtodo
Dispose,debeavisarledequeeltrabajodelimpiezayaestrealizadollamandoalmtodoSuppressFinalize.El
cdigodelmtodoDisposeydeldestructordebetenerlasiguienteforma:

Public Sub Dispose()


insertar el cdigo encargado de la liberacin de recursos

Indica al Garbage Collector que no debe llamar al destructor
GC.SuppressFinalize(Me)
End Sub
Protected Overrides Sub finalize()
Dispose()
End Sub

Una ltima solucin consiste en pedirle al Garbage Collector que entre en accin inmediatamente llamando al
mtodocollect.

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
GC.Collect()

Sinembargo,noserecomiendausarestasolucin,porqueconsumemuchosrecursosdelsistemaoperativopara,
aveces,recuperarsolounospocoscentenaresdebytesenmemoria.

d.Enlacetardo,enlaceprecoz

El compilador Visual Basic realiza una operacin llamada enlace cuando asigna un objeto a una variable. Este
enlace se llama precoz cuando se crea la variable a partir de una clase especfica. Esta funcionalidad permite al
compiladorefectuaroptimizacionesenelcdigogenerado.Laasignacindeunobjetotambinsepuederealizara
unavariabledetipoObject.Estetipodevariableescapazdereferenciaracualquierotrotipodeclase.Eneste
caso,elenlacesellamatardo,yaqueeltiporealdelobjetosoloserdescubiertoenelmomentodelaejecucin
de la aplicacin. Se debe evitar esta tcnica, ya que genera un cdigo menos eficaz y sobre todo no permite
beneficiarsedelacompilacinautomticadelcdigoeneleditornitampocodelaayudadinmica.Efectivamente,
enestecasoVisualBasicnopuededeterminareltiporealdelobjetomanipulado.

Sin embargo, algunas funciones devuelven un tipo Object, pero para poder manipularlo conviene tomar algunas
precauciones.LaprimerasolucinconsisteenutilizarsolomiembrosdelaclaseObjectconelobjetodevueltopor
lafuncin.Estasolucinesrelativamentelimitadaencuantoalasfuncionalidadesdisponibles.

Lasegundasolucinconsisteenasignaraunavariabledeuntipoparticularelvalordevueltoporlafuncin.Esta
solucinpermiteutilizartodaslasfuncionalidadesdelobjetodevueltoporlafuncin.Sinembargo,hayqueestar
seguro de que el objeto devuelto es realmente una instancia de la clase que se desea manipular. De hecho, el
compiladorseencargarderecordrnoslo.

Por lo tanto, debemos asegurarnos del tipo del objeto devuelto y pedir explcitamente la converson de tipo.
Podemosobtenerelnombredeltipodelobjetoyefectuarunacomparacindecadenadecaracteres.

Dim hijo As Persona


If TypeName(p.getHijo(0)).Equals("Persona") Then
hijo = CType(p.getHijo(0), Persona)
End If

Estasolucinfunciona,perocomportaelriesgodeescribirmalelnombredelaclasedurantelacomparacin.El
operadorTypeOf ... Is ...esmsadecuadoparaestasituacin.

Dim hijo As Persona


If TypeOf p.getHijo(0) Is Persona Then
hijo = CType(p.getHijo(0), Persona)
End If

Observequelaconversindetiponocambiaeltipodelobjetoenmemoria,simplementepermiteverlodeforma
temporaldeotramanera.SiporejemplotenemosenmemoriaunainstanciadelaclaseAsalariado,laconversin
detiponospermiteverlacomounObject,unaPersona o unAsalariadoperoseguirsiendounainstanciadela

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 19 -
claseAsalariado.

3.Herencia

Laherenciaesunapotentefuncionalidaddeunlenguajeorientadoaobjetos,peroavecespuedesermalutilizada.
Se pueden utilizar dos tipos de relaciones entre dos clases. Podemos tener la relacin es una especie dey la
relacin concierne a un.Se debe considerar la relacin de herencia cuando la relacin es una especie dese
puedeaplicarentredosclases.Tomemosunejemplocontresclases:Persona,Cliente,Pedido.

Probemoslasrelacionesparacadaunadelasclases.

1.Unpedidoesunaespeciedecliente.

2.Unpedidoesunaespeciedepersona.

3.Unclienteesunaespeciedepedido.

4.Unclienteesunaespeciedepersona.

5.Unapersonaesunaespeciedecliente.

6.Unapersonaesunaespeciedepedido.

Entretodoslosintentos,solounonosparecelgico:unclienteesunaespeciedepersona.Porlotanto,podemos
considerarunarelacindeherenciaentreestasdosclases.Lautilizacinesmuysencillaaniveldelcdigo,yaque
enladeclaracindelaclaseessuficienteespecificarlapalabraclaveInheritsseguidaporelnombredelaclasede
laquesedeseaheredar.PuestoqueVisualBasicnoaceptalaherenciamltiple,noesposibleespecificarmsdeun
nombredeclasebase.

Public Class Cliente


Inherits Persona
Private elCodigo As Integer
Public Property codigo() As Integer
Get
Return elCodigo
End Get
Set(ByVal value As Integer)
elCodigo = value
End Set
End Property
End Class

La clase se puede utilizar despus y dispone de todas las funcionalidades definidas en la clase Cliente, ms las
heredadasdelaclasePersona.

- 20 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
a.MyBaseyMyClass

Acontinuacineslegtimoquerermodificarelfuncionamientodeciertosmtodosheredadosparaadaptarlosala
claseCliente.Porejemplo,elmtodoMostrarsepuedesustituirparaaadirlosnuevoscamposdisponiblesenla
clase.

Public Overrides Sub mostrar()


Console.Write("Sr {0} {1} nacido el {2}", nombre, apellido, fecha_naci)
Console.Write(" cdigo de Cliente: {0}", elCodigo)
End Sub

Este cdigo funciona muy bien, pero no respeta uno de los principios de la programacin orientada a objetos:
utilizaralmximoloqueyaexiste.Ennuestrocaso,yatenemosunbloquedecdigoencargadodelavisualizacin
delapellido,nombreyfechadenacimientodeunapersona.PorqunoreutilizarloenelmtodoMostrar de la
claseClienteyaqueloheredamos?

Asnuestromtodoseconvierteenlosiguiente:

Public Overrides Sub mostrar()


mostrar()
Console.Write(" cdigo de Cliente: {0}", elCodigo)
End Sub

Intentemosutilizarlo:

Dim c As Cliente
c = New Cliente
c.nombre = "Pablo"
c.apellido = "Garca"
c.fecha_naci = #12/23/1954#
c.codigo = 12345
c.mostrar()

Desafortunadamente,elresultadonoestalaalturadenuestrasexpectativas!

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 21 -
Quhaocurridodurantelaejecucin?

Durante la llamada del mtodo mostrar, la primera lnea de cdigo consisti en llamar al mtodo mostrar de la
clasebase.Dehecho,VisualBasicbuscaelprimermtodomostrarqueencuentrayllamaporlotantoenbucleal
mtodomostrardelaclasecliente;deahprocedeelerrorqueencontramosdedesbordamientodelapila.

Paraevitarestetipodeproblema,debemosprecisarqueelmtodomostrarquequeremosllamarseencuentraen
laclasebase.Parahacerlo,debemosutilizarlapalabraclaveMyBaseparacalificarelmtodomostrarllamado.

Public Overrides Sub mostrar()


MyBase.mostrar()
Console.Write(" cdigo de Cliente: {0}", elCodigo)
End Sub

Despusdeestamodificacin,todovuelvealanormalidadynuestrocdigomuestra:

Sr Pablo Garca nacido el 23/12/54 00:00:00 Cdigo cliente: 12345

Lamismasintaxissepuedeutilizarparallamaralconstructordelaclasebase.

Lallamadaalconstructordelaclasebasedebeserlaprimeralneadeunconstructor.

AspodemoscrearunconstructorparalaclaseClientequeutiliceelconstructordelaclasePersona.

Public Sub New(ByVal nombre As String,ByVal apellido As String,


ByVal pwd As String, ByVal elCodigo As Integer)
MyBase.New(nombre, apellido, pwd)
elCodigo = elCodigo
End Sub

- 22 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Verifiquemosqueelnuevoconstructorfunciona:

Dim c As Cliente
c = New Cliente("Pablo", "Garca", "secreto", 12345)
c.fecha_naci = #12/23/1967#
c.mostrar()
Console.ReadLine()

Nosmuestra:

Sr Garca Pablo nacido el 23/12/1967 00:00:00 cdigo de Cliente: 0

Se han tenido en cuenta correctamente los datos, excepto el cdigo de cliente, que se ha quedado en cero.
Miremos ms de cerca el cdigo del constructor. Descubrimos que un parmetro del constructor lleva el mismo
nombre que un campo de la clase. Cuando escribimos la lnea CodeCli=CodeCli, el compilador considera que
queremos asignar al parmetroCodeCli el valor contenido en el parmetro CodeCli. Nada ilegal, pero no es en
absoluto lo que deseamos hacer. Debemos indicar que la asignacin debe hacerse a la variable miembro de la
clase.Parahacerlo,tenemosqueusarcomoprefijolapalabraclaveMyClass.

Elconstructorseconvierte,as,enlosiguiente:

Public Sub New(ByVal nombre As String, ByVal apellido As String, ByVal pwd
As String, ByVal elCodigo As Integer)
MyBase.New(nombre, apellido, pwd)
MyClass.elCodigo = elCodigo
End Sub

Nuestrocdigodepruebanosmuestraentonceslosdatoscorrectos:

Sr Garca pablo nacido el 23/12/67 00:00:00 cdigo de Cliente: 12345

b.Clasesabstractas

Las clases abstractas son clases que solo se pueden utilizar como clase base en una relacin de herencia. Es
imposiblecrearunainstanciadeunaclaseabstracta.Sirvenesencialmentedeplantillaparalacreacindeclasesy
debentenertodasunmnimodecaractersticasidnticas.Puedencontenercampos,propiedadesymtodoscomo
unaclasenormal.

Estatcnicafacilitalaevolucindelaaplicacin,yaque,siunanuevafuncionalidaddebeestardisponibleenlas
clasesderivadas,bastaaadirestafuncionalidadalaclasebase.Tambinesposiblenofacilitarlaimplementacin
para una clase abstracta y as dejar al usuario de la clase la posibilidad de crear la implementacin en la clase
derivada.

Para que una clase se convierta en una clase abstracta, debemos utilizar la palabra clave MustInherit en la
declaracindelaclase.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 23 -
Public MustInherit Class Plantilla

End Class

c.Clasesfinales

Lasclasesfinalessonclasesnormalesquepuedenserinstanciadas,peronosonutilizablescomoclasebaseen
unarelacindeherencia.EselcasodemuchasclasesdelFramework .NET,comoporejemplolaclaseString.

UnaclasefinaldebedefinirseconlapalabraclaveNotInheritable.

Public NotInheritable Class Cliente


Inherits Persona
End Class

d.Clasesannimas

Visual Basic nos ofrece la posibilidad de crear objetos sin necesidad de escribir el cdigo correspondiente a la
definicindelaclase.Elcompiladorseencargardelageneracindelaclase.Obviamente,habrqueayudarleun
pocoydarlealgunosdatosparaquepuedagenerarlaclaseycrearunainstancia.Ladeclaracindeunainstancia
declaseannimasebasaprincipalmenteenelprincipiovistoenelprrafoUtilizacindeunaclaseInicializacin
de una instancia. Durante la declaracin de una instancia as, debemos proveer la lista de las propiedades
deseadasysusrespectivosvalores.Veamosunprimerejemplo.

Dim producto = New With {.Nombre = bizcocho, .Precio = 1.56}

Lavariableproductohacereferenciaaunainstanciadelaclasequecontienedospropiedades,NombreyPrecio.
Estasdospropiedadessoninicializadasrespectivamenteconlosvalores"bizcocho"y1.56.

Las clases annimas respetan las mismas reglas que todas las otras clases, ya que heredan por defecto de la
claseObject.LosmtodosdisponiblessonlosheredadosdelaclaseObject.Dehecho,sonlosnicosquepodr
haberenunaclaseannima,yaqueparaestetipodeclaseesimposibledefinirotracosaquepropiedades,as
que nada de mtodos o eventos. Seguramente, se estar preguntando: cmo hace el compilador para no
perderse si existen varias instancias de clase annima? En realidad, estas clases son annimas para nosotros,
peronoparal,yaquedurantelacompilacinvaagenerarautomticamenteunnombreparaestasclases.Para
comprobarlo,pidamosalavariableproductoquenosindiquesutipo.

Console.WriteLine(producto.GetType.Name)

Alejecutarlo,obtenemoselsiguienteresultado:

- 24 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
VB$AnonymousType_02

Existeporlotantounnombreparaestasclases,perosoloseconocedespusdelacompilacinporlotanto,no
podemos utilizarlo en nuestro cdigo. De hecho no sera una buena idea, ya que se puede cambiar en cada
compilacindelaaplicacin.

Enrealidad,elcompiladornocreaunanuevaclaseparacadainstanciacin,yaqueantesdecrearunanuevaclase
verificasinohatratadoantesunadefinicinidntica.Paraello,sebasaenloselementossiguientes:

l Elnmerodepropiedades.

l Elnombredepropiedades.

l Eltipodepropiedades.

l Elordendelaspropiedadesenladefinicin.

Si todos estos elementos son idnticos, entonces utilizar de nuevo la clase que ya ha generado para crear la
instancia.Verifiquemosesto:

Dim producto1 = New With {.Nombre = bizcocho, .precio = 1.56}


Dim producto2 = New With {.Nombre = pan, .Precio = 2.24}
Console.WriteLine(la clase del producto1 es: {0}, producto1.GetType.Name)
Console.WriteLine(la clase del producto2 es: {0}, producto2.GetType.Name)

Obtenemoselsiguienteresultado:

la clase del producto1 es: VB$AnonymousType_02


la clase del producto2 es: VB$AnonymousType_02

Todo es normal, ya que las dos variables tienen rigurosamente la misma definicin. Si hacemos una pequea
modificacininvirtiendosimplementeelordendelaspropiedades:

Dim producto1 = New With {.Nombre = bizcocho, .precio = 1.56}


Dim producto2 = New With {.Precio = 2.24, .Nombre = pan}
Console.WriteLine(la clase del producto1 es: {0}, producto1.GetType.Name)
Console.WriteLine(la clase del producto2 es: {0}, producto2.GetType.Name)

Estavez,obtenemoselsiguienteresultado:

la clase del producto1 es: VB$AnonymousType_02


la clase del producto2 es: VB$AnonymousType_12

Ahora,elcompiladorhageneradodosclases,yaquelasdefinicionessondiferentes.

Durante la declaracin de una instancia de clase annima, ciertas propiedades pueden ser definidas como
propiedadesclavesdelainstancia.Estaspropiedadestienenunpapelimportanteenlacomparacindeinstancias
declasesannimas.Seidentificangraciasalapalabraclavekeyubicadadelantedelnombredelapropiedad.Las
propiedadesasdeclaradassondesololectura.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 25 -
Paracomparardosinstanciasdeclasesannimas,debemosutilizarelmtodoEquals.Estemtodoesheredado
de la claseObject, pero sustituido por el compilador en el momento de la generacin de la clase annima. Este
mtodoindicarquedosinstanciassonidnticassiserespetantodaslascondicionessiguientes:

l Sedebendeclararlosdosobjetosenelmismoensamblado.

l Laspropiedadesdebentenerelmismonombre,elmismotipoyserdeclaradasenelmismoorden.

l DebeexistiralmenosunapropiedaddeclaradaconlapalabraclaveKey.

l LasmismaspropiedadesdebenserdeclaradasconlapalabraclaveKeyenlasdosinstancias.

l LosvaloresdelaspropiedadesdeclaradasconlapalabraclaveKeydebenseridnticosenlasdosinstancias.

l Unainstanciadeclaseannimaquenotieneunapropiedaddeclaradaconlapalabraclave Keynopuedeseriguala
smisma.

Verifiquemosestasreglascomparandodiferentesproductos.

Dim producto1 = New With {Key .codigo = 12854, .Nombre = bizcocho,


.precio = 1.56}
Dim producto2 = New With {Key .codigo = 12854, .Nombre = bizcocho,
.precio = 1.56}

Console.WriteLine(producto1.Equals(producto2))

Estecdigonosmuestra True,yaquelasdosinstanciasrespetanelconjuntodelasreglasdeigualdadcitadas
anteriormente.

Tratemosdeincumplirunadelasreglas,porejemploladelapalabraclaveKey.

Dim producto1 = New With {.codigo = 12854, .Nombre = bizcocho,


.precio = 1.56}
Dim producto2 = New With {Key .codigo = 12854, .Nombre = bizcocho,
.precio = 1.56}

Console.WriteLine(producto1.Equals(producto2))

Elresultadoesinapelable:lasdosinstanciasyanosonidnticas.

4.Interfaces

Hemos visto que se poda obligar a una clase a implementar un mtodo declarndolo con la palabra clave
MustOverride. Si tenemos varias clases que deben implementar el mismo mtodo, es ms prctico utilizar las
interfaces. Como las clases, las interfaces permiten definir un conjunto de propiedades, mtodos, eventos. Sin
embargo, no contienen cdigo alguno. La implementacin debe efectuarse a nivel de la propia clase. La interfaz

- 26 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
constituye un contrato que firmamos. Al declarar que la clase implementa una interfaz, nos comprometemos a
proporcionarenlaclasetodoloqueestdefinidoenlainterfaz.Convieneserprudentey,sidebemosutilizarlas
interfaces,nomodificarnuncaunainterfazyautilizadaporquecorremoselriesgodetenerquemodificarelcdigo
detodaslasclasesqueimplementanesainterfaz.

Parapoderutilizarunainterfaz,convienedefinirlapreviamente.Ladeclaracinesparecidaaladeunaclase,pero
seutilizanlaspalabrasclaveInterfaceyEnd Interface.

PuedetambinutilizarlapalabraclaveInheritsparaintroducirunarelacindeherenciaenlainterfaz.Lasnicas
instrucciones que deben aparecer en una interfaz son las declaraciones de propiedades con Property, de
procedimientos y funciones con Sub y Function o de eventos con Event. No debe haber ningn cdigo en los
procedimientosyenlasfunciones,nisiquieradeEnd SubodeEnd Function.

Ascreamosnuestraprimerainterfaz.

Public Interface Comparable


Function compara(ByVal o1 As Object) As Integer
End Interface

Esta interfaz nos obligar a crear, en las clases que la implementen, una funcin que nos permita comparar la
instanciaactualdeunobjetoyelobjetoqueserpasadocomoparmetro.Lafuncindevolverunvaloriguala1si
elobjetopasadocomoparmetroessuperioralainstanciaactual,unvaloriguala0silosdosobjetossonigualesy
unvaloriguala1silainstanciaactualessuperioralobjetopasadocomoparmetro.

Peroqucriteriosvamosautilizarparadecirqueunobjetoessuperioraotro?

Esenoesnuestroproblemacuandodescribimoslainterfaz!Dejemosquelapersonaquehadedefinirunaclase
utilizandonuestrainterfazseocupededefinirculessonloscriteriosdecomparacin.Porejemplo,ennuestraclase
Cliente, podramos implementar la interfaz Comparable de la manera siguiente, eligiendo comparar dos clientes
segnelapellido:

Public Class Cliente


Inherits Persona
Implements Comparable

...
...

Public Function compara(ByVal o1 As Object) As Integer


Implements Comparable.compara
Select Case apellido
Case Is < o1.apellido
Return -1
Case Is > o1.apellido
Return 0
Case Else
Return 1
End Select
End Function

Sepuedenobservardosmodificacionesenlaclase:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 27 -
l ElhechodequelaclaseimplementalainterfazComparable.

l Laimplementacinrealdelafuncincompareconlaindicacindelainterfazydelmtodoqueimplementa.

Enestafuncin,lacomparacinseharconelapellidodelosclientes.Muybien,perodequsirve?

Amenudoocurrequesenecesitaordenarelementosenunaaplicacin.Existendossoluciones:

l Crearunafuncindeordenacinespecficaparacadatipodeelementoquesedeseaordenar.

l Crear una rutina de ordenacin genrica y hacer de tal manera que los elementos utilizados sean ordenables segn
estarutina.

Lasinterfacesnosvanaayudaraponerenmarchaestasegundasolucin.Parapoderordenarelementos,ysea
cualseaelmtodoutilizadoparasuordenacin,necesitaremoscomparardoselementos.Paraasegurarnosdeque
nuestra rutina de ordenacin funciona sin problema, tenemos que estar seguros de que los elementos que debe
ordenar tienen la posibilidad de ser comparados los unos con los otros. Podemos garantizar eso solo si todos
nuestroselementosimplementanlainterfazComparable.Porlotanto,vamosaexigirloenladeclaracindenuestra
rutinadeordenacin.

Public Sub ordena(ByVal matriz As Comparable())

As definido, nuestro procedimiento ser capaz de ordenar cualquier tipo de matriz siempre que sus elementos
implementenlainterfazComparable.Aspodemosescribirelsiguientecdigoyutilizarelmtodocomparesinriesgo.

Public Sub ordena(ByVal matriz As Comparable())


Dim i As Integer
Dim j As Integer
Dim o As Object
For i = 0 To UBound(matriz) - 1
For j = i + 1 To UBound(matriz)
If (matriz(j).compare(matriz(i))) < 0 Then
o = matriz(j)
matriz(j) = matriz(i)
matriz(i) = o
End If
Next
Next
End Sub

Despus, para probar nuestro procedimiento, creamos algunos clientes, intentamos ordenarlos y mostrar sus
apellidos.

Dim matriz(4) As Cliente


matriz(0) = New Cliente("pepe2", "nombre2 ", "secreto", 2)
matriz(1) = New Cliente("pepe1", "nombre1 ", "secreto", 1)
matriz(2) = New Cliente("pepe5", "nombre5 ", "secreto", 5)
matriz(3) = New Cliente("pepe3", "nombre3 ", "secreto", 3)
matriz(4) = New Cliente("pepe4", "nombre4 ", "secreto", 4)
ordena(matriz)

- 28 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim i As Integer
For i = 0 To 4
Console.WriteLine(matriz(i).apellido)
Next

Obtenemoselsiguienteresultado:

Sr pepe1 nombre1 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1


Sr pepe2 nombre2 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 2
Sr pepe3 nombre3 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 3
Sr pepe4 nombre4 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 4
Sr pepe5 nombre5 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 5

Enefecto,tenemoslalistadenuestrosclientesordenadosalfabticamentesegnelnombre.

Intentemosutilizarnuestroprocedimientodeordenacinconunamatrizdeobjetosquenoimplementenlainterfaz
Comparable.

Dim tabCoche(4) As Coche


tabCoche(0) = New Coche("Fiat", "500")
tabCoche(1) = New Coche("Peugeot","205")
tabCoche(2) = New Coche("Opel", "Corsa")
tabCoche(3) = New Coche("Renault", "Laguna")
tabCoche(4) = New Coche("Lancia", "Delta")
ordena(tabCoche)
Dim i As Integer
For i = 0 To 4
Console.WriteLine(tabCoche(i).nombre)
Next

Ningnproblemaenlacompilacin,perolascosassecomplicandurantelaejecucin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 29 -
Esteerrorapareceenelmomentodelallamadaalprocedimientodeordenacin.Loselementosdelamatrizque
hemospasadocomoparmetronoimplementanlainterfazComparableynoestamossegurosdequecontenganuna
funcin compare. Observe que, incluso si existe una funcin compare correcta en la clase Coche, tenemos que
especificar obligatoriamente que esta clase implementa la interfaz Comparable, para que nuestro cdigo pueda
funcionar.

5.Loseventos

Losmtodosnospermitenestablecercomunicacinconlosobjetosquecomponenunaaplicacin,perolosobjetos
tambintienenlaposibilidaddetransmitirnossusreaccionesgenerandoeventos.Acontinuacin,debemostomar
encuentaestoseventosparaquepodamosreaccionaranteloqueacabadeocurrirenlaaplicacin.

En el diseo de la interfaz grfica de una aplicacin se utilizan mucho los eventos, ya que nos permiten tener
informacinsobrelasaccionesefectuadasporelusuariodelaaplicacin.

a.Declaracinyactivacindeeventos

Veamos primero cmo generar un evento en una clase. Lo primero que se debe hacer consiste en declarar el
eventoenlaclase.Estadeclaracinseefectadelamismamaneraqueladelasvariablesinternasalaclase.Se
utiliza para ello la palabra clave Event seguida por el nombre del evento. En la declaracin, tambin podemos
especificar los parmetros que proporcionarn datos adicionales sobre el propio evento o sobre el estado del
objeto, en el momento en que se activa el evento. Por ejemplo, podemos crear en nuestra clase Cliente un
evento que se activar cada vez que se aada un pedido. Como informacin adicional, nuestro evento
proporcionarelnmerodelospedidosdespusdequehayansidoaadidos.

Public Event NuevoPedido(ByVal numPedido As integer)

Nosquedapordefinirenqucondicionesseactivarnuestroeventoyporsupuestoquhayquehacerparaque

- 30 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
seactiveenundeterminadomomento.ParanuestraclaseCliente,lomslgicoesgenerarnuestroeventoenel
momento de la ejecucin del mtodo que permite aadir un pedido. Para hacerlo, vamos a crear el mtodo
AgregarPedido.Estemtodorecibecomoparmetroelnmerodelpedidoquesevaaagregar.Lanicaaccinde
estemtodoserincrementarelnmerodepedidosdelcliente.

Public Sub AgregarPedido(ByVal numero As Integer)


numPedidos = numPedidos + 1
End Sub

En el mtodoAgregarPedido, vamos a activar el evento con la instruccinRaiseEventseguidaporelnombredel


evento declarado al principio en la clase. Tambin debemos proporcionar los eventuales parmetros declarados
connuestroevento.

Public Sub AgregarPedido(ByVal numero As Integer)


numPedido = numPedido + 1
RaiseEvent NuevoPedido(numPedido)
End Sub

DespusdelaejecucindelainstruccinRaiseEvent,eleventosetransmitiratodosloselementosquesehayan
declaradointeresadosenesteevento.Sihaymuchoselementosafectadosporelevento,recibirnunotrasotrola
notificacindelevento.

Detodosmodos,hayqueresaltarquenoesposiblepredecirelordenenqueloselementosdenuestraaplicacin
recibirn el aviso, ni tampoco avisar a un nuevo elemento en tanto el anterior no haya terminado de tratar el
evento.

b.Gestionarloseventos

Vamosaverahoracmorecuperarloseventosennuestraaplicacin.Sonposiblesdossoluciones:

l DeclararunavariableconlapalabraclaveWithEventsyutilizarlaclusulaHandles.

l Agregarmanualmenteunadministradordeeventos.

La segunda solucin es ms flexible, ya que nos permite agregar o eliminar dinmicamente administradores de
eventos durante el funcionamiento de nuestra aplicacin, pero necesita un poco ms de cdigo que la primera
solucin.

UtilizacindelaclusulaHandles

Esta solucin necesita una declaracin de variable especfica. La declaracin de una variable, que puede hacer
referenciaaunainstanciadelaclaseCliente,serealizadelasiguientemanera:

Dim WithEvents unCliente As Cliente

Es conveniente ahora decidir qu cdigo se ejecutar cuando se produzca este evento. Se debe crear un
procedimientoparalarecepcindeesteevento.Parahacerlo,elentornodedesarrollonosfacilitalatarea.Enla
partesuperiordenuestraventanadecdigo,tenemosdoslistasdisponibles.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 31 -
La primera nos indica todas las fuentes de eventos disponibles y nos permite entonces elegir de dnde vendr
nuestroevento.

Lasegundaindica,paralafuentedeeventoseleccionada,culessonloseventossusceptiblesdeactivacin.

Despus de elegir en las dos listas, el entorno genera automticamente el esquema del procedimiento que se
llamarparalaactivacindelevento.

Private Sub unCliente_NuevoPedido(ByVal numPedido As Integer) Handles


unCliente.NuevoPedido
End Sub

Este mtodo es igual a los que hemos escrito hasta ahora, aadiendo la palabra claveHandles seguida por el
nombredeleventoquetrataresteprocedimiento.Porconvencin,elnombredelprocedimientoestcompuesto
delnombredelelementoseguidoporelnombredeleventogestionadoenesteobjeto.Peronoesmsqueuna
convencin que facilita la lectura del cdigo. La nica obligacin es que el procedimiento respete la estructura
definidaenelevento.

Tambinpodemosaadirmuchosprocedimientosquesellamarnatravsdelmismoevento,peroenestecaso
esnecesarioescribirelcdigomanualmenteyporsupuestoutilizarnombresdiferentesparalosprocedimientos.
Estemtodonoesmuyflexible,yaqueesimposibleelegir,durantelaejecucin,quadministradordeeventose
utilizar.

ExistetambinotralimitacinrelativaalhechodequelasvariablesdeclaradasWithEventsdebenserdeclaradas
fueradecualquierprocedimientoofuncin.

Agregarysuprimirunadministradordeevento

Paraevitarestaslimitaciones,tenemoslaposibilidaddeaadirmanualmenteadministradoresdeevento.Eneste

- 32 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
caso, la variable debe declararse sin la palabra clave WithEvents. Se utiliza a continuacin la palabra clave
AddHandlerparaasociarauneventounprocedimientoquelogestione.

AddHandler unCliente.NuevoPedido, AddressOf unCliente_NuevoPedido

ElprimerparmetrodeAddHandlereseleventoquesequieregestionar,alqueseleindicaadems,atravsde
AddressOf, el emplazamiento en el que se encuentra el procedimiento que se ejecutar para gestionar este
evento.Aspodemosdecidir,duranteelfuncionamientodelaaplicacin,quingestionaruneventoenconcreto.
Porejemplo,sitenemosunaaplicacinquefuncionaenmodoconsolaoenmodoWindows,tendremosunmodo
devisualizacindistinto.

Dim mode As String = "consola"


Dim unCliente As Cliente
unCliente = New Cliente("Pablo", "Garca", "secreto", 12345)

If mode = "grafico" Then


AddHandler unCliente.NuevoPedido, AddressOf gestion_grafico
Else
AddHandler unCliente.NuevoPedido, AddressOf gestion_texto
End If
unCliente.AgregarPedido(10)

Public Sub gestion_grafico(ByVal numpdo As Integer)


MsgBox("nmero de pedidos " & numpdo)
End Sub

Public Sub gestion_texto(ByVal numpdo As Integer)


Console.WriteLine("nmero de pedidos " & numpdo)
End Sub

Del mismo modo, podemos eliminar un administrador de evento que ya est referenciado, utilizando
RemoveHandler.

RemoveHandler unCliente.NuevoPedido, AddressOf gestion_grafico

Estainstruccinnoeliminaelprocedimientogestion_grafico,sinoquesimplementecortalarelacinconelevento
elJefe.aumento_sueldo.EstarelacinpodrrestablecersemsadelanteutilizandootravezAddHandler.

Eventosyherencia

ltimopuntoporaclarar:cmosevanacomportarloseventoscuandonuestraclaseseconviertaensubclase?

Loseventossiguenlasmismasreglasdeherenciaquelaspropiedadesymtodos.Uneventodeclaradoenuna
claseseraccesibleentodassussubclases.Sinembargo,existeunapequearestriccin,porquelaactivacindel
eventopodrtenerlugarsoloenlaclaseenlaqueesdeclarado.Paraevitarelproblema,essuficientedeclararun
mtodo protected en la clase y simplemente hacer activar el evento por este mtodo. Enseguida tendremos la
posibilidad de activar el evento en cualquier otra subclase, no utilizando directamente el RaiseEvent, sino el
mtodoprotegidoqueloharpornosotros.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 33 -
Porejemplo,parapoderactivareleventoenunasubclasedeCliente,podremosescribirelsiguientecdigo:

EnlaclaseCliente:

Protected Sub desencadena_NuevoPedido(ByVal num as integer)


RaiseEvent NuevoPedido (num)
End sub

EnlasubclasedeCliente:

Public Sub masUno()


...
desencadena_NuevoPedido(numero)
...
End Sub

6.Losdelegados

Avecespuederesultartilpasarcomoparmetroaunafuncinounprocedimientonountiposimpleounobjeto,
sinodirectamenteunprocedimientoounafuncin.Porejemplo,siqueremoselegirelcriteriosegnelcualvamosa
hacer la ordenacin de nuestros empleados, debemos escribir una funcin de comparacin para cada criterio.
Durante la llamada del procedimiento de ordenacin, especificaremos qu mtodo utilizar para efectuar la
comparacin.

a.Declaracinycreacindeundelegado

Laprimeraetapaconsisteendeclarareldelegado.EstadeclaracinutilizalapalabraclaveDelegateseguidaporla
firmadelprocedimientoofuncin.

Public Delegate Function comparacion(ByVal o1 As Object, ByVal o2 As Object)


As Integer

Luego hay que crear un procedimiento o funcin que respete la firma del delegado. En nuestro caso, vamos a
creardosfuncionescapacesdecomparardosclientes.

Crearemos una para realizar la comparacin sobre el cdigo y otra para la comparacin sobre el nmero de
pedidos. Estas funciones pueden escribirse en un mdulo o en una clase. En este ltimo caso, la funcin debe
declararse compartida, con la palabra clave shared, para que sea accesible sin haber creado la instancia de la
clase.

Function comparaCodigo(ByVal c1 As Cliente, ByVal c2 As Cliente) As Integer


Select Case c1.codigo
Case Is < c2.codigo
Return -1
Case c2.codigo
Return 0
Case Else

- 34 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Return 1
End Select
End Function

Function comparaNumPedidos(ByVal c1 As Cliente, ByVal c2 As Cliente)


As Integer
Select Case c1.numpedido
Case Is < c2.numpedido
Return -1
Case c2.numpedido
Return 0
Case Else
Return 1
End Select
End Function

Ahorahayquemodificarnuestrafuncindeordenacinparaquetomecomoparmetro,ademsdelamatrizque
hay que ordenar, la funcin utilizada para la comparacin de dos elementos de la matriz. Nuestra funcin de
ordenacinseconvierteporlotantoenlosiguiente:

Public Sub ordena(ByVal matriz() As Object, ByVal comparador As comparacion)


Dim i As Integer
Dim j As Integer
Dim o As Object
For i = 0 To UBound(matriz) - 1
For j = i + 1 To UBound(matriz)
If comparador.Invoke(matriz(j), matriz(i)) < 0 Then
o = matriz(j)
matriz(j) = matriz(i)
matriz(i) = o
End If
Next
Next
End Sub

Dosmodificacionesennuestrocdigo:

l Lainclusindelparmetrocomparadorcomodelegadoparanuestrafuncindeordenacin.

l Lautilizacindeesedelegadoparacomparardoselementosdelamatrizutilizandoelmtodoinvoke.

LoselementosdelamatrizyanotienenlaobligacindeimplementarlainterfazComparable,yaquesepasaala
funcinunamaneradecompararlosdedosendos.

b.Utilizacindelosdelegados

Para utilizar la funcin de ordenacin, debemos facilitarle dos parmetros: la matriz que se debe ordenar y una
instancia de un delegado utilizado para ordenar la matriz. Por lo tanto, debemos crear una instancia de un
delegado.

Dim fct As comparacion

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 35 -
fct = New comparacion(AddressOf comparaCodigo)

Elconstructoresperaunparmetroquelepermitaencontrarelcdigodelafuncin.EloperadorAddressOfextrae
ladireccindelamemoriadelafuncinyselapasaalconstructor.

A continuacin podemos llamar la funcin de ordenacin pasndole como segundo parmetro la instancia del
delegado.

ordena(tab, fct)

Sideseamosutilizarotrocriteriodeordenacin,simplementedebemoscrearotrafuncinquerespetelafirmadel
delegadoyconstruirundelegadoapartirdeestafuncin.

c.Expresioneslambda

Unaexpresinlambdasepuedecompararaunafuncinsinnombrequeefectaunatareaydevuelve,ono,un
simplevalor.Sepuedenutilizarencualquierpartedondeseesperaundelegado.

Las expresiones lambda utilizan la palabra clave Function o Sub para su declaracin. Se debe especificar entre
parntesislosparmetrosesperadosenentradaporlaexpresinlambda.Debencorresponderalosparmetros
esperadosporeldelegadoquelaexpresinlambdareemplaza.Sieldelegadonoesperaningnparmetro,hay
queespecificar,apesardetodo,eljuegodeparntesis.Lapartesiguientedelaexpresinlambdarepresentala
instruccinoelbloquedeinstruccionesqueseejecutar.Siseutilizaunbloquedeinstrucciones,debeterminar
porlaspalabrasclavesEnd SuboEnd Function.Elprimerodelossiguientesejemplosllamalafuncinordenacin
pasndolecomosegundoparmetrounaexpresinlambdaquerespetalafirmadeldelegadoesperadoyefecta
laordenacinsegnelapellidodelcliente.

Dim matriz(4) As Cliente


matriz(0) = New Cliente("pepe2", "nombre2 ", "secreto", 2)
matriz(1) = New Cliente("pepe1", "nombre1 ", "secreto", 1)
matriz(2) = New Cliente("pepe5", "nombre5 ", "secreto", 5)
matriz(3) = New Cliente("pepe3", "nombre3 ", "secreto", 3)
matriz(4) = New Cliente("pepe4", "nombre4 ", "secreto", 4)
Dim fct As Comparacin
ordena(matriz, Function(c1 As Cliente, c2 As Cliente)
c1.apellido.CompareTo(c2.apellido)
Dim i As Integer
For i = 0 To 4
matriz(i).mostrar()
Console.WriteLine()
Next

Si la expresin contiene varias lneas, se tiene que utilizar un bloque de cdigo terminado con End Sub o End
Function.Estedebecontenertodaslasinstruccionesdelaexpresin.Elsiguienteejemploefectaunaordenacin
utilizandocomocriterioelcdigodelcliente.

Dim matriz(4) As Cliente


matriz(0) = New Cliente("pepe2", "nombre2 ", "secreto", 2)
matriz(1) = New Cliente("pepe1", "nombre1 ", "secreto", 1)

- 36 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
matriz(2) = New Cliente("pepe5", "nombre5 ", "secreto", 5)
matriz(3) = New Cliente("pepe3", "nombre3 ", "secreto", 3)
matriz(4) = New Cliente("pepe4", "nombre4 ", "secreto", 4)
ordena(matriz, Function(c1 As Cliente, c2 As Cliente)
If (c1.codigo > c2.codigo) Then
Return 1
End If
If (c1.codigo < c2.codigo) Then
Return -1
Else
Return 0
End If
End Function
)
Dim i As Integer
For i = 0 To 4
matriz(i).mostrar()
Console.WriteLine()
Next

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 37 -
Lostiposgenricos

Lostiposgenricossonelementosdeunprogramaqueseadaptanautomticamentepararealizarlamismafuncin
endiferentestiposdedatos.Cuandocreaunelementogenrico,nonecesitadisearunaversindiferenteparacada
tipodedatosconelquedesearealizarunafuncin.

Pararealizarunaanalogaconunobjetocorriente,vamosatomarelejemplodeundestornillador.Enfuncindeltipo
detornilloquesevayaautilizar,puedecogerundestornilladorespecficoparaestetipodetornillo(plano,decruz,de
estrella,etc.).Unatcnicaamenudoutilizadaporunmanitasexpertoconsisteenadquirirundestornilladoruniversal,
conmltiplescabezas.Enfuncindeltipodetornillo,eligelacabezaadecuada.Elresultadofinaleselmismoquesi
disponedevariosdestornilladores:puedeatornillarydesatornillar.

Cuando se utiliza un tipo genrico, se configura con un tipo de datos. Esto permite al cdigo adaptarse
automticamente y realizar la misma accin independientemente del tipo de datos. Una alternativa podra ser la
utilizacin del tipo universal Object. La utilizacin de los tipos genricos presenta varias ventajas respeto a esta
solucin:

l Impone la verificacin de los tipos de datos en el momento de la compilacin y evita las verificaciones que deben
efectuarsemanualmenteconlautilizacindeltipoObject.

l EvitalasoperacionesdeconversindeltipoObjecthaciauntipomsespecficoyque,adems,consumanrecursos.

l Evitalautilizacindelenlacetardo,ineludibleconeltipoObject.

l ElentornodedesarrollofacilitalaescrituradelcdigograciasaIntelliSense.

l Favorecelaescrituradealgoritmosindependientesdelostiposdedatos.

Los tipos genricos pueden, sin embargo, imponer ciertas restricciones relativas al tipo de datos utilizado. Por
ejemplo, pueden imponer que el tipo utilizado implemente una o varias interfaces, que sea un tipo de referencia o
queposeaunconstructorpordefecto.

Esimportanteentendercorrectamentealgunostrminosutilizadosconlosgenricos:

Eltipogenrico

Esladefinicindeunaclase,estructura,interfazoprocedimientoparaelquesepuedeespecificaral
menosuntipodedatosenelmomentodesudeclaracin.

Eltipoparmetro

Eslaubicacinreservadaparaeltipodedatosenladeclaracindeltipogenrico.

Eltipoargumento

Eseltipodedatosquesustituyeeltipodeparmetrodurantelaconstruccindeuntipoapartirdeun
tipogenrico.

Laslimitaciones

Sonlascondicionesqueustedimponeyquelimitaneltipoargumentoquepuedefacilitar.

Eltipoconstruido

Eslaclase,interfaz,estructuraoprocedimientodeclaradoapartirdeuntipogenricoparaelqueha

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
especificadounostiposdeargumento.

1.Lasclasesgenricas

Unaclasequeesperauntipodeparmetrosellamaclasegenrica.Puedegenerarunaclaseconstruidafacilitando
alaclasegenricauntipoargumentoparacadaunodeestostiposparmetro.

a.Definicindeunaclasegenrica

Puededefinirunaclasegenrica,quefacilitalasmismasfuncionalidadessobrediferentestiposdedatos.Paraello,
debefacilitarunoovariostiposdeparmetroenladefinicindelaclase.Tomemoselejemplodeunaclase,capaz
degestionarunalistadeelementosconlassiguientesfuncionalidades:

l Agregarunelemento.

l Suprimirunelemento.

l Desplazarsehastaelprimerelemento.

l Desplazarsehastaelltimoelemento.

l Desplazarsehastaelelementosiguiente.

l Desplazarsehastaelelementoanterior.

l Obtenerelnmerodeelementos.

Primerodebemosdefinirlaclasecomounaclaseordinaria.

Public Class ListaGenerica

End Class

La transformacin de esta clase en clase genrica se efecta aadiendo un tipo de parmetro inmediatamente
despusdelnombredelaclase.

Public Class ListaGenerica(Of tipo)

End Class

Sisonnecesariosvariostiposdeparmetro,sedebensepararconcomassinrepetirlapalabraclaveOf.

Sisucdigodeberealizaroperacionesquenoseanasignaciones,debeaadirlimitacionesaltipodeparmetro.
Parahacerlo,aadalapalabraclaveAsseguidaporlalimitacin.

Siesnecesarioaplicarvariaslimitacionessobreelparmetro,debenespecificarseentrellaves.

Laslimitacionessiguientesestndisponibles:

structure

Estarestriccinimponequeeltipoparmetroseauntipoporvalor,ynountiporeferencia.Ademsestetipono

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
debeserNullable.

Public Class ListaGenerica(Of tipo As Structure)

End Class

class

Estalimitacinimponequeeltipoparmetroseauntiporeferencia:clase,interfaz,matrizodelegado.

Public Class ListaGenerica(Of tipo As Class)

End Class

New

Esta limitacin impone la presencia de un constructor public y sin parmetro en el tipo parmetro. Tambin se
utilizaconotraslimitaciones,comoporejemplolalimitacinClass.Laslimitacionesdebenirenlalistaseparadas
concomas.

Public Class ListaGenerica(Of tipo As {Class, New})

End Class

nombredeunaclase

Estalimitacinexigequeeltipoparmetrosealaclaseindicadaounadesussubclases.

Public Class ListaGenerica(Of tipo As Persona)

End Class

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
interfaz1,interfaz2...

Estalimitacinexigequeeltipoparmetroimplementelainterfazolasinterfacesindicadas.

Public Class ListaGenerica(Of tipo As {IComparable


Ienumerable})

End Class

Sinoseespecificanlimitaciones,lasnicasoperacionesautorizadassernlassoportadasporeltipoObject.

Enelcdigodelaclase,cadamiembroquedebaserdeltipodeparmetrodebedefinirseconlasintaxisAs tipo,
ennuestrocaso.Veamosahoraelcdigocompletodelaclase.

Public Class ListaGenerica(Of tipo)


matriz para almacenar los elementos de la lista
Private lista() As tipo
puntero de posicin en la lista
Private position = 0
puntero para agregar un nuevo elemento
Private elementoSiguiente = 0
nmero de elementos de la lista
Private numElementos = 0
dimensin de la lista
Private tamao As Integer
indica si la lista est llena
Private completa As Boolean = False
constructor con un parmetro que permita dimensionar la lista
Public Sub New(ByVal tamao As Integer)
lista = New tipo(tamao - 1) {}
MyClass.tamao = tamao
End Sub
Public Sub agregar(ByVal elemento As tipo)
verificamos si la lista est completa antes
de agregar un elemento
If Not completa Then
lista(elementoSiguiente) = elemento
numElementos = numElementos + 1
completa = (numElementos = tamao)
si la lista no est completa, colocamos el puntero
para agregar el elemento siguiente
If Not completa Then
elementoSiguiente = elementoSiguiente + 1
End If
Else
Beep()
End If
End Sub
Public Sub suprime(ByVal ndice As Integer)
Dim i As Integer
verificamos si el ndice no es superior al nmero de elementos
si el ndice no es inferior a 0

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
If ndice >= numElementos OrElse ndice < 0 Then
Beep()
Exit Sub
End If
desplazamos los elementos una posicin hacia arriba
For i = indice To numElementos - 2
lista(i) = lista(i + 1)
Next
colocamos el puntero para agregar un nuevo elemento
elementoSiguiente = elementoSiguiente - 1
actualizamos el nmero de elementos
numElementos = numElementos - 1
End Sub
Public ReadOnly Property tamaoLista() As Integer
Get
Return numElementos
End Get
End Property

Public Function primero() As tipo


If numElementos = 0 Then
Err.Raise(1000, , "lista vaca")
End If
desplazamos el puntero hacia el primer elemento
posicion = 0
Return lista(0)
End Function
Public Function ltimo() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vaca")
End If
desplazamos el puntero hacia el ltimo elemento
posicion = numElementos - 1
Return lista(position)
End Function
Public Function siguiente() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vaca")
End If
verificamos que no estamos al final de la lista
If posicion = numElementos - 1 Then
Beep()
Err.Raise(1000, , "ningn elemento siguiente")
Exit Function
End If
desplazamos el puntero hasta el elemento siguiente
posicion = posicion + 1
Return lista(posicion)
End Function
Public Function anterior() As tipo
If numElementos = 0 Then
Err.Raise(1000, , "lista vaca")
End If
verificamos que no estamos en el primer elemento
If posicion = 0 Then

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Beep()
Err.Raise(1000, , "ningn elemento anterior")
Exit Function
End If
nos desplazamos hasta el elemento anterior
posicion = posicion - 1
Return lista(posicion)
End Function
End Class

b.Utilizacindeunaclasegenrica

Para poder utilizar una clase genrica, ante todo debe generar una clase construida que proporcione un tipo
argumentoparacadaunodesustiposparmetro.Entoncespuedeinstanciarlaclaseconstruidaporunodelos
constructoresdisponibles.Vamosautilizarlaclasediseadaanteriormenteparatrabajarconunalistadeenteros.

Dim lista As New ListaGenerica(Of Integer)(5)

Estadeclaracinpermiteinstanciarunalistadecincoenteros.Losmtodosdelaclaseentoncesestndisponibles.

lista.Aadir(10)
lista.Aadir(11)

Porsupuesto,elcompiladorcompruebaqueutilizamosnuestraclasecorrectamente,enparticularverificandolos
tiposdedatosqueleconfiamos.

A continuacin tenemos el cdigo de una pequea aplicacin que permite probar el funcionamiento correcto de
nuestraclasegenrica:

Module testGenerica
Dim lista As New ListaGenerica(Of Integer)(5)
Public Sub main()
lista.Aadir(10)
lista.Aadir(11)
lista.Aadir(12)
lista.Aadir(13)
lista.Aadir(14)
lista.Aadir(15)
menu()
End Sub
Public Sub menu()
Dim elige As Char

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
On Error GoTo gestionerror
Console.SetCursorPosition(1, 24)
Console.WriteLine("p (primero) < (anterior) >(siguiente) d (ultimo) f
(fin)")
While elige <> "f"
elige = Console.ReadLine()
Console.Clear()
Console.SetCursorPosition(1, 1)
Select Case elige
Case "p"
Console.WriteLine("el primero {0}", lista.primero())
Case "<"
Console.WriteLine("el anterior {0}", lista.anterior())
Case ">"
Console.WriteLine("el siguiente {0}", lista.siguiente())
Case "d"
Console.WriteLine("el ltimo {0}", lista.ultimo())
End Select
Console.SetCursorPosition(1, 24)
Console.WriteLine("p (primero) < (anterior) >(siguiente) d
(ltimo) f (fin)")
End While
Exit Sub
gestionerror:
Console.ForegroundColor = ConsoleColor.Red
Console.WriteLine(Err.Description)
Console.ResetColor()
Resume Next
End Sub
End Module

Tambin podemos verificar que nuestra clase funciona sin problema si le pedimos trabajar con cadenas de
caracteres.

Public Sub main()


lista.Aadir("primero")
lista.Aadir("segundo")
lista.Aadir("tercero")
lista.Aadir("cuarto")
lista.Aadir("quinto")
menu()
End Sub

2.Interfacesgenricas

Demaneratotalmentesimilaraloqueacabamosdeverrespectoalasclasesgenricas,tambinesposibledisear
interfacesgenricas.Utilizanlasmismastcnicasdediseoquelasclasesgenricas.

a.Definicindeunainterfazgenrica

Ladefinicindeunainterfazgenricaessimilarentodopuntoaladeclaracindeunainterfaznormal,exceptopor

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
el hecho de que se debe especificar al menos un tipo parmetro despus del nombre de la interfaz. La interfaz
Comparabledefinidaanteriormentepuedetomarportantolaformasiguiente:

Public Interfaz ComparableGenerica(Of tipo)


Function compare(ByVal o1 As tipo) As Integer
End Interfaz

Eltipoparmetrosepuedeutilizarenlafirmadelosmtodosexigidosporlainterfaz.

b.Utilizacindeunainterfazgenrica

Como ocurre con una interfaz normal, una interfaz genrica debe ser implementada por una clase. Durante la
declaracindelaclase,eltipoolostiposparmetrosdebensersustituidosporunoovariostiposargumento.

Lautilizacindenuestrainterfazgenricapuedetomarlaformasiguiente:

Public Class Persona


Implements ComparableGenerica(Of Persona)

End Class

Elcompiladorexigeahoraqueelmtodoolosmtodosdescritosenlainterfazestnrealmentedisponiblesenla
clase.

Tambinhayqueobservarqueelcompiladorhayatenidoencuentaeltipoargumentoutilizadoparaladeclaracin
delaclase,yaquenosreclamalapresenciadeunafuncinllamadacompareyesperacomoparmetrounobjeto
detipoPersona(eltipoargumentoespecificadoenelmomentodeladeclaracindelaclase).

Dehecho,sepuedesimplificarmuchoelcdigodelafuncincomparerespectoaldelaversinnogenricadela
clase,yaqueyanonecesitaefectuarunaoperacindeconversinexplcitaantesdeutilizarelparmetrorecibido
porlafuncin.

Public Function compare(ByVal o1 As Persona) As Integer


Implements ComparableGenerica(Of Persona).compare
Return o1._apellido.CompareTo(_apellido)

End Function

3.Procedimientosyfuncionesgenricos

Losprocedimientosofuncionesgenricossonmtodosdefinidosconalmenosuntipoparmetro.Estopermiteal
cdigo que los llama especificar el tipo de datos que necesita en cada llamada del procedimiento o funcin. Sin
embargo,sepuedeutilizarestemtodosinindicarinformacinparaeltipoargumento.Enestecaso,elcompilador

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
intenta determinar el tipo en funcin de los argumentos pasados al mtodo. Esta solucin se debe utilizar con
precaucin,yaque,sielcompiladornopuededeterminareltipodelosargumentos,generaunerrordecompilacin.

a.Creacindeunprocedimientoofuncingenrico

La declaracin de un procedimiento o funcin genrico debe contener al menos un tipo parmetro. Este tipo
parmetro se define utilizando la palabra clave Of seguida por un identificador. A continuacin se utiliza este
identificadorenelrestodelcdigocadavezquenecesiteutilizareltipoparmetro.

Vamosacrearunafuncingenricacapazdebuscarunelementoparticularenunamatrizdecualquiertipo.Esta
funcin va a utilizar un tipo parmetro que indica la naturaleza de los elementos presentes en la matriz. Para
poder buscar un elemento en la matriz, deberemos compararlo con los presentes en todas sus casillas. Para
garantizarqueestacomparacinserposible,aadimosunalimitacineneltipoparmetro:debeimplementarla
interfazIcomparableconelfindeasegurarqueelmtodoCompareToutilizadoenlafuncinestdisponiblepara
cadaelementodelamatriz.

Ladeclaracindelafuncintomalaformasiguiente:

Public function busquedaGenerica(Of tipo As Icomparable) (byval


matriz As tipo(), elementoBuscado As tipo) As Integer

Despus de haber comprobado que la matriz contiene al menos un elemento, debemos comparar el elemento
buscadoconaquelpresenteencadacasilladelamatrizSihayigualdad,lafuncindevuelveelndicedondeseha
encontrado el elemento si no, la funcin devuelve 1. Para efectuar la comparacin, utilizaremos la funcin
CompareTodecadaelementodelamatriz.

Public Function busquedaGenerica(Of tipo As Icomparable)(ByVal matriz


As tipo(), ByVal elementoBuscado As tipo) As Integer
comprobar si la matriz tiene ms de una dimensin
If matriz.Rank() > 1 Then
Return -1
End If
comprobamos si la matriz est vaca
If matriz.Length = 0 Then
Return -1
End If
For i As Integer = 0 To matriz.GetUpperBound(0)
If matriz(i).CompareTo(elementoBuscado) = 0 Then
Return i
End If
Next Return -1
End Function

b.Utilizacindeunprocedimientoofuncingenrico

Lautilizacindeunprocedimientoofuncingenricoesidnticaaladeunprocedimientoofuncinclsico,salvo
queesnecesariodeespecificaruntipoargumentoparalostiposparmetro.

Elsiguientecdigopermiteprobarelcorrectofuncionamientodenuestrafuncin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Public Sub main()
Dim t() As Integer = {12, 45, 85, 47, 62, 95, 81}
Dim resultado As Integer
resultado = busquedaGenerica(Of Integer)(t, 47)
If resultado = -1 Then
Console.WriteLine("valor no encontrado")
Else
Console.WriteLine("valor encontrado en la posicin {0}",
resultado)
End If
Console.ReadLine()
Dim s() As String = {"uno", "dos", "tres", "cuatro", "cinco"}
resultado = busquedaGenerica(Of String)(s, "seis")
If resultado = -1 Then
Console.WriteLine("valor no encontrado")
Else
Console.WriteLine("valor encontrado en la posicin {0}",
resultado)
End If
Console.ReadLine()
End Sub

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Delegadosgenricos

Comocualquierotroelemento,undelegadopuededefinirunostiposparmetroensudeclaracin.Cuandoseutiliza
eldelegado,hayquefacilitarunostiposargumentoparacadaunodesustiposparmetro.Elsiguienteextractode
cdigodeclaraundelegadogenrico.

public Delegate Function comparacion(Of tipo)(ByVal


p1 As tipo, ByVal p2 As tipo) As Integer

Acontinuacinsepuedeutilizarestedelegadoenladeclaracindeunmtodoquefaciliteuntipoargumentopara
cadaunodesustiposparmetro.

Public Sub tri(ByVal matriz() As Cliente, ByVal comparador As


comparacion(Of Cliente))
Dim i As Integer
Dim j As Integer
Dim c As Cliente
For i = 0 To UBound(matriz) - 1
For j = i + 1 To Ubound(matriz)
If comparador.Invoke(matriz(j), matriz(i)) < 0 Then
c = matriz(j)
matriz(j) = matriz(i)
matriz(i) = c
End If
Next
Next
End Sub

Parapoderllamarestafuncindeordenacin,hayquefacilitarlecomoprimerparmetrounamatrizdeclientesyuna
funcinquerespetelafirmadeldelegadocomosegundoparmetro.

Function comparaCodigo(ByVal c1 As Cliente, ByVal c2 As Cliente) As


Integer
Select Case c1.codigo
Case Is < c2.codigo
Return -1
Case c2.codigo
Return 0
Case Else
Return 1
End Select
End Function

Dim del As comparador(Of Cliente)


del = New comparador(Of Cliente)(AddressOf comparaCodigo)
ordenacion(matriz, del)

Elcompiladorverificaquelafirmadelafuncinseacompatibleconladefinicindeldelegado.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Varianza

En programacin orientada a objetos, la varianza designa el hecho de utilizar un tipo de objetos que no se
corresponde exactamente con el esperado. Sin embargo, hay una pequea restriccin, ya que el tipo utilizado y el
tipoesperadodebenformarpartedelamismajerarquadeclase.As,eltipoutilizadopuedeserunsupertipodeltipo
esperadoounsubtipodeltipoesperado.Sieltipoutilizadoesunsupertipodeltipoesperado (tipomenosderivado),
hablamosdecontravarianza.Sieltipoutilizadoesunsubtipodeltipoesperado(tipomenosderivado),hablamosde
covarianza. Tomemos el ejemplo de una clase Persona y una de sus subclases, la clase Cliente. La covarianza
consisteenutilizarlaclaseClientedondeseesperalaclasePersona.Lacontravarianzaeseltrmiteinverso,yaque
consiste en utilizar la clase Persona donde se espera la clase Cliente. Las interfaces genricas y los delegados
genricosseencargandeestosdosmecanismosacontinuacin.Vamosadetallarestasdosnociones.

1.Varianzaenlasinterfacesgenricas

Parailustrartodoesto,utilizaremoslasdosclasesdefinidasacontinuacin:

Public Class Persona

Protected elApellido As String


Protected elNombre As String
Protected laFecha_naci As DateTime
Protected laContrasea As String

Public Sub New()


elApellido = ""
elNombre = ""
laContrasea = ""
End Sub

Public Sub New(ByVal apellido As String, ByVal nombre As String,


ByVal pwd As String)
elApellido = apellido
elNombre = nombre
laContrasea = pwd
End Sub

Public Sub New(ByVal apellido As String, ByVal nombre As String,


ByVal fNaci As DateTime)
elApellido = apellido
elNombre = nombre
laFecha_naci = fNaci
End Sub
Public Property apellido As String
Get
Return elApellido
End Get
Set(ByVal value As String)
elApellido = value.ToUpper()
End Set
End Property

Public Property nombre As String

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Get
Return elnombre
End Get
Set(ByVal value As String)
elnombre = value.ToLower
End Set
End Property
Public Property fecha_naci As DateTime
Get
Return laFecha_naci
End Get
Set(ByVal value As DateTime)

End Set
End Property
Public ReadOnly Property age As Integer
Get
Return DateTime.Now.Year - laFecha_naci.Year
End Get
End Property
Public WriteOnly Property contrasea As String
Set(ByVal value As String)
laContrasea = value
End Set
End Property
End Class

Public Class Cliente


Inherits Persona
Private elNumero As Integer
Public Property numero As Integer
Get
Return elNumero
End Get
Set(ByVal value As Integer)
elNumero = value
End Set
End Property
End Class

Contravarianzaenlasinterfacesgenricas

Lasdosclasesdefinidasanteriormentesecompletanahoraconlasiguienteinterfazgenrica.

Interface ComparadorGenerico(Of tipo)


Function compare(ByVal o1 As tipo, ByVal o2 As
tipo) As Integer
End Interface

Lasclasesqueimplementanestainterfazdebernconteneralmenoselmtodocompare.Ahoravamosacreardos

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
clasescapacesdecompararPersonasoClientesalimplementarlainterfazComparadorGenericoconlaclasePersona
oClientecomotipoargumento.Lacomparacindelaspersonasseharsegnelapellidoylacomparacindelos
clientessegnelnmero.

Public Class ComparadorPersona


Implements ComparadorGenerico(Of Persona)

Public Function compare(ByVal p1 As Persona, ByVal p2 As


Persona) As Integer Implements ComparadorGenerico(Of
ConsolaAplicacion1.Persona).compare
Return p1.apellido.CompareTo(p2.apellido)
End Function
End Class

Public Function compare(ByVal c1 As Cliente, ByVal c2 As Cliente) As


Integer Implements ComparadorGenerico(Of
ConsolaAplicacion1.Cliente).compare
If c1.numero > c2.numero Then
Return -1
ElseIf c1.numero < c2.numero Then
Return 1
Else
Return 0
End If
End Function

Nuestraltimaetapaconsisteencrearunmtodoutilizandonuestrainterfazgenricacomoparmetro.Paraello,
aadimos la siguiente funcin, que verifica la igualdad de dos clientes en funcin del comparador que se le pasa
comoprimerargumento.

Public Sub verifIgualdad(ByVal c As ComparadorGenerico(Of


Cliente), ByVal c1 As Cliente, ByVal c2 As Cliente)

If c.compare(c1, c2) = 0 Then


Console.WriteLine("los dos son idnticos")
Else
Console.WriteLine("los dos son diferentes")
End If

End Sub

SolonosquedaprobarestoalcreardosinstanciasdelaclaseClienteyalintentarcompararlasconelnmerode
clientecomocriterio.Paraello,utilizaremosunainstanciadelaclaseComparadorCliente.

Dim c1, c2 As Cliente


c1 = New Cliente()
c1.numero = 10
c1.apellido = "garca"
c2 = New Cliente()

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
c2.numero = 10
c2.apellido = "garca"
verifIgualdad(New ComparadorCliente(), c1, c2)

Nuestrocdigofuncionacorrectamente,yaqueobtenemoselsiguientemensajeenlaconsola.

los dos clientes son idnticos

Si ahora queremos comparar nuestros dos clientes segn su apellido, en lugar de hacerlo segn su nmero,
podemos utilizar la clase ComparadorPersona, ya que el mtodo compare, definido en esta clase, espera como
parmetros dos instancias de la clase Persona por tanto, si le facilitamos dos instancias de la clase Cliente,
funcionardelamismamanera:nuestrasinstanciasdelaclaseClientedisponendeunapellidodebidoalarelacin
deherenciaconlaclasePersona.Sinembargo,elcompiladornotienelamismaopininquenosotrosydetectaun
error.

Enrealidad,lafuncinverifIgualdadesperacomoprimerparmetroundelegadocapazdetrabajarconClientesy,
en cambio, le facilitamos nicamente un delegado capaz de trabajar con Personas. Utilizamos la clase Persona
dondeseesperalaclaseCliente,portantoestamosenpresenciadeunacontravarianza.Paraqueelcompiladorla
acepte,esindispensableaadirlapalabraclaveinenladeclaracindelainterfazgenrica.

Interface ComparadorGenerico(Of tipo)


Function compare(ByVal o1 As tipo, ByVal o2
As tipo) As Integer
End Interface

Sinembargo,solopuededeclararuntipocomocontravarianteenunainterfazoundelegadogenrico,siseutiliza
comotipodeargumentodemtodo.Enningncasosepuedeutilizarcomotipoderetornodeunmtodo.

Si modificamos nuestra interfaz agregando un mtodo que utilice el tipo contravariante como tipo de retorno,
obtenemosunerrordecompilacin.

Covarianzaenlasinterfacesgenricas

Para ilustrar la covarianza en las interfaces genricas, vamos a crear una nueva interfaz que defina el mtodo
creacionInstancia.Estemtododeberdevolver,enlasclasesqueimplementarnestainterfaz,unainstanciadel
tipoargumentoutilizadodurantelaimplementacindelainterfaz.

Public Interfaz IFabrica1(Of tipo)

Function CrearInstancia() As tipo

End Interface

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Acontinuacinestainterfazseimplementaconlasiguienteclase.

Public Class Fabrica(Of tipo As New)


Implements IFabrica(Of tipo)
Public Function CrearInstancia() As tipo Implements
IFabrica(Of tipo).CrearInstancia
Return New tipo()
End Function
End Class

Enestaclase,hayqueobservarquehemosaadidounarestriccinsobreeltipoparmetroparaestarsegurosde
quelaclaseutilizadacomotipoargumentodisponecorrectamente deunconstructorpordefecto.

AhorapodemoscrearunainstanciadeestaclaseyutilizarlaparaproducirinstanciasdelaclasePersona.

Dim fPersona As IFabrica(Of Persona)


fPersona = New Fabrica(Of Persona)()
Dim p As Persona
p = fPersona.CrearInstancia()

EstecdigosecompilasinerrorynospermiteobtenercorrectamenteinstanciasdelaclasePersona.Simodificamos
estecdigoparacrearunobjetoFabricadeCliente,obtenemosunerrordecompilacin.

Efectivamente,intentamosasignaraunavariabledetipoIFabrica<Persona>unainstanciadeIFabrica<Cliente>.
En realidad, estamos utilizando la covarianza al especificar un tipo ms derivado que el esperado. Para que el
compiladoracepteestasituacin,hayqueutilizarlapalabraclaveoutenladeclaracindelainterfazgenrica.

Public Interfaz IFabrica1(Of Out tipo)

Function CrearInstancia() As tipo

End Interface

Sinembargo,estatcnicacomportaunalimitacin,yaqueeltipodeclaradocovariantesolosepuedeutilizarcomo
tipoderetornodeunafuncin.Siseutilizacomotipoparaunparmetrodemtodo,elcompiladoractivaunerror.

2.Varianzaenlosdelegadosgenricos

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Como las interfaces genricas, los delegados genricos se encargan de la contravarianza y covarianza. As es
posible utilizar para un delegado genrico un tipo ms derivado o un tipo menos derivado que el esperado. Las
limitacionessonlasmismasqueparalasinterfacesgenricas,yaqueuntipomenosderivadosolosepuedeutilizar
comoparmetrodeundelegadogenricoyuntipomsderivadoqueelesperadosolosepuedeutilizarcomotipo
deretornodeunafuncingenrica.

Contravarianzaenlosdelegadosgenricos

Para ilustrar la contravarianza en los delegados genricos, vamos a utilizar el ejemplo usado para los delegados
genricos:

public Delegate Function comparacion(Of tipo)(ByVal p1


As tipo, ByVal p2 As tipo) As Integer

Public Sub ordena(ByVal matriz() As Object, ByVal comparador As


comparacion (Of Client))
Dim i As Integer
Dim j As Integer
Dim o As Object
For i = 0 To UBound(matriz) - 1
For j = i + 1 To UBound(matriz)
If comparador.Invoke(matriz(j), matriz(i)) < 0 Then
o = matriz(j)
matriz(j) = matriz(i)
matriz(i) = o
End If
Next
Next
End Sub

Para efectuar nuestro test, aadimos una funcin que respete la firma del delegado y permita realizar la
comparacindedosPersonassegnsuapellido.

Public Function compareApellido(ByVal p1 As Persona, ByVal p2 As


Persona) As Integer

Return p1.apellido.CompareTo(p2.apellido)

End Function

AhorasolonosquedautilizartodoelloparaordenarunamatrizdeClientes:

Dim matriz(4) As Cliente


matriz(0) = New Cliente("pepe2", "nombre2 ", "secreto", 2)
matriz(1) = New Cliente("pepe1", "nombre1 ", "secreto", 1)
matriz(2) = New Cliente("pepe5", "nombre5 ", "secreto", 5)
matriz(3) = New Cliente("pepe3", "nombre3 ", "secreto", 3)

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
matriz(4) = New Cliente("pepe4", "nombre4 ", "secreto", 4)
Dim fct As comparacion(Of Persona)
fct = New comparacion(Of Persona)(AddressOf compareApellido)
ordenacion(matriz, fct)

Como no hemos tomado precauciones particulares, cuando llamamos la funcin de ordenacin pasndole como
parmetro una instancia de delegado que trabaja con objetos Persona, mientras que la funcin esperaba una
instanciadedelegadoquetrabajaconClientes,elcompiladorgeneraunerror.

Paraqueelcompiladorautoricelacontravarianza,hayqueutilizarlapalabrainenladeclaracindeldelegado.

Public Delegate Function comparacion(Of tipo)(ByVal p1


As tipo, ByVal p2 As tipo) As Integer

Comoparalasinterfacesgenricas,untipopuededeclararsecontravariantenicamentesiseutilizacomotipode
argumentosdemtodo.Enningncasosepuedeutilizarcomotipoderetornodeunmtodo.

Covarianzaenlosdelegadosgenricos

Para ilustrar el funcionamiento de la covarianza en los delegados genricos, vamos a crear una funcin capaz de
devolver una matriz rellenada con instancias de una clase particular. La creacin de las instancias de clase
necesariaspararellenarlamatrizserconfiadaaundelegado.

Eldelegadogenricocorrespondientepuedetenerlasiguienteforma:

Public Delegate Function construccion(Of tipo As New)()


As tipo

Larestriccineneltiponosimponetenerunconstructorpordefectoenlaclasecorrespondiente.

Ahorapodemosescribirdosfuncionesquerespetenlafirmadeldelegado.

Public Function fabricacionCliente() As Cliente

Return New Cliente()

End Function

Public Function fabricacionPersona() As Persona

Return New Persona()

End Function

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Ahora solo nos queda escribir la funcin que permite la creacin de una matriz. Esta funcin espera como primer
parmetro el tamao de la matriz, y como segundo parmetro, el delegado encargado de crear las instancias de
clasequesirvenpararellenarlamatriz.Estafuncindevuelvelamatrizrellenada.

Public Function LlenarMatriz(ByVal tamao As Integer, ByVal cc


As construccion(Of Persona)) As Persona()
Dim i As Integer
Dim matriz(tamao) As Persona

For i = 0 To tamao - 1
matriz(i) = cc.Invoke()
Next
Return matriz
End Function

Ahorapodemosutilizarestoconlaspocaslneasdecdigosiguientes.

Dim cp Asconstruccion(OfPersona);
cp = AddressOf fabricacionPersona;
Dim matriz() As Persona

matriz = LlenarMatriz(5, cp)

Elcompiladornotienenadaquedecirencontradeestecdigo.

Ahora podemos intentar rellenar la matriz no con instancias de la clase Persona, sino con instancias de la clase
Cliente. Gracias a la relacin de herencia entre estas dos clases, una casilla de la matriz se puede utilizar para
referenciarunainstanciadelaclasePersona,perotambinunainstanciadecualquieradeestassubclases,yporlo
tantodelaclaseCliente.

Podemosescribirentodaconfianzaelcdigosiguiente:

Dim cp As construccion(Of Cliente)


cp = AddressOf fabricacionPersona
Dim tablo As Persona()
matriz = LlenarMatriz(5, cp)

Desafortunadamente, el compilador descubre el truco, ya que facilitamos a nuestra funcin una instancia de
delegadoqueutilizauntipomsderivadoqueelesperado.

Para que el compilador acepte esta manipulacin, hay que autorizarla aadiendo la palabra clave out en la
declaracindeldelegado.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Public Delegate Function construccion(Of tipo As
New)() As tipo

Como para la covarianza con las interfaces genricas, se aplica una restriccin, ya que el tipo covariante solo se
puedeutilizarcomotipoderetorno,ynocomotipoparaunparmetrodemtodo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Lascolecciones

Lasaplicacionesnecesitanamenudomanipulargrandescantidadesdeinformacin.EnVisualBasicestndisponibles
muchasestructurasparafacilitarlagestindeestosdatos.Estnagrupadasbajoeltrminocoleccin.Comoenla
vidacorriente,haydiferentestiposdecoleccin.Puedehaberpersonasquecoleccionantodotipodecosas,perono
siguen ninguna organizacin especial al guardarlas otras personas estn especializadas en la coleccin de ciertos
tiposdeobjetos,yhaymanacosquetomantodaslasprecaucionesparapoderencontrarenseguidaunobjeto...

EnFramework.NETexistenclasesquesecorrespondenconcadaunadeestassituaciones.

1.Lascoleccionespredefinidas

Lasdiferentesclasesquepermitenlagestindelascoleccionesserepartenentredosespaciosdenombres:

l System.Collections

l System.Collections.Generic

El primero contiene las clases normales, mientras que el segundo contiene las clases genricas equivalentes que
permitenlacreacindecoleccionesmuycaractersticas.Estascoleccionesmuycaractersticasestnespecializadas
enlagestindeuntipodeterminadodedatos.Aunquenumerosasclasesofrecenfuncionalidadesdiferentes,tienen
muchos puntos en comn, ya que implementan las mismas interfaces. Por ejemplo, todas estas clases pueden
facilitarunobjetoenumeratorquepermiterecorrerelconjuntodelacoleccin.Eselobjetoqueutilizalainstruccin
For EachdeVisualBasic.

a.Array

La clase Array no es parte del espacio de nombres System.Collections, pero de todos modos puede ser
consideradacomocoleccin,porqueimplementalainterfazIlist.LasmatricescreadasapartirdelaclaseArray
tienendimensionesfijas,aunqueesposibleutilizarlainstruccinredimpararedimensionarunamatriz.Dehecho,
lainstruccinRedimnoamplalamatriz,sinoquecreaunanuevamsgrandeomspequeaycopialosvalores
existentes, si se usa la palabra clave Preserve. Esta clase tambin contiene muchos mtodos compartidos, que
permitenlaejecucindemuchasfuncionalidadesenlasmatrices.Existendospropiedadesmuytilesparaeluso
delaclaseArray:

l Length,querepresentaelnmerototaldeelementosenlamatriz.

l Rank,quecontieneelnmerodedimensionesdelamatriz.

EstaclaseseusapocoparalacreacindeunamatrizporqueseprefiereutilizarlasintaxisVisualBasic.

b.ArrayListyList

LaclaseArrayListosuversingenricaListsonevolucionesdelaclaseArray.Aportanmuchasmejorasrespeto
aestaltima.

l EltamaodeunArrayListesdinmicoyseajustaautomticamenteenfuncindelasnecesidades.Eltratamiento,
queparaunArraysedebarealizarconlainstruccinRedim,serealizaautomticamente.

l Propone mtodos que permiten agregar, insertar y suprimir varios elementos de manera simultnea en una sola
operacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Porelcontrario,enalgunospuntos,laclaseArrayListesmenoseficazqueunasimplematriz:

l LosArrayListsolotienenunadimensin.

l Una matriz de datos de un tipo especfico es ms eficaz que un ArrayList cuyos elementos se gestionan como
Object.Lautilizacindelaversingenrica(List)permiteobtenerrendimientosequivalentes.

Como cualquier clase, un ArrayList debe ser instanciado antes de poder utilizarlo. Dos constructores estn
disponibles. El primero es un constructor por defecto y crea un ArrayList con una capacidad inicial de cero. Se
dimensionaautomticamentealahoradeaadirelementos.Noseaconsejaestasolucin,yaquelaampliacin
del ArrayList consume muchos recursos. Si tiene una estimacin del nmero de elementos que es preciso
almacenar, es preferible utilizar el segundo constructor, que espera como parmetro la capacidad inicial del
ArrayList.Estoevitaeldimensionamientoautomticoenelmomentodeagregarelementos.

Luego se deben agregar los elementos llamando al mtodo Adddelaclase ArrayListo List para cada uno de
ellos.

Sepuedencombinarestasdosetapasfacilitandolosvaloresquesedebenalmacenarenellaenelmomentodela
instanciacindelArrayListodelaList.

Dim lst As New List(Of Integer) From {1, 2, 3, 4, 5}

Cuandoelcompiladoranalizaestalneadecdigo,enrealidadefectalasoperacionessiguientes :

Dim lst As New List(Of Integer)


lst.Add(1)
lst.Add(2)
lst.Add(3)
lst.Add(4)
lst.Add(5)

Tambinsepuedeutilizarestatcnicaparainicializarlistasdeobjetos.

Dim lstCliente As New List(Of Cliente) From


{
New Cliente("garca", "pablo", "password", 1),
New Cliente("prez", "pedro", "pwd", 2)
}

Incluso se puede mejorar evitando tener que crear las instancias de los objetos que se deben almacenar en la
lista.Paraello,essuficientevolveradefinirelmtodoAdddelalistaconlaformadeunmtododeextensinpara
queelcompiladorpuedallamarloalagregarelementosycrearlainstanciadecadaunodeellos.

<Extension()>
Sub add(ByVal lst As List(Of Client),
ByVal apellido As String,
ByVal nombre As String,
ByVal contrasea As String,
ByVal code As String)

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
lst.add(New Cliente With
{
.apellido = apellido,
.nombre = nombre,
.Contrasea = contrasea,
.codigo = codigo
})
End Sub

Ahorasepuedeutilizarlasintaxissiguienteparainstanciareinicializarunalistadeclientes.

Dim lstCliente As New List(Of Cliente) From


{
{"garca", "pablo", "password", 1},
{"prez", "pedro", "pwd", 2}
}

Hay que resaltar que la dimensin indicada no es definitiva y el ArrayList podr contener ms elementos que los
previstosinicialmente.

LapropiedadCapacitypermiteconocerelnmerodeelementosqueel ArrayListpuedecontener.Lapropiedad
Count indica el nmero actual de elementos en elArrayList. Los mtodos Addy AddRange aaden elementos al
finaldelalista.LosmtodosInserteInsertRangepermitenelegirlaubicacindondeseagregarnloselementos.
LapropiedadItem,queeslapropiedadpordefectodeclase,seutilizaparaasignarunelementoenunaposicin
dada. La supresin de elementos se hace por el mtodo RemoveAt o RemoveRange el primero espera como
parmetroelndicedelelementoquesedebesuprimir,elsegundoexigeademselnmerodeelementosquese
debensuprimir.ElmtodoClearesmsradicalysuprimetodosloselementos.

Elcdigosiguienteilustraelfuncionamientodeestaclase:

Public Sub main()


Dim lista As ArrayList
Dim c As Cliente
lista = New ArrayList()
Console.WriteLine("capacidad inicial de la lista {0}", lista.Capacity)
Console.WriteLine("nmero de elementos de la lista {0}", lista.Count)
Console.WriteLine("aadir un cliente")
c = New Cliente("cliente1", "nombre1", "secreto", 1001)
lista.Add(c)
Console.WriteLine("capacidad de la lista {0}", lista.Capacity)
Console.WriteLine("nmero de elementos de la lista {0}", lista.Count)
Console.WriteLine("aadir cuatro clientes")
c = New Cliente("cliente2", "nombre2", "secreto", 1002)
lista.Add(c)
c = New Cliente("cliente3", "nombre3", "secreto", 1003)
lista.Add(c)
c = New Cliente("cliente4", "nombre4", "secreto", 1004)
lista.Add(c)
c = New Cliente("cliente5", "nombre5", "secreto", 1005)
lista.Add(c)
Console.WriteLine("capacidad de la lista {0}", lista.Capacity)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Console.WriteLine("nmero de elementos de la lista {0}", lista.Count)
Console.WriteLine("mostrar la lista de clientes")
For Each c In lista
c.mostrar()
Console.WriteLine()
Next
Console.WriteLine("borrar clientes 1002, 1003, 1004")
lista.RemoveRange(1, 3)
Console.WriteLine("capacidad de la lista {0}", lista.Capacity)
Console.WriteLine("nmero de elementos de la lista {0}", lista.Count)
Console.WriteLine("mostrar la lista de clientes")
For Each c In lista
c.mostrar()
Console.WriteLine()
Next
Console.WriteLine("mostrar el segundo cliente de la lista")
lista(1).mostrar()
Console.WriteLine()
Console.WriteLine("borrar todos los clientes")
lista.Clear()
Console.WriteLine("capacidad de la lista {0}", lista.Capacity)
Console.WriteLine("nmero de elementos de la lista {0}", lista.Count)
Console.ReadLine()
End Sub

Muestraelresultadosiguiente:

capacidad inicial de la lista 0


nmero de elementos de la lista 0
aadir un cliente
capacidad de la lista 4
nmero de elementos de la lista 1
aadir cuatro clientes
capacidad de la lista 8
nmero de elementos de la lista 5
mostrar la lista de clientes
Sr cliente1 apellido1 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1001
Sr cliente2 apellido2 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1002
Sr cliente3 apellido3 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1003
Sr cliente4 apellido4 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1004
borrar los clientes 1002, 1003, 1004
capacidad de la lista 8
nmero de elementos de la lista 2
mostrar la lista de clientes
Sr cliente1 apellido1 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1001
Sr cliente5 apellido5 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1005
mostrar el segundo cliente de la lista
Sr cliente5 apellido5 nacido el 01/01/0001 00:00:00 cdigo de Cliente: 1005
Borrar todos los clientes
capacidad de la lista 8
nmero de elementos de la lista 0

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lacapacidaddelalistanodisminuyeconlasupresindeunelemento,inclusocuandolalistaestvaca.

c.HashtableyDictionary

Un Hashtable o su versin genricaDictionary registra los datos en forma de parejas clave valor. ElHashtable
est constituido internamente por compartimentos que contienen los elementos de la coleccin. Para cada
elementodelacoleccin,segenerauncdigomedianteunafuncinhashbasadaenlaclavedecadaelemento.
Luego se utiliza el cdigo para identificar el compartimento en el que se almacena el elemento. Durante la
bsquedadeunelementoenlacoleccin,seefectalaoperacininversa.Elcdigohashsegeneraapartirdela
clavedelelementobuscado.Estaclavesirvedespusparaidentificarelcompartimentoenelqueseencuentrael
elementobuscado.ParaqueunaHashtablepuedaalmacenarunobjeto,estedebesercapazdefacilitarsupropio
cdigohash.

d.Queue

Seutilizaestetipodecoleccincuandosenecesitaunespaciodealmacenamientotemporal.Cuandoserecupera
unelementoapartirdelacoleccin,sesuprimealmismotiempodeesta.

LascoleccionesdetipoQueueseadaptan,sinecesitaraaccederalosdatosenelmismoordenenquehansido
almacenadosenlacoleccin.EstetipodegestinsellamaavecesFirstInFirstOut(FIFO).Lastresprincipales
operacionesdisponiblesson:

l Enqueueparaagregarunelementoalfinaldelacola.

l Dequeueparaobtenerelelementomsantiguodelacolaysuprimirlo.

l Peekparaobtenerelelementomsantiguosinsuprimirlodelacola.

Elejemplosiguienteilustralautilizacindeestostresmtodos.

Public Sub main()


Dim q As Queue
q = New Queue
Dim c As Cliente
c = New Cliente("cliente1", "nombre1", "secreto", 1001)
Console.WriteLine("llegada del primer cliente:{0}", c.apellido)
q.Enqueue(c)
c = New Cliente("cliente2", "nombre2", "secreto", 1002)
Console.WriteLine("llegada del segundo cliente:{0}", c.apellido)
q.Enqueue(c)
c = New Cliente("cliente3", "nombre3", "secreto", 1003)
Console.WriteLine("llegada del tercer cliente:{0}", c.apellido)
q.Enqueue(c)
Console.WriteLine("salida del primer cliente:{0}",
q.Dequeue.apellido)
Console.WriteLine("quedan {0} clientes", q.Count)
Console.WriteLine("salida del segundo cliente:{0}",
q.Dequeue.apellido)
Console.WriteLine("quedan {0} clientes", q.Count)
Console.WriteLine("el tercer cliente se inserta:{0}",
q.Peek.apellido)
Console.WriteLine("quedan {0} clientes", q.Count)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Console.WriteLine("salida del tercer cliente:{0}",
q.Dequeue.apellido)
Console.WriteLine("quedan {0} clientes", q.Count)
Console.ReadLine()
End Sub

e.Stack

Las colecciones de este tipo utilizan el mismo principio que las Queue: cuando se recupera un elemento de la
coleccin,sesuprimedeella.LanicadistincinrespetoalaclaseQueueeselordenenelqueserecuperanlos
elementos. Este tipo de coleccin utiliza la tcnica Last In First Out (LIFO). El ejemplo clsico de este tipo de
gestin es la pila de platos de su cocina. Despus de fregar los platos, se guardan en una estantera. Al da
siguiente,alponerlamesa,elprimerplatodisponibleeselltimo,queguarddeldaanterior.

Lastresprincipalesoperacionesdisponiblesson:

l Pushparaagregarunelementoencimadelapila.

l Popparaobtenerelelementoencimadelapilaysuprimirlo.

l Peekparaobtenerelelementoencimadelapilasinsuprimirlodelapila.

2.Elegiruntipodecoleccin

Acontinuacinledamosunosconsejosparaelegireltipodecoleccinquemsseadapteasusnecesidades.

l Necesitaaccederaloselementosdelacoleccinconunndice:utiliceunArrayList.

l El acceso a los elementos se debe efectuar en el orden en que han sido agregados a la coleccin o en el orden
inverso:utiliceunQueueounStack.

l Necesitaordenartodosloselementosenunordendiferentedeaquelenelquesonaadidosalacoleccin:utiliceun
ArrayListounHashtable.

l Loselementosquesehandealmacenarenlalistasonparejasclaveelemento:utiliceunHashtable.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Losobjetosintrnsecos

Existen numerosos objetos disponibles automticamente a partir de Visual Basic, sin que se tenga que crear una
instancia.EstosobjetossonaccesiblesconlapalabraclaveMy.Permitenlamanipulacinyelaccesoadatosquese
utilizanfrecuentementeduranteelfuncionamientodeunaaplicacin.Proporcionan,porejemplo,unmediodeacceso
alaspropiedadesdelamquinaenlaqueseejecutalaaplicacin,atravsdeMy.Computer,oalaspropiedadesde
la propia aplicacin a travs deMy.Application. En funcin del tipo de proyecto en el que trabaja, es posible que
algunos objetos no estn disponibles. La siguiente tabla presenta los objetos existentes y el contexto en el que
estndisponibles.

Aplicacinde Bibliotecade Aplicacinde Bibliotecade Serviciode


Windows clases consola controlesde Windows
Windows

My.Application S S S S S

My.Computer S S S S S

My.Forms S No No S No

My.Resources S S S S S

My.Settings S S S S S

My.User S S S S S

My.WebServices S S S S S

Segneltipodeproyectoenelqueseutilizan,algunaspropiedadesdeestosobjetospuedennoestardisponibles.
Porejemplo,lapropiedadMainFormdelobjetoApplicationsolosepuedeutilizarenlosproyectosdeaplicacionesde
Windows.

l El objeto Application proporciona propiedades, mtodos y eventos relativos a la aplicacin en curso. Permite, por
ejemplo, recuperar informacin sobre la configuracin lingstica de la aplicacin, los parmetros de la lnea de
comandosutilizadosparalanzarlaaplicacinolainformacinrelativaalaversindelaaplicacin.

l El objetoComputer ofreceaccesoalosdiferentesrecursosenlamquina.Permite,porejemplo,accederdirectamente
alsistemadeaudiodelamquina,alteclado,alratnoalared.

l El objeto Formsponeasudisposicinunainstanciadecadaunadelasventanasdisponiblesenelproyecto.Elacceso
serealizaatravsdelnombredeclasecorrespondientealaventana,queseconvierteasenunapropiedaddelobjeto
Forms.

l El objeto Resources permite acceder a los recursos de audio, a los iconos y a las imgenes y cadenas de caracteres
definidasaniveldelproyecto.

l ElobjetoSettingspermiteaccederalosparmetrosdelaaplicacindefinidosporlaspropiedadesdelproyecto.

l ElobjetoUser representaelusuariodelaaplicacin.Sinoseutilizaningunaautenticacinespecficaenlaaplicacin,el
objetoUsercorrespondealusuarioconelquesehaabiertolasesindeWindows.

l ElobjetoWebservicesfacilitaunainstanciadecadaservicioWebreferenciadoenlaaplicacin.Comoparalapropiedad
Forms,elaccesoseefectaatravsdelnombredelservicioWeb.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Losdiferentestiposdeerrores

Paraundesarrollador,loserroressonunadelasprincipalesfuentesdeestrs.Enrealidad,podemosclasificarestos
erroresentrescategoras.Vamosavercadaunadeellas,ascomolassolucionesdisponiblespararesolverlos.

1.Loserroresdesintaxis

Estetipodeerroresseproduceenelmomentodelacompilacin,cuandounapalabraclavedellenguajeestmal
escrita. Eran muy frecuentes con las primeras herramientas de desarrollo, en las que el editor de cdigo y el
compiladorerandosentidadesseparadas.AhorasoncadavezmsrarosenlosentornossimilaresaVisualStudio.
La mayora de estos entornos ofrecen un anlisis sintctico mientras se escribe el cdigo. Desde este punto de
vista,VisualStudioproporcionamuchasfuncionalidadesquenospermiteneliminarestetipodeerrores.

As,porejemplo,controlaquecadainstruccinIfseacabecorrectamenteconunEnd If.

Sidetectaunerrordesintaxis,VisualBasicproponelasposiblessolucionesparacorregirlo.Sepuedenverhaciendo
cliceneliconoasociadoalerror.

Porotraparte,loserroresdeortografaenlosnombresdepropiedadesomtodosseeliminanfcilmentegracias
alasfuncionalidadesIntelliSense.IntelliSenseseencargade:

l Mostrarautomticamentelalistadelosmiembrosdisponibles.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
l Mostrarlalistadeparmetrosquesepuedenfacilitarparalallamadadeunprocedimientoofuncin:

Si un mtodo est sobrecargado, IntelliSense muestra su nmero y le permite recorrerlos utilizando las flechas
arribayabajodelteclado.

l Mostrarinformacinpuntualacercadelosmiembrosdeunaclase:

l Completarautomticamentelaspalabras:empieceporescribirelprincipiodepalabra,luegoutilicelacombinacinde
teclas[Ctrl][Espacio]paramostrartodoloquepuedeutilizarcomopalabraeneseemplazamiento,queempiezacon
loscaracteresyaelegidos.Sisolohayunaposibilidad,lapalabraseaadeautomticamentesino,seleccineladela
listayvalideconlatecla[Tab].

l Mostrarlalistadelosposiblesvaloresparaunapropiedaddetipoenumeracin.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Contodasestasfuncionalidades,esprcticamenteimposiblegenerarerroresdesintaxisenelcdigo.

2.Loserroresdeejecucin

Estoserroresaparecendespusdelacompilacin,cuandodecidelanzarlaejecucindesuaplicacin.Lasintaxis
delcdigoescorrecta,peroelentornodesuaplicacinnopermitelaejecucindeunainstruccinqueestautilice.
Estoocurre,porejemplo,cuandoseintentaabrirunarchivoquenoexisteeneldiscodesumquina.Seguramente
obtengauncuadrodedilogodeestetipo,nomuyagradableparaelusuario:

Afortunalmente, Visual Basic permite la recuperacin de este tipo de error y evita as la visualizacin de este
inquietantecuadrodedilogo.Existendostcnicasparalagestindeestetipodeerrores:

l Lagestinenlnea.

l Lasexcepciones.

Lasveremosendetallemsadelanteenestecaptulo.

Loserroresdelgica

Los peores enemigos de los desarrolladores. Todo se compila sin problema, todo se ejecuta sin problema y, sin
embargo,nofunciona!!

En este caso, conviene revisar la lgica de funcionamiento de la aplicacin. Las herramientas de depuracin nos
permitenseguireldesarrollodelaaplicacin,ubicarpuntosdeparada,visualizarelcontenidodelasvariables,etc.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Tratamientodeloserrores

ExistendostcnicasparaeltratamientodeloserroresdeVisualBasic:

l Lagestinenlnea.

l Eltratamientodelaexcepcin.

1.Lagestinenlnea

La instruccin On Error es el elemento bsico de la gestin de los errores en lnea. Cuando esta instruccin se
ejecuta en un procedimiento o funcin, activa la gestin de los errores para ese procedimiento o funcin. Sin
embargo, conviene indicar a nuestro gestor cmo debe reaccionar cuando una instruccin desencadena un error.
Haydossoluciones:

On error resume next

Laejecucindelcdigoseguirporlalneaposterioralaquehaprovocadoelerror.

On error goto etiqueta

Laejecucindelcdigopasaralalneasealadaconetiqueta.

Lasintaxises,portanto,lasiguiente:

Private Sub Nombre_de_procedimiento()


On Error Goto gestionErrores
...
"Instrucciones peligrosas"
...
Exit Sub
gestionErrores:
...
cdigo que gestiona los errores
...
End Sub

Laetiquetahacialaqueelgestordeerroresdirigirlaejecucinsedebeencontrarenelmismoprocedimientoque
lainstruccinon error goto.LainstruccinExit subes obligatoriaparaqueelcdigodegestindeerroresnose
ejecutedespusdelasinstrucionesnormales,sinosoloenelcasodeerrores.

Elcdigodelgestordeerroresdebedeterminarelcomportamientoquehayqueseguirenelcasodeerror.

Tressoluciones:

Resume

Sevuelveaintentarlaejecucindelalneaquehaproducidoelerror.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
resume next

Sesigueconlaejecucinenlalneaquesiguealaquehaprovocadoelerror.

exit suboexit function

Separalaejecucindeesteprocedimientoofuncin.

Normalmente,elgestordeerroresmuestrauncuadrodedilogoquelepreguntaalusuarioququierehacer.

Enfuncindesurespuesta,seutilizarunasolucinuotra.

Private Sub AbrirArchivo()


On Error GoTo gestionErrores
My.Computer.FileSystem.OpenTextFileReader("c:\prueba")
Exit Sub
gestionErrores:
Dim respuesta As Integer
respuesta = MsgBox("no se puede leer el archivo",
MsgBoxStyle.AbortRetryIgnore)
Select Case respuesta
Case MsgBoxResult.Retry
Resume
Case MsgBoxResult.Ignore
Resume Next
Case MsgBoxResult.Abort
Exit Sub
End Select
End Sub

Nosquedatodavaunproblemaporresolver:nuestrogestordeerroresreaccionarindependientementedelerror.
Parapoderdeterminarquerrorseacabadeproducirenlaaplicacin,tenemosanuestradisposicinelobjetoerr,
que nos proporciona informacin sobre el ltimo error que ha aparecido. Este objeto contiene, entre otras, dos
propiedades, number y description, que nos permiten obtener el cdigo del error y su descripcin. Podemos
modificarentoncesnuestrocdigoparaquereaccionedemaneradiferenteenfuncindelerror.

Private Sub AbrirArchivoBis()


On Error GoTo gestionErrores
My.Computer.FileSystem.OpenTextFileReader("a:\prueba")
Exit Sub
gestionErrores:
Dim respuesta As Integer
Console.WriteLine(Err.Number)
Stop
If Err.Number = 53 Then
respuesta = MsgBox("no se ha encontrado el archivo", MsgBoxStyle.
AbortRetryIgnore)
Select Case respuesta
Case MsgBoxResult.Retry
Resume
Case MsgBoxResult.Ignore

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Resume Next
Case MsgBoxResult.Abort
Exit Sub
End Select
End If
If Err.Number = 57 Then
respuesta = MsgBox("insertar un disco en el lector",
MsgBoxStyle.OKCancel)
Select Case respuesta
Case MsgBoxResult.OK
Resume
Case MsgBoxResult.Cancel
Exit Sub
End Select
End If
End Sub

Sepuededesactivarungestordeerroresutilizandolainstruccinon error goto 0.Siseproduceunerrordespus


deestainstruccin,noserecuperaylaaplicacinsedetiene.

Dehecho,laaplicacinnoseparainmediatamente,sinoqueVisualBasicbuscaenlasfuncionesdellamadasihay
ungestordeerroresactivo.Siencuentrauno,leencargalagestindelerror.

Private Sub procedimiento1()


On Error GoTo gestionErrores
procedimiento2()
Exit Sub
gestionErrores:
MsgBox("error de ejecucin")
End Sub
Private Sub procedimiento2()
Dim x, y As Integer
x = 0
y = (1 / x)
End Sub

Enesteejemplo,procedimiento2ejecutarunainstruccinqueactivaunerror(1/x).Comonoexisteungestorde
errores en este procedimiento, Visual Basic busca entre las llamadas si existe un gestor activo. El primero que
encuentraestenelprocedimiento1seresteelqueseencargardelagestindelerror.

2.Lasexcepciones

a.Recuperacindeexcepciones

Lagestindelasexcepcionesdalaposibilidaddeprotegerunbloquedecdigocontraloserroresdeejecucin
quepodranproducirse.ElcdigopeligrososedebecolocarenunbloqueTry End Try.Siseactivaunaexcepcin
en este bloque de cdigo, Visual Basic mira las siguientes instrucciones catch. Si existe una capaz de tratar la
excepcin, el cdigo correspondiente se ejecuta de otra forma, la misma excepcin se activara para ser
recuperada en un bloque Try End Try, de nivel ms alto. Una instruccin finally permite marcar un grupo de
instrucciones,ejecutadasantesdelasalidadelbloquetry,tantosisehaproducidounerrorcomosino.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Portanto,lasintaxisgeneraleslasiguiente:

Try
...
Instrucciones peligrosas
...
catch excepcion1
...
cdigo ejecutado si se produce una excepcin de tipo Excepcion1
...
catch excepcion2
...
cdigo ejecutado si se produce una excepcin de tipo Excepcion2
...
Finally
...
cdigo ejecutado siempre antes de salir del bloque Try
...
End Try

EstaestructuratieneunfuncionamientomuyparecidoalSelect casequeyahemosestudiado.Cadatipodeerror
se asocia a un tipo de exceptin y, cuando se produce este error, se crea una instancia de la clase Exception
correspondiente.Podremosdeterminar,paracadainstruccinCatch,qutipodeexcepcindebetratar.

LaclasedebaseeslaclaseExceptiondesdelaquesecreaunaseriedesubclasesespecializadas,cadaunapara
untipodeerrorparticular.Acontinuacin,presentamoslalistadelasclasesquederivandirectamentedelaclase
Exception.

l Microsoft.Build.BuildEngine.InternalLoggerException

l Microsoft.Build.BuildEngine.InvalidProjectFileException

l Microsoft.Build.Framework.LoggerException

l Microsoft.JScript.CmdLineException

l Microsoft.JScript.ParserException

l Microsoft.VisualBasic.ApplicationServices

l Microsoft.VisualBasic.ApplicationServices.NoStartupFormException

l Microsoft.VisualBasic.CompilerServices.IncompleteInitialization

l Microsoft.VisualBasic.CompilerServices.InternalErrorException

l Microsoft.VisualBasic.FileIO.MalformedLineException

l Microsoft.WindowsMobile.DirectX.DirectXException

l System.ApplicationException

l System.ComponentModel.Design.ExceptionCollection

l System.Configuration.Provider.ProviderException

l System.Configuration.SettingsPropertyCannotBeSetForAnonymousUserException

l System.Configuration.SettingsPropertyIsReadOnlyException

l System.Configuration.SettingsPropertyNotFoundException

l System.Configuration.SettingsPropertyWrongTypeException

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
l System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectExistsException

l System.DirectoryServices.ActiveDirectory.ActiveDirectoryObjectNotFoundException

l System.DirectoryServices.ActiveDirectory.ActiveDirectoryOperationException

l System.DirectoryServices.ActiveDirectory.ActiveDirectoryServerDownException

l System.DirectoryServices.Protocols.DirectoryException

l System.IO.IsolatedStorage.IsolatedStorageException

l System.Net.Mail.SmtpException

l System.Runtime.Remoting.MetadataServices.SUDSGeneratorException

l System.Runtime.Remoting.MetadataServices.SUDSParserException

l System.SystemException

l System.Web.Security.MembershipCreateUserException

l System.Web.Security.MembershipPasswordException

l System.Web.UI.ViewStateException

l System.Windows.Forms.AxHost.InvalidActiveXStateException

Esta lista solo presenta el primer nivel de la jerarqua. Cada una de estas clases tambin tiene muchos
descendientes.

Estasexcepcionesseutilizanparaindicar,encadainstruccinCatch,eltipodeexcepcinquedebegenerar.

Private Sub AbrirArchivo()


Try
My.Computer.FileSystem.OpenTextFileReader("a:\prueba")
Catch ex As System.IO.IOException
MsgBox("error al abrir el archivo", MsgBoxStyle.OKOnly)
Finally
MsgBox("fin del procedimiento de apertura de un archivo")
End Try
End Sub

SientretodaslasCatchningunasecorrespondeconlaexcepcingenerada,laexcepcinsepropagaalcdigode
los procedimientos o funciones de llamadas, a la bsqueda de una instruccin Catch capaz de tomar en
consideracinestaexcepcin.Sinoseencuentraningnbloque,seactivaunerrordeejecucin.

LosbloquesCatchtambinpuedensercondicionales,aadiendolapalabraWhenseguidaporunaexpresinque
sepuedaevaluarcomounbooleano.

Catch ex As Exception When condicin < 0


...
Catch ex As Exception When condicin > 10
...
End Try

ElbloqueCatchseejecutasiseactivaunaexcepcindeestetipoysisecumplelacondicin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
SielparmetroindicadoenlainstruccinCatchesunaclasedeexcepcingeneral,estainstruccinCatchser
capazdecapturartodaslasexcepcionescreadasapartirdeestaclaseodeestassubclases.Elsiguientecdigo
nospermitecapturartodaslasexcepciones.

Private Sub AbrirArchivo()


Try
My.Computer.FileSystem.OpenTextFileReader("a:\prueba")
Catch ex As Exception
MsgBox("error al abrir el archivo", MsgBoxStyle.OKOnly)
Finally
MsgBox("fin del procedimiento de apertura de un archivo")
End Try
End Sub

Lasdiferentesclasesdisponendelassiguientespropiedadesquenospermitentenermsdatossobreelorigen
delaexcepcin.

Message

Cadenadecaracteresasociadaalaexcepcin.

Source

Nombredelaaplicacinqueactivlaexcepcin.

StackTrace

Listadetodoslosmtodosporlosquehapasadolaaplicacinantesdelaactivacindelerror.

TargetSite

Nombredelmtodoqueactivlaexcepcin.

InnerException

Obtienelaexcepcinoriginalsiseactivandosexcepcionesencascada.

b.Creacinyactivacindeexcepciones

Las excepciones son, ante todo, clases. Por lo tanto, es posible crear nuestras propias excepciones heredando
unadelasnumerosasclasesdeexcepcinyadisponibles.PararespetarlasconvencionesdelFramework.NET,se
aconseja conservar el trmino Exception en el nombre de la clase. Podemos, por ejemplo, escribir el siguiente
cdigo:

Public Class NoFuncionaException


Inherits Exception
Public Sub New()

End Sub
Public Sub New(ByVal mensaje As String)
MyBase.New(mensaje)

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Sub
Public Sub New(ByVal mensaje As String, ByVal inner As Exception)
MyBase.New(mensaje, inner)
End Sub
End Class

Luego se puede utilizar esta clase para activar una excepcin personalizada. El siguiente cdigo activa una
excepcinpersonalizadaenunbloquecatch.

Catch ex As Exception
Throw New NoFuncionaException("error en la aplicacin", ex)
End Try

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Lasherramientasdedepuracin

En la seccin dedicada a la gestin de los errores, hemos visto que los errores de lgica son los ms dificiles de
eliminar de una aplicacin. Afortunalmente, Visual Studio .NET nos propone numerosas herramientas de depuracin
eficacesysencillas.Permitencontrolareldesarrollodelaejecucindelaaplicacin(ubicandopuntosdeinterrupciny
haciendo ejecutar las instrucciones una a una), visualizar y modificar el contenido de las variables, visualizar el
contenido de la memoria en una ubicacin particular, verificar la lista de todas las funciones utilizadas, etc. Estas
herramientassonaccesiblesdesdelabarradeherramientasDepurar.

ElmenDEPURARtambinfacilitaelaccesoanumerosasherramientas:

Segn la configuracin del entorno de Visual Studio, es posible que algunas herramientas no estn disponibles.
PuedevolveraconfigurarVisualStudioparaintegrarestasherramientasatravsdelmenHerramientasImportar
y exportar configuraciones. Los diferentes cuadros de dilogo le proponen guardar su entorno actual antes de
modificarlo,yluegoelegirunentornotipoparaimportar.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Entre las configuraciones disponibles, la Configuracin general de desarrollo contiene la mayora de las
funcionalidades.

Despusdeestaimportacin,seaadenmuchasherramientasadicionalesalmenDEPURAR:

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Paralassiguientesexplicacionesdeestecaptulo,vamosaconsiderarqueestaeslaconfiguracinutilizadaenVisual
Studio.

1.Controldelaejecucin

a.Iniciodelasolucin

UnproyectoenVisualStudiopuedetenertresestadosdistintos:

l Endesarrollo.

l Enejecucin.

l Enmododeparada(seinterrumpilaejecucin).

Ellanzamientodelaejecucinsepuedeefectuarporlabarradeherramientasoporlacombinacindeteclas[F5]
o[Ctrl][F5].Siseutilizaestaltimasolucin,laaplicacinselanzaenmodonormalynohaydisponibleninguna
herramientadedepuracin.

Si la solucin contiene varios proyectos, se debe configurar uno de ellos como proyecto de lanzamiento para la
solucin.Esteproyectotambindebetenerunobjetodelanzamientoconfigurado,yconsuejecucinseiniciarla
applicacin.

b.Pararlasolucin

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
SepuedepararlaaplicacincerrandotodaslasventanasparaunaaplicacindeWindows,encuantosecierrala
ltima ventana, o a travs de las teclas [Ctrl] C para una aplicacin de consola. La barra de herramientas o la
combinacindeteclas[Ctrl][Alt][Pausa]tambinpermitenpararlaaplicacin.

Lacombinacindeaccesorpido[Mays][F5]permiterelanzarlaejecucindelasolucin.

c.Interrumpirlasolucin

La interrupcin de la ejecucin se efecta con la combinacin de teclas [Ctrl][Pausa] o a travs de la barra de


herramientas:

Lainterrupcinseproducesobrelainstruccinquesiguealaqueestencursodeejecucinenelmomentodela
parada.Laventanadecdigosevuelvedenuevovisible,conunamarcadelantedelalneadondeseinterrumpi
laejecucin.

Estemtodonoesmuyprctico,yaquehacefaltatenermuchasuerteparainterrumpirlaejecucinenunlugar
preciso. Ms adelante veremos que los puntos de interrupcin son una solucin mucho mejor para detener la
ejecucindelcdigo.

d.Proseguirlaejecucin

Unavezenmodoparado,tenemosdistintasformasdecontinuarconlaejecucindelaaplicacin.

Laprimerapermiteretomarlaejecucinnormaldelaaplicacinutilizandolamismatcnicaqueseusaparaelinicio
delprograma(barradeherramientasocombinacindeteclas[F5]).Sinembargo,latcnicamscorrientedurante
unadepuracinconsisteenlaejecucinpasoapaso.

Haytressolucionesdisponibles:

l Pasoapasoporinstrucciones([F11]).

l Pasoapasoporprocedimientos([F10]).

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
l Pasoapasoparasalir([Shift][F11]).

El Paso a paso por instrucciones y el Paso a paso por procedimientos difieren simplemente en su manera de
gestionarlasllamadasdeprocedimientosyfunciones.Siestamosenmododeparadaenunalneadecdigoque
contieneunallamadaaunprocedimientoounafuncin,elmodoPasoapasoporinstruccionesvaapermitirentrar
en el cdigo de la funcin y luego lanzar la ejecucin de su cdigo lnea por lnea. El modo Paso a paso por
procedimientosejecutarelprocedimientoolafuncindeunasolavezsinquepodamosverloqueocurreenel
interiordelprocedimientoofuncin.

El Paso a paso para salir permite la ejecucin del cdigo hasta el final de un procedimiento o funcin, sin
descomponerlneaporlnea,ydespusvuelvealmododeparadaenlalneaquesiguealallamadadelafuncin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Existeunaltimasolucinquenospermiteejecutarfcilmenteunbloquedecdigoyluegodetenerseenunalnea
especfica.Paraello,unmencontextualenlaventanadecdigonosofrecelaposibilidaddevolveralanzarla
ejecucinhastalaubicacindelcursor,sinpararentodaslasinstruccionesentrelalneaactualylaposicindel
cursor(muytilparaejecutarrpidamentetodaslasiteracionesdeunbucle).

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Siporelcontrariodeseaignorarlaejecucindeunbloquedecdigooprefiereencambioejecutardenuevoun
bloque de cdigo, es posible desplazar el punto de ejecucin para designar la prxima instruccin ejecutada.
Bastacondesplazarlaflechaamarillaquesemuestraenelmargenfrentealasiguienteinstruccinquesevaa
ejecutar.

ComonosindicaMicrosoft,sedebeutilizarestecomandoconprecaucin.Hayquerecordarlossiguientespuntos:
lasinstruccionescolocadasentreelantiguoyelnuevopuntodeejecucinnoseejecutarndesplazarelpuntode
ejecucin hacia atrs no anula las instrucciones ya tratadas el punto de ejecucin solo puede desplazarse dentro de
unafuncinoprocedimiento.

2.PuntosdeinterrupcinyTracePoint

Solo tenemos una solucin para pasar a modo de parada y consiste en utilizar las teclas [Ctrl][Alt][Pausa]. Esta
solucinpresentaungraninconveniente:laejecucinseparaencualquierpunto.Lospuntosdeinterrupcinnos
facilitanunasolucinmselegantegraciasalacualpodemoselegirlaubicacindondetendrlugarlainterrupcin
delaejecucin.

Los puntos de interrupcin pueden ser condicionales. Se tienen en cuenta diferentes tipos de condiciones en su
activacin(condicin,nmerodepaso...).

LosTracePointsonprcticamenteidnticosalospuntosdeinterrupcin,exceptoqueparaunTracePointsepuede
especificarlaaccinejecutadacuandosealcanzaelpunto.Puedeserelpasoenmododeparadadelaaplicacino
lavisualizacindeunmensaje.EnelentornoVisualStudio,lospuntosdeinterrupcinolosTracePointsemuestran
medianteunaseriedeiconos.Losiconosvacosrepresentanunelementodesactivado.

representaunpuntodeinterrupcinnormal,activadoodesactivado.


representaunpuntodeinterrupcinavanzado(condicin,nmerodepasoofiltro).


representaunTracePointnormal,activadoodesactivado.


representaunTracePointavanzado(condicin,nmerodepasoofiltro).


representaunpuntodeinterrupcinounTracePointenerror.


representaunavisoenunpuntodeinterrupcinounTracePoint.

a.Ubicarunpuntodeinterrupcin

Paraubicarunpuntodeinterrupcin,existenmuchasposibilidades:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
l Efectuarunclicenelmargendelaventanadecdigo.

l Colocarelcursorenlalneacorrespondienteyutilizarlacombinacindeteclas[Ctrl]B.

l Utilizar la opcin Punto de interrupcin Insertar un punto de interrupcin del men contextual de la
ventanadecdigo.

Todasestastcnicasinsertanelpuntodeinterrupcinymaterializansuubicacinconunpuntorojoenelmargen
yencuadranenrojolalneacorrespondiente.

Para todas estas soluciones, el cdigo debe ser visible en el editor. La opcinInterrumpir la funcin del men
Depurar Nuevo punto de interrupcin permite ubicar un punto de interrupcin en un procedimiento o funcin
soloconteclearsunombre.

Cuidado:elcuadrodedilogoleproponeprecisarenqulneadelafuncindeseaubicarunpuntodeinterrupcin,
peroestafuncionalidadnoestdisponibleparalospuntosdeinterrupcinenfunciones.

Los puntos de interrupcin que se ubican as son incondicionales. En cuanto la ejecucin llega a esta lnea, la
aplicacin pasa a modo detenido. Se puede perfeccionar el funcionamiento de los puntos de interrupcin al
aadirles condiciones, un nmero de paso o al transformarlos en TracePoint. Para ello, conviene modificar las
propiedadesdelpuntodeinterrupcinatravsdelmencontextualdisponiblehaciendounclicderechoenlalnea
correspondiente.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Agregarunacondicin

Se puede someter a condicin el paso a modo de parada. El siguiente cuadro de dilogo permite precisar las
condicionesdeejecucindelpuntodeinterrupcin.

En este cuadro de dilogo, debemos introducir una expresin que ser evaluada a cada paso por el punto de
interrupcin.Entonceslaejecucinseparar:

l Sielresultadodelaevaluacindelacondicinesverdadero.

l Si el resultado de la evaluacin de la condicin ha sido modificado desde el ltimo paso por este punto de
interrupcin.Hayqueobservarenestecasoquesonnecesariosalmenosdospasosparaprovocarlaparadadela
aplicacin(elprimerosirvesimplementeparagrabarelresultadodelaexpresin).

Modificacindelnmerodepasos

Los puntos de interrupcin tambin pueden contar el nmero de veces que se les alcanza y activarse para un
nmeroparticulardepasos.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Este cuadro de dilogo nos permite definir el nmero de pasos en el punto de interrupcin para que este pare
efectivamentelaaplicacin.Estndisponiblescuatroopcionesparalacondicindeinterrupcinenelnmerode
pasos.

Cuidado:siseindicaunacondicinparaelpuntodeinterrupcin,elnmerodepasoscorrespondealnmerode
vecesquepasalaejecucindelaaplicacinporestalneaconlacondicincomprobada.Conlaconfiguracinde
nuestro ejemplo, nos pararemos en el bucle al paso nmero 100.000 (la condicin ser verdadera para
i=0,100,200,300,400,500,600,700,800,900).

Filtrado

Losfiltrospermitenaadircriteriosadicionalesparalaejecucindeunpuntodeinterrupcin. Estoscriteriosson
relativosalnombredelamquinadondeseejecutalaaplicacinyalprocesoothread.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
La condicin debe expresarse con las palabras clave MachineName, ProcessId, ProcessName, ThreadId,
ThreadNameylosoperadores&(y),||(o), !(not).

TransformacinenTracePoint

Un punto de interrupcin se puede transformar en tracePoint precisando una accin particular que se debe
ejecutarcuandosealcance.

Estecuadrodedilogoesperalaformulacindelmensajevisualizadoenlaventanadesalidacuandosealcanzael

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
punto de interrupcin. Tambin autoriza la ejecucin de una macro. Para que el punto de interrupcin se
transformerealmenteenTracePoint,laopcinContinuarlaejecucindebeestaractivada.

b.Activar,desactivar,suprimirunpuntodeinterrupcin

Demaneramomentneasepuedendesactivarlospuntosdeinterrupcingraciasalmencontextual.

A continuacin, el punto de interrupcin se puede activar de nuevo al utilizar otra vez el men contextual. Este
mismomenpermitetambineliminarunpuntodeinterrupcin, peroesmsrpidohacerdobleclicenelpropio
puntodeinterrupcin.ElmenDepurarproponetambinlaopcinEliminartodoslospuntosdeinterrupcin, y
evitaastenerquerecorrermuchaslneasdecdigoparaeliminarelconjuntodelospuntosdeinterrupcin.

Parafacilitarnoslatareaduranteladepuracindeunaaplicacin,unaventananosmuestraunresumendetodos
los puntos de interrupcin ubicados en su proyecto. Esta ventana es accesible por medio del men Depurar
Ventanas Punto de interrupcin, y propone un men contextual que permite realizar las principales acciones
sobreunpuntodeinterrupcin.

Lospuntosdeinterrupcinseconservancuandosecierraelproyecto.

3.Examendelcontenidodevariables

Elinterspordepurarconsisteenpoderseguirelfuncionamientodelaaplicacindurantesuejecucin.Cuandola
aplicacinestenmododeparada,esprimordialpodervisualizarlosvalorescontenidosenlasdiferentesvariables
de la aplicacin. Esta visualizacin nos permite comprobar el resultado de las operaciones ya efectuadas o
anticiparnosalasqueserealizarnenelrestodelcdigo.

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
a.DataTips

Los DataTips ofrecen un medio rpido para visualizar el contenido de una variable. Solo hay que desplazar el
cursor del ratn sobre el nombre y, en un momento, se visualiza una ventana que presenta el contenido de la
variable. Si la variable es un tipo complejo, como una instancia de clase por ejemplo, el DataTips propone un
pequeo signo + que permite bajar en la estructura de la variable. Los datos mostrados tambin se pueden
modificardirectamenteenelDataTips.ElDataTipsdesapareceautomticamentecuandoalejaelratn.

Paravisualizarelresultadodeunclculodeunaexpresin,convienepreviamenteseleccionarlaexpresinyluego
ubicarelcursordelratnsobrelaseleccin.Eldepuradorevalalaexpresinymuestraelresultado.ElDataTips
solo puede visualizar las variables accesibles en el mbito actual (variables declaradas en la funcin donde
estamosdetenidosovariablesglobales).

Unpequeotruco:sideseavisualizarelcdigoocultadoporelDataTipssinhacerlodesaparecer,puedeutilizarla
tecla[Ctrl],quelovuelvetransparente.

b.VentanaAutomtico

La ventana Automtico muestra las variables utilizadas en la instruccin actual, en las tres instrucciones
anterioresyenlastresinstruccionessiguientes.EstaventanaesaccesibleatravsdelmenDepurarVentanas
Automtico.

Estaventanatambinpermitemodificarelcontenidodeunavariablehaciendodobleclicenelvalor,introduciendo
elvalornuevoyaceptandoelcambiomediantelatecla[Intro].Laaplicacinseguirejecutndoseconesevalor
nuevoenlavariable.

c.VentanaVariableslocales

LaventanaVariableslocalesesaccesibledesdeelmismomenDepurar Ventanas Variableslocalesyposee


un funcionamiento idntico a la ventana Automtico, pero muestra todas las variables actuales, es decir, las
variablesglobalesylasvariablesdeclaradasenelprocedimientoofuncinencursodeejecucin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
En todas estas ventanas, no es posible controlar la lista de las variables que se muestran, ya que el depurador
determinalalistaenfuncindelcontextoenelqueseencuentralaaplicacin.Avecesesmsprcticoconfigurar
manualmentelalistadelasvariablesyexpresionesquequeremoscontrolarduranteelfuncionamientodelaaplicacin.

d.LasventanasInspeccin

LaventanaInspeccinpermitemostrarlasvariablesquepareceninteresantesparaladepuracindelaaplicacin.
Estaventana,omejordicho,estasventanas,yaqueexistencuatroventanasWatch,semuestrandesdeelmen
Depurar Ventanas Inspeccin y luego Inspeccin 1 a Inspeccin 4. A continuacin debemos configurar la
ventana aadiendo las variables y expresiones que deseamos visualizar. Al hacer doble clic en la columna
Nombre, podemos escribir lo que deseamos visualizar en la ventana. Tambin podemos efectuar un arrastrar
soltar desde la ventana de cdigo. Si escribimos el nombre de variable compleja (por ejemplo, una instancia de
clase),sevisualiza,enformaderbol,elconjuntodesuspropiedadesenlaventana.

Solosemuestraelcontenidodelasvariablessilaaplicacinestenmododeparadaenunalneadecdigoa
partir de la cual se puede acceder a la variable. Por ejemplo, el contenido de las variables locales de un
procedimientoofuncinsolosemuestrasiel cdigoseparaenesteprocedimientoofuncin.

En el caso contrario, la ventana Inspeccin nos indica simplemente que esta variable no est declarada en la
partedecdigodondenosencontramos,mostrndolaencaracteresgrises.

En este ejemplo, se declara la variable e en un procedimiento distinto al que se est ejecutando en este
momento.

Como para las otras ventanas, se puede modificar el contenido de la variable haciendo doble clic en ella para
pasaralmododeedicinyvalidarlamodificacinconlatecla[Intro].

e.LaventanaInspeccinrpida

La ventana Inspeccin rpida tiene el mismo principio de funcionamiento y es accesible a travs del men
DepurarInspeccinrpida.Enestecaso,lavariableolaexpresinenlaqueseencuentraelcursorsevisualiza
en la ventana Inspeccin rpida. Al ser una ventana modal, es obligatorio cerrarla antes de continuar la
depuracindelaaplicacin.

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
El botn Agregar inspeccin permite agregar rpidamente la expresin en la ventana Inspeccin para poder
estudiarlaenelrestodeladepuracin.

4.Lasotrasventanasdedepuracin

Existen otras ventanas de depuracin, pero algunas de ellas no son realmente tiles para el desarrollo de
aplicacionesVisualBasic.Sereservanmsbienparalapruebadeaplicacionesdesarrolladasconotroslenguajes,
comoC++,porejemplo.

Elsiguientoejemplotratadelaventanadememoriaquepermitelavisualizacindelcontenidodeunazonadela
memoriacuyadireccinconocemos.

Siquiere,puedeverelcdigomquinacorrespondientealasinstruccionesVB.NET.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Otrastcnicasdedepuracin

Lacompilacincondicional

Puedeutilizarlacompilacincondicionalparaespecificarfragmentosquecdigoquesernonocompiladosenfuncin
del valor de una constante definida previamente. Por ejemplo, puede probar varias soluciones para resolver un
problemautilizandovariosalgoritmosyverificarculeselmseficaz.

El fragmento de cdigo sometido a la condicin debe estar colocado entre las instrucciones#if condicion Then y
#endif.Enfuncindelvalordelacondicin,elfragmentodecdigosercompiladoono.Porsupuesto,esnecesario
que la variable o las variable(s) utilizada(s) en la condicin sea(n) inicializada(s) antes de su aparicin en una
instruccin#if.

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e


As System. EventArgs) Handles Button1.Click
Dim i As Integer
#Const version = 2
#If version = 1 Then
For i = 0 To 1000000
calcula(i)
Next
#End If
#If version = 2 Then
Do While i < 100000
calcula(i)
i = i + 1
Loop
#End If

End Sub

Lasconstantessepuedendeclararconladeclaracin#const,comoenelejemplosiguiente,oenlaspropiedadesdel
proyecto.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Sinembargo,hayquetenercuidado,yaquelasconstantesdeclaradasconestosdosmtodossolosepuedenutilizar
paralacompilacioncondicionalynosonaccesiblesdesdeelcdigo.

UtilizacindelaclaseDebug

LaclaseDebugdisponedemuchosmtodosestticos,yporlotantoutilizablessintenerquecrearinstanciasdela
clase,quenospermiteninsertarinstruccionesenelcdigoparaseguireldesarrollodelaaplicacin.

Conelmtodoassert,seafirmaque,cuandoseejecuteestalneadecdigo,lacondicinespecificadaenelmtodo
serverdadera.

Debug.Assert(y <> 5)

Silacondicinesfalsa,VisualBasicmuestrauncuadrodedilogoqueresumelasituacin.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Estecuadrodedilogoproponetressolucionesparacontinuar:

Anular Paralaejecucindelaaplicacin.

Reintentar LaaplicacinpasaamododeparadaenlalneaquecontienelainstruccinAssert,
permitiendoasintentaranalizarlasituacin.

Omitir Laejecucindelaaplicacincontinaconnormalidad.

El mtodoFail es ms radical, ya que muestra el mismo cuadro de dilogo, pero sin ninguna condicin. Se puede
utilizar,porejemplo,enunbloqueTry End Try.

Try
z = 1 / x
Catch ex As Exception

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Debug.Fail("divisin por cero")
End Try

LosmtodosWriteyWriteLinepermitenseguirlaevolucindeunaexpresinsinquelaaplicacinpasealmodode
parada.Lainstruccinmostrarenlaventanadesalidaelresultadodelaevaluacindelaexpresin.

LosmtodosIndentyUnindentformateanlavisualizacinenlaventanaResultados.

Debug.WriteLine("principio del bucle")


Debug.Indent()
For x = 1 To 5
Debug.WriteLine("pasada n" & x)
...
...
Next
Debug.Unindent()
Debug.WriteLine("final del bucle")

Enlaventanadesalidaseobtieneelresultadosiguiente:

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Losdiferentestiposdeaplicacin

Las aplicaciones de Windows se basan en una o ms ventanas que constituyen la interfaz entre el usuario y la
aplicacin.Paradesarrollarestetipodeaplicacin,tenemosanuestradisposicinenelFramework.NETunconjunto
de clases que permiten disear la interfaz de la aplicacin. Estos elementos se recogen frecuentemente bajo el
trmino Tecnologa Windows Forms. Una aplicacin basada en Windows Forms utiliza uno o ms formularios para
construirlainterfazdeusuariodelaaplicacin.Enestosformularios(oventanas),colocaremoscontroles,paradefinir
exactamenteelaspectodelainterfazdelaaplicacin.LosformulariossecreanapartirdeclasesdelFramework.NET
que se podrn especializar aadiendo funcionalidades. El formulario as creado es en s una clase y ser posible
utilizarlo en otra aplicacin aadindole funcionalidades adicionales mediante una relacin de herencia. Se pueden
crear los Windows Forms directamente con el cdigo, pero el entorno de desarrollo Visual Studio proporciona una
seriedeherramientasgrficasparafacilitarnoslatarea.Utilizaremosprincipalmenteestatcnica.

1.Modalidadesdepresentacindelasventanas

EnunaaplicacindeWindows,existentresestilosdepresentacinparasusventanas.

a.Interfazmonodocumento(SDI)

Solo hay una ventana disponible en la aplicacin. Para poder abrir un nuevo documento, es necesario cerrar el
documentoactivodelaaplicacin.ElblocdenotasdeWindowsesunaaplicacinSDI.

b.Interfazmultidocumento(MDI)

Laaplicacinestconstituidaporunaventanaprincipal(laventanamadre),enlaqueaparecernvariasventanas
(ventanas hijas) que contienen los documentos en los que se va a trabajar. Por regla general, este tipo de
aplicacin dispone de un men que permite la organizacin de las diferentes ventanas hijas. Este tipo de
presentacinseutilizaenlamayoradelasaplicacionesofimticas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
c.Interfazdeestiloexplorador

Esteestilodeinterfazsedesarrollacadavezmsconrespectoalasotrasdos.Enestecaso,sedividelaventana
en dos zonas. La zona de la izquierda presenta en forma de rbol los elementos que la aplicacin puede
manipular.Lazonadeladerechapresentaelelementoseleccionadoenelrbolypermitesumodificacin.Muchas
herramientasadministrativasutilizanestapresentacin.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LasventanasenVB.NET

Cuando comience una nueva aplicacin de Windows Forms, el entorno de desarrollo aade automticamente un
formularioalproyecto.Esteformulariosirvedepuntodepartidaparalaaplicacin.Puedelanzarinmediatamentela
ejecucin de la solucin y todo funciona. Obviamente, la aplicacin no permite hacer mucho, pero tiene todas las
funcionalidadesdeunaaplicacindeWindowsytodoellosinescribirunasolalneadecdigo.Enrealidad,existealgo
decdigoquecorrespondeaestaaplicacin,perohasidogeneradoautomticamenteporVisualStudio.Puestoque
estecdigonuncasedebemodificarmanualmente,losarchivosquelocontienenestnocultosenelexploradorde

soluciones.Paramostrarlos,puedeutilizarelbotn delabarradeherramientasdelexploradordesoluciones.

Podr constatar que ya existen muchos archivos en el proyecto. Todos los archivos reservados de Visual Studio
tienenlaextensin.designer.vb.Porsupuesto,sepuedevisualizarelcontenidodeestosarchivos.

Este,porejemplo,eselcontenidodelarchivoApplication.designer.vb.

-------------------------------------------------
<auto-generated>
This code was generated by a tool.
Runtime Version:2.0.50727.1433

Changes to this file may cause incorrect behavior and will be
lost if the code is regenerated.
</auto-generated>
--------------------------------------------------

Option Strict On
Option Explicit On

Namespace My

NOTE: This file is auto-generated; do not modify it directly.


To make changes, or if you encounter build errors in this file,
go to the Project Designer (go to Project Properties or
double-click the My Project node in Solution Explorer),
and make changes on the Application tab.

Partial Friend Class MyApplication

<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Public Sub New()
MyBase.New(Global.Microsoft.VisualBasic.ApplicationServices.Authentication
Mode.Windows)
Me.IsSingleInstance = false
Me.EnableVisualStyles = true
Me.SaveMySettingsOnExit = true
Me.ShutDownStyle =
Global.Microsoft.VisualBasic.ApplicationServices.ShutdownMode.AfterMainForm
Closes
End Sub

<Global.System.Diagnostics.DebuggerStepThroughAttribute()> _
Protected Overrides Sub OnCreateMainForm()
Me.MainForm = Global.WindowsApplication1.Form1

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
End Sub
End Class
End Namespace

Loscomentarioscolocadosenestearchivosonmuyclaros:nuncamodifiqueestearchivomanualmente!Seactualiza
deformaautomticadespusdecadamodificacindelaspropiedadesdelproyecto.Elsegundoarchivo,actualizado
automticamente, se asocia a la ventana de la aplicacin. En nuestra primera aplicacin, se denomina
form1.designer.vb.Contendrladescripcindetodaslasacciones,traducidasalcdigoVB,quesevanarealizarpara
personalizarlascaractersticasdelaventana.

Veamoselcontenidodeestearchivo:

<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Partial Class Form1
Inherits System.Windows.Forms.Form

Form overrides dispose to clean up the component list.


<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
Try
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
Finally
MyBase.Dispose(disposing)
End Try
End Sub

Required by the Windows Form Designer


Private components As System.ComponentModel.IContainer

NOTE: The following procedure is required by the Windows Form Designer


It can be modified using the Windows Form Designer.
Do not modify it using the code editor.
<System.Diagnostics.DebuggerStepThrough()> _
Private Sub InitializeComponent()
components = New System.ComponentModel.Container()
Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font
Me.Text = "Form1"
End Sub

ContieneladefinicindelaclasecorrespondientealaventanaqueheredadelaclaseSystem.Windows.Forms.Form.
Estadefinicinconllevaunapequeaparticularidadconrespectoaladefinicindeunaclase,talycomohemosvisto
enelcaptulodedicadoalaprogramacinorientadaaobjetos.Delantedelnombredelaclaseseespecificalapalabra
clavePartial.Estapalabraclaveleindicaalcompiladorqueelarchivosolocontieneunapartedeladefinicindela
clase,mientrasquelaotraparteestdisponibleenelarchivoForm1.vb.Estatcnicapermiterepartirlospapelesde
cadauno:

l Visual Studio se encarga de generar, dentro del archivo form1.designer.vb, el cdigo correspondiente a la
personalizacindelaspectodelaventana.

l El usuario es responsable del cdigo, contenido en el archivo form1.vb, encargado de la personalizacin del
funcionamientodelaventana.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Esta solucin limita los riesgos de modificacin involuntaria de la parte de cdigo reservada a Visual Studio. El
elemento ms importante est constituido por el mtodo InitializeComponent. Este mtodo es llamado
automticamentedurantelacreacindeunainstanciadelaventana,durantelallamadadelconstructor.Paraestar
seguro de ello, puede aadir un constructor por defecto en el archivo Form1.vb y constatar que Visual Studio lo
convierteautomticamenteaadindoleunallamadaalmtodo.

Public Class Form1


Public Sub New()
This call is required by the Windows Form Designer.
InitializeComponent()
Add any initialization after the InitializeComponent() call.
End Sub

Porelcontrario,siaadeunconstructorsobrecargado,ustedeselresponsabledeesallamada.Lomssencilloen
esecasoeshacerlallamadaalconstructor,pordefecto,enlaprimeralneadesuconstructorsobrecargado.

Public Sub New(ByVal i As Integer)


MyClass.New()
End Sub

Piense tambin en respetar en el constructor por defecto el emplazamiento que tiene reservado para sus
inicializacionespersonales.Sisecolocanantesdelallamadaalmtodo InitializeComponent,estepodramodificarlas.
Antesdelainvocacindelmtodo InitializeComponent,loselementosgrficosdelaventananoestndisponibles,yaque
elpapelprincipaldeestemtodoconsisteencrearloseinicializaralgunasdesuspropiedades.

Paraqueseaposibleeliminartodoslosobjetosinstanciadosporlaclase,secreaunmtodoDispose.Estemtodo
comienzaeliminandolosobjetoscreadosluegollamaalmtodoDisposedelaclasemadre.

Form overrides dispose to clean up the component list.


<System.Diagnostics.DebuggerNonUserCode()> _
Protected Overrides Sub Dispose(ByVal disposing As Boolean)
If disposing AndAlso components IsNot Nothing Then
components.Dispose()
End If
MyBase.Dispose(disposing)
End Sub

Hemosrepasadoelcdigogeneradoautomticamente.Veamosahoracmomodificarelaspectoyelcomportamiento
denuestraventanamedianteestaspropiedades.

1.Dimensinyposicindelasventanas

Laposicindelaventanaenlapantalla(oensucontenedor)semodificaconlapropiedadLocation.Estapropiedad
esunaestructuracompuestapordosmiembros.Indicalascoordenadasdelngulosuperiorizquierdodelaventana
conrespetoalngulosuperiorizquierdodelapantalla.Losmiembrosdeestaestructurasepuedenmodificarenla
ventanadepropiedadesdeVisualBasic.Dehecho,cuandoustedmodificapropiedades,seaadecdigoparatener
encuentasusmodificaciones.Porejemplo,siquisiramosquenuestraventanaaparecieraenlascoordenadas100,
100,deberamosmodificarlapropiedadLocation.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Simiramoselcdigo,encontraremoslamodificacindenuestrapropiedad.

Me.Location = New System.Drawing.Point(100, 100)

Las dimensiones de la ventana se pueden modificar con la propiedad size, que contiene dos miembros Width y
Heightqueindicanlaanchuraylaalturadelaventana.

Vamosaresumirtodoconunpequeoesquema:

Las unidades son pxeles para todas las propiedades relativas a las dimensiones y posiciones de objetos. Las
propiedades Left,Top, Heighty Width estn disponibles en el cdigo, pero no en la ventana de propiedades. La
correspondencia con las propiedades Location y Size de estas propiedades se indica entre parntesis en el
esquema.

Estaspropiedadesseactualizandurantelaejecucindelaaplicacinsilaventanasedesplazaoseredimensiona.
Sonaccesiblesatravsdelcdigodelaaplicacin.

El ancho y el largo de la ventana pueden variar dentro de los lmites fijados por las propiedades MinimumSize y
MaximumSize.Pordefecto,estasdospropiedadesseinicializana0.Enestecaso,el0indicaquenohayunlmitefijo
paraeltamaodelaventana.

Otrasdospropiedadesindicanelcomportamientodelaventanaduranteelarranquedelaaplicacin.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
La propiedad StartPosition permite imponer una posicin a la ventana, al iniciarse la aplicacin. Los posibles
valoresseresumenenlasiguientetabla:

Valordelapropiedad Efectoenlaventana

Manual LaspropiedadesLocationySizeseutilizanparamostrarlaventana.

CenterParent Laventanaestcentradaenlaventanamadre.

CenterScreen Laventanaestcentradaenlapantalla.

WindowsDefaultLocation Elsistemacolocaautomticamentelasventanasapartirdelaesquina
superiorizquierdadelapantalla.Lasventanasbajanhacialaderechadela
pantallacadavezquesemuestraunanuevaventana.Lasdimensionesde
cadaventanaseespecificanenlapropiedadSize.

WindowsDefaultBounds Mismoprincipioqueenelcasoanterior,peroelsistemadeterminalas
dimensionescuandosemuestralaventana.

LapropiedadWindowStateindicaelestadodelaventana.Lostresvaloresposiblesson:

Valordelapropiedad Estadodelaventana

Normal DimensionesdefinidasporlapropiedadSize.

Minimized Ventanaminimizadaenlabarradetareas.

Maximized Ventanaentodalapantalla.

Por supuesto, se puede modificar estas propiedades con el cdigo de la aplicacin. Sin embargo, es ms eficaz
utilizar los mtodos SetLocation y SetSize que permiten redimensionar y colocar la ventana directamente. La
utilizacindeestosmtodosolamanipulacindirectadelaspropiedadesactivanloseventosResizey Moveenla
ventanacorrespondiente.

Elsiguientecdigonospermiteseguirlaposicinylasdimensionesdelaventana:

Private Sub Form1_Resize(ByVal sender As Object, ByVal e As System.Event


Args)Handles MyBase.Resize

System.Console.WriteLine(" Mi anchura: " & Me.Size.Width)


System.Console.WriteLine(" Mi altura: " & Me.Size.Height)
End Sub
Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs)
Handles MyBase.Move
System.Console.WriteLine(" Estoy en la posicin X:" & Me.Location.X )
System.Console.Writeline(" Estoy en la posicin Y:" & Me.Location.Y)
End Sub

Obtenemoslasiguienteinformacin:

Estoy en la posicin X:263


Estoy en la posicin Y:311
Mi anchura: 364
Mi altura: 122

Una pequea curiosidad para acabar con las dimensiones y la posicin de las ventanas. Si reducimos nuestra
ventana a icono, haciendo clic en el botn Minimizar o modificando la propiedadWindowState, obtenemos los

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
valoressiguientes:

Estoy en la posicin X:-32000


Estoy en la posicin Y:-32000
Mi anchura: 160
Mi altura: 24

LasposicionesXeYdelaventanasonvaloresnegativos!Enrealidad,puedeusarvaloresqueestndentrodel
lmite de los valores aceptables para un entero. Solo se ver la parte de su ventana que est entre el cero y la
anchurayalturadesupantalla.PuedeutilizarelmtodoGetBoundsdelobjetoScreenparaobtenerlasdimensiones
delapantalla.

Private Sub Form1_Move(ByVal sender As Object, ByVal e As System.EventArgs)


Handles MyBase.Move

System.Console.WriteLine(" Estoy en la posicin X:" & Me.Location.X)


System.Console.WriteLine(" Estoy en la posicin Y:" & Me.Location.Y)
System.Console.Write(" en una pantalla de:" &
Screen.GetBounds(Me).Size.Width)
System.Console.WriteLine(" por " & Screen.GetBounds(Me).Size.Height)
End Sub

Estecdigonospermiteconocerlasdimensionesdelapantallaquemuestralaaplicacin.

Estoy en la posicin X: 115


Estoy en la posicin Y: 203
en una pantalla de: 1024 por 768

Paraqueelusuariopuedadesplazaromodificarlasdimensionesdelaventana,debedisponerdelasherramientas
necesarias:

l Unabarradettuloparapodercogerlaventanaydesplazarla.

l Unbordeparapoderlaredimensionar.

l Botonesparapoderhacerlamsgrande,mspequeaymostrarlaconlasdimensionesnormales.

Para poder restaurar la ventana, esta debe disponer de un borde sizable asignado a su propiedad
FormBorderStyle.

Parapoderserdesplazada,unaventanadebetenerunabarradettulo.Estabarradettulosepuedeocultarconla
propiedadControlBoxcolocadaenFalso.Enesecaso,nosemuestranisiquieraelttulodelaventanaespecificado
porlapropiedadText.Silabarradettuloesvisible,susdiferentesbotonessepuedencontrolarconlassiguientes
propiedades:

MinimizeBox Mostraronoelbotndeminimizardelaventana.

MaximizeBox Mostraronoelbotndemaximizardelaventana.

HelpButton Mostrarelbotndeayuda.Visiblesolosilosdosbotonesanterioresnosonvisibles.

2.Coloresyfuentedeletrautilizadosenlasventanas

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lapropiedad BackColorindicaelcolordefondoutilizadoenlaventana.Estecolortambinseusaparatodoslos
controles que se colocarn, a partir de ahora, en la ventana. La propiedad ForeColor indica el color de los
elementosquesecolocarndirectamenteenlaventanaoelcolordelaleyendadeloscontrolescolocadosenella.
Existencuatroposibilidadesparaasignarunvaloraestaspropiedadesdecolor:

l Porlaventanadepropiedades,eligiendouncolorenlapestaaPersonalizado.

l Por la ventana de propiedades, eligiendo un color web. Estos colores corresponden a los colores disponibles en el
lenguajeHTML.

l Por la ventana de propiedades, eligiendo un color del sistema. En este caso, su aplicacin se adaptar
automticamente al entorno del puesto de trabajo en el que est instalada. Si el usuario ha configurado su puesto
paraquelosbotonesseandecolorrosafosforito,encontrarelmismoaspectoensuaplicacin.

l Creando su propio color con un poco de rojo, un poco de verde y un poco de azul. Para mezclar todo y obtener el
color final, utilice el mtodo FromARGB, que toma como parmetro la cantidad de rojo, de verde y de azul y
proporciona el color resultante. Las cantidades de cada color son valores que estn entre el 0 y el 255. Este ltimo
valorsecorrespondeauncolorpuro.

La propiedadOpacity permite regular la transparencia de su ventana. El valor debe estar entre el cero (ventana
transparente)yeluno(ventanaopaca).Cuidado:soloalgunossistemastienenencuentaestapropiedad(Windows
2000,WindowsXP,Windows 2003,Vista).Tambinpuedecrearunfondoespecialindicandounaimagendefondo
para su ventana con la propiedad BackgroundImage. Si la imagen no es suficientemente grande para cubrir la
ventana,sereproduceenmosaico.

Del mismo modo, puede especificar que un color se considere transparente en su ventana. Para hacerlo, debe
asignaralapropiedadTransparencyKeyelvalordeesecolor.

Paraexplicarlautilizacinpococlaradeestapropiedad,hemosindicadoenlaventanasiguientequeelcolorblanco
eratransparente(seveunapartedelaventanadepropiedadesatravsdelazonadetexto).

LapropiedadFontpermiteespecificarlascaractersticasdelafuentedeloscaracteres,yseutilizaparamostrarel
texto directamente en la ventana. Esta fuente se utiliza tambin para todos los controles que se colocarn en la
ventana.Puedemodificarlaspropiedadesdirectamenteenlaventanadepropiedades,abriendolapropiedadFonty
haciendoclicenelsignoms+delantedelapropiedad.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Tambin puede modificar las caractersticas de la fuente con el cuadro de dilogo estndar para elegir la fuente.

Estesemuestrautilizandoelbotn ,desdelapropiedadFontenlaventanadepropiedades.

3.LasventanasMDI

LasaplicacionesMDIestnconstituidaspordostiposdeventanas:

l Lasventanasmadres.

l Lasventanashijas.

EnVB.NET,seutilizalamismaclasebaseparalosdostiposdeventana.Enelprimercaso,seindicasimplemente
quelaventanaesunaventanamadreMDIcolocandoen True su propiedadIsMdiContainerParaaadirdespus
una ventana hija, conviene por supuesto crear primero la ventana y despus asociarla a una ventana madre a
travsdesupropiedadMdiParent.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
EsteesuncdigoquecreatresventanasylasconvierteenventanashijasMDI:

Dim ventana1 As Form


Dim ventana2 As Form
Dim ventana3 As Form

ventana1 = New Form()


ventana1.Text = "ventana 1"
ventana1.MdiParent = Me
ventana1.Show()
ventana2 = New Form()
ventana2.Text = "ventana 2"
ventana2.MdiParent = Me
ventana2.Show()
ventana3 = New Form()
ventana3.Text = "ventana 3"
ventana3.MdiParent = Me
ventana3.Show()

Para obtener ventanas hijas bien colocadas en su ventana madre, puede utilizar el mtodo LayoutMdipasndole
comoparmetrounadelasconstantespredefinidasdelaenumeracinMdiLayout:

Me.LayoutMdi(MdiLayout.TileHorizontal)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Me.LayoutMdi(MdiLayout.TileVertical)

Me.LayoutMdi(MdiLayout.Cascade)

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Se suele llamar a estos diferentes mtodos mediante un men de la aplicacin que proporciona la lista de las
ventanasabiertasenlaaplicacin.Veremoscmohacerloenlaseccindedicadaalosmens.

Para ilustrar otras posibles acciones con las ventanas MDI, vamos a realizar una aplicacin del estilo explorador.
Veamosacontinuacinelaspectogeneraldelaaplicacin.

Enlaparteizquierda,vemosenelrbollosdocumentosdisponiblesdelaaplicacin.Lazonaderechaseadapta,en
funcindelaseleccinhechasobreelrbol,paramostrarlaimagenoeltextodeunareceta.Debemoscreartres
tiposdiferentesdeventanas:

l La ventana principal, que va a contener el control TreeView, y el conjunto de ventanas encargadas de visualizar los
documentos.

l Unaventanaparamostrarlasimgenes.

l Unaventanaparamostrareltexto.

Creemoslaventanaprincipal:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
ModifiquelapropiedadIsMdiContaineraTrueparaactivarlafuncionalidaddeventanamadreMDI.

AgregueuncontrolTreeView.

Modifique la propiedad Dock del control TreeView en Left para que se ajuste al borde izquierdo de la
ventana.

AgregueloselementosalcontrolTreeViewconlaayudadeleditordenodos.

Ennuestraaplicacin,lapropiedadNamedelosnodosrazseutilizaparadeterminareltipodedocumento(txpara
archivotexto,grparaarchivogrfico).Enelrestodelosnodosdelrbol,guardaelnombredelarchivorespectivo.

Lasventanashijastambinsonfcilesdeconfigurar.

Paralaventanagrfica:

EstablezcalapropiedadBorderStyleennone.

AgregueuncontrolPictureBox.

Establezcalapropiedad DockdeestecontrolenFillparaqueocupetodalasuperficiedisponibledela
ventana.

Establezca la propiedad SizeMode de dicho control en StretchImage para que la imagen se adapte al
tamaodelcontrol(dentrodelaventana).

Paralaventanadetexto:

EstablezcalapropiedadBorderStyleennone.

AgregueuncontrolRichtextBox.

Establezcalapropiedad DockdeestecontrolenFillparaqueocupetodalasuperficiedisponibledela
ventana.

Nos resta ahora escribir las lneas de cdigo para mostrar la ventana correcta al efectuar una seleccin sobre el
controlTreeView.Acontinuacinpresentamosdichaslneasdecdigo:

Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e


As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
If Not IsNothing(e.Node.Parent) Then
Dim f As Form
For Each f In Me.MdiChildren
f.Close()
Next
Select case e.Node.Parent.Name
case "gr"
Dim fGr As Grafico

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
fGr = New Grafico
fGr.MdiParent = Me
fGr.Show()
fGr.Dock = DockStyle.Fill
fGr.PictureBox1.Image = Image.FromFile("../../" & e.Node.Name)
case "tx"
Dim fTx As Texto
fTx = New Texto
fTx.MdiParent = Me
fTx.Show()
fTx.Dock = DockStyle.Fill
fTx.RichTextBox1.LoadFile("../../" & e.Node.Name)
End Select
End If
End Sub

La totalidad del cdigo del manejador de eventos TreeView1_AfterSelect se invoca automticamente cuando el
usuario selecciona un elemento del control TreeView. Nuestro primer trabajo consiste en verificar si el nodo
seleccionadoesunnodohijo.Siesteeselcaso,cerramostodaslasventanashijasyapresentes(pormediodeeste
mecanismoelusuariosolopodrverunaventanaalavez).Entoncesverificamoseltipodedocumentosolicitado
consultando la propiedad Name del nodo Padre del elemento seleccionado (gr o tx). En funcin del resultado,
creamosunainstanciadelaventanaacordealasituacin.Establecemoselenlacedeparentescoconlaventana
principal (propiedad MdiParent). La ventana mostrada ocupar toda la superficie libre de la ventana madre Mdi
(propiedad Dock=DockStyle.Fill). Por ltimo, mostramos el documento con el control RichTextBox o PictureBox,
segncorresponda.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Loseventosdetecladoyderatn

La gestin del teclado y del ratn se realiza exclusivamente utilizando los eventos que estos dos perifricos son
capacesdeactivar.Lamayoradeloscontrolespuedengestionarestoseventos.Necesitamossimplementeconocer
enqumomentoseactivanyqudatosproporcionan.

1.Loseventosdeteclado

Lasposibilidadesdeaccindelusuarioeneltecladosonlimitadas:puedesimplementepulsarunatecladelteclado.

EnVisualBasic.NET,estaaccinsedescomponeentreseventosdistintos:

KeyDown

Esteeventoseproducecuandosepulsalatecla.

KeyUp

Esteeventoseproducecuandosesueltalatecla.

KeyPress

Esteeventoseproducecuandosepulsalatecla,perosolosiestacorrespondeauncarcterASCII.

En los eventos KeyDown y KeyUp, un parmetro del tipo KeyEventArgs proporciona informacin adicional sobre el
evento.

Tenemoslassiguientespropiedades:

l [Alt]indicaelestadodelatecla[Alt]deltecladoenelmomentoenqueseproduceelevento.

l [Ctrl]y[Mays]proporcionandatosigualesparalasteclas[Ctrl]y[Mays].

l KeyCodeindicaelnmerodelateclaenelteclado.

EleventoKeyDownseutilizaprincipalmenteparatrabajarconlasteclasdefuncin.Podemos,porejemplo,convertir
enmaysculaseltextodeuncontrolTextBoxsielusuariopulsalacombinacindeteclas[Mays][Ctrl][Alt][F8].

Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As


System.Windows.
Forms.KeyEventArgs) Handles TextBox1.KeyDown
If e.Alt And e.Control And e.Shift And (e.KeyCode = Keys.F8) Then
TextBox1.Text = UCase(TextBox1.Text)
End If
End Sub

OtrasolucinserautilizarlapropiedadModifiers,querecogeelestadodelasteclas[Mays],[Ctrl]y[Alt].

Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e


As System.Windows. Forms.KeyEventArgs) Handles TextBox1.KeyDown
If e.Modifiers = Keys.Shift + Keys.Control + Keys.Alt And

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
e.KeyCode = Keys.F8 Then
TextBox1.Text = UCase(TextBox1.Text)
End If
End Sub

Finalmente, la ltima posibilidad consiste en utilizar la propiedad KeyData, que recoge el estado de las teclas
[Mays],[Ctrl],[Alt]yunatecladefuncin.

Private Sub TextBox1_KeyDown(ByVal sender As Object, ByVal e As


System.Windows.Forms.KeyEventArgs) Handles TextBox1.KeyDown

If e.KeyData = Keys.Shift + Keys.Control + Keys.Alt + Keys.F8


Then
TextBox1.Text = UCase(TextBox1.Text)
End If
End Sub

EleventoKeyPressnosindicasimplemente,atravsdelparmetroedetipoKeyPressEventArgs,elcarcterquese
acabadecoger.Porejemplo,podemosutilizaresteeventoparaverificarquetodosloscaracteresintroducidossean
numricos.Sinoesas,seemiteunbeep.

Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As


System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If Not IsNumeric(e.KeyChar) Then
Beep()
End If
End Sub

Este procedimiento informa simplemente al usuario de que ha elegido un carcter no vlido, pero el carcter
aparecedetodosmodosenlazonadeltexto.Seramejorevitarqueelcarcterentraraenlazonadeltexto.La
propiedadHandleddelparmetropermite,asignndoleelvalor true,indicarqueeleventodetecladoseacabade
gestionaryqueelcontrolnodebetomarloenconsideracin.

Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As


System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If Not IsNumeric(e.KeyChar) Then
Beep()
e.Handled = True
End If
End Sub

Si muchos controles TextBox deben tener el mismo funcionamiento, puede copiar este cdigo en los eventos
KeyPressdecadacontrol.UnasolucinmselegantenospermitecentralizareltratamientoeneleventoKeyPress
delaventana.Parahacerlo,convieneindicaralapropiedadKeyPreviewdelaventanaquerecibirloseventosde
teclado antes que el control de la ventana focalizada. Solo hace falta probar el control activo de la ventana y
verificarquerecibaeltratamiento.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Private Sub TextBox1_KeyPress(ByVal sender As Object, ByVal e As System.
Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress
If Me.ActiveControl Is TextBox1 Then
If Not IsNumeric(e.KeyChar) Then
Beep()
e.Handled = True
End If
End If
End Sub

2.Loseventosderatn

Estos eventos estn relacionados con la utilizacin de los botones o de la rueda del ratn. El eventoClick es el
eventoderatnmsutilizado.Consisteenpulsaryluegosoltarelbotnprincipaldelratn.Esnecesariohablarde
botnprincipaldelratn,yaque,enfuncindelaconfiguracindelpuestodetrabajo,estebotnprincipalpuede
ser tambin el botn derecho (configuracin para zurdos). El evento DoubleClick no funciona con todos los
controles,asque,porejemplo,loscontrolesButtonnosoncapacesdegestionareldobleclicydehechogeneran
doseventosClickseguidos.

Existentambineventosderatnmselementales:

l MouseDowncuandosepulsaunbotndelratn.

l MouseUpcuandosesueltaunbotndelratn.

l MouseWheelcuandoseutilizalaruedadelratn.

Paraestostreseventos,existeunparmetrodetipoMouseEventArgs.Atravsdelaspropiedadesdisponiblesen
estaclase,seobtienenlossiguientesdatos:

l ElbotnorigendeleventoconlapropiedadButton.

l ElnmerodevecesqueelbotnespulsadoosedejadepulsarconlapropiedadClicks.

l ElnmerodemovimientosdelaruedaconlapropiedadDelta.Estapropiedadesunenteropositivoonegativo,que
sigueelsentidoderotacindelarueda.Cadadesplazamientodeunaposicindelaruedaaumentaodisminuyeesta
propiedadconunvalorde120.

l LaspropiedadesXeYindicanelemplazamientoenelcontrolenelqueeleventoderatnseacabadeproducir.

Losdesplazamientosdelratngenerancuatroeventos:

l MouseEntercuandoseponeelratnencimadeuncontrol.

l MouseMovecuandoelratnsedesplazasobreelcontrol.

l MouseLeavecuandoelratndejalasuperficiedelcontrol.

l MouseHovercuandoelratnsequedaencimadeuncontrolduranteunsegundo.

Comoparaloseventosrelativosalosbotonesdelratn,senosproporcionaunparmetrodeltipoMouseEventArgs
enestoseventos.

Unpequeoejemploparaprobarloconunaaplicacindediseomuysencillo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Acadadesplazamientodelratn,sedibujaunpuntoenlaventanaconelcolorindicadoporlastreszonasdetexto
(rojo, verde, azul). Para modificar el color, es suficiente desplazar el ratn encima de la zona de texto
correspondiente (se focaliza automticamente gracias al evento MouseHover) y accionar la rueda del ratn para
aumentarodisminuirelporcentaje.

Public Class Telepantalla


Dim rojo, verde, azul As Integer
Private Sub telepantalla_MouseMove(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles Me.MouseMove
Dim g As Graphics
Dim lapiz As Pen
If e.Button = MouseButtons.Left Then
g = Graphics.FromHwnd(Me.Handle)
lapiz = New Pen(Color.FromArgb(rojo * 2.55, verde * 2.55, azul * 2.55))
g.DrawEllipse(lapiz, e.X, e.Y, 1, 1)
End If
End Sub
Private Sub txtRojo_MouseWheel(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles txtRojo.MouseWheel
rojo += e.Delta / 120
If rojo > 100 Then
rojo = 100
txtRojo.Text = "100%"
ElseIf rojo < 0 Then
rojo = 0
txtRojo.Text = "0%"
Else
txtRojo.Text = rojo & "%"

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End If
End Sub
Private Sub txtVerde_MouseWheel(ByVal sender As Object, ByVal e As
System.Windows.Forms.MouseEventArgs) Handles txtVerde.MouseWheel
verde += e.Delta / 120
If verde > 100 Then
verde = 100
txtVerde.Text = "100%"
ElseIf rojo < 0 Then
verde = 0
txtVerde.Text = "0%"
Else
txtVerde.Text = verde & "%"
End If
End Sub

Private Sub txtAzul_MouseWheel(ByVal sender As System.Object, ByVal e


As System.Windows.Forms.MouseEventArgs) Handles txtAzul.MouseWheel
azul += e.Delta / 120
If azul > 100 Then
azul = 100
TxtAzul.Text = "100%"
ElseIf azul < 0 Then
azul = 0
TxtAzul.Text = "0%"
Else
TxtAzul.Text = azul & "%"
End If
End Sub
Private Sub txtRojo_MouseHover(ByVal sender As Object, ByVal e As
System.EventArgs) Handles txtRojo.MouseHover
txtRojo.Focus()
End Sub

Private Sub txtVerde_MouseHover(ByVal sender As Object, ByVal e As


System.EventArgs) Handles txtVerde.MouseHover
txtVerde.Focus()
End Sub

Private Sub txtAzul_MouseHover(ByVal sender As System.Object, ByVal e


As System.EventArgs) Handles txtAzul.MouseHover
TxtAzul.Focus()
End Sub
End Class

3.ElDragandDrop

ElDragandDropesunafuncionalidadmuytilenlasaplicacionesdeWindows.Permiteeldesplazamientodedatos
enunaaplicacinoentreaplicaciones,pegandounelementoalcursordelratnydejndolodespusencimade
sudestino.

Se puede pegar prcticamente cualquier elemento al cursor del ratn para luego desplazarlo o copiarlo (texto,
imagen,archivo...).Paraguiaralusuariosobreesasposibilidades,elcursordelratnsemodificaenfuncindelos

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
controlesquesesobrevuelanconelratn.

UnaoperacindeDragandDropsedesarrollaentresfases:

l Pegarunelementoalratn.

l Desplazarelratnhaciaundestino.

l Soltarencimadeldestino.

Duranteestaltimaoperacin,tenemosdosposibilidades:

l Elelementopegadoalratnsedesplaza.Enestecaso,desaparecedelcontroldepartidaenelmomentoenquesele
dejaencimadelcontroldedestino.

l Secopiaelelementopegadoalratn.Enestecaso,loquesedejaencimadelcontroldedestinoesunacopia.

VamosaverendetalleelcdigonecesariopararealizarconxitounaoperacindeDragandDrop.Tomemosun
ejemplosencillo,realizandounacopiaentredoszonasdetexto(TxtOrigen,TxtDestino).

a.IniciodelDragandDrop

UnaoperacindeDragandDropsesueleiniciarcuandoelratnsemueveencimadeuncontrolyloseleccionasin
dejardepulsarelbotndelratn.Enestecaso,elusuarioacabadepegarelcontrolalratn.

Enelcdigo,estosetraducesimplementeconlallamadadelmtodoDoDragDropdelcontroldepartida.Lallamada
deestemtodonecesitadosparmetros:

l Elelementoquepegamosalcursordelratn(cadenadecaracteres,unaimagendebitmapounaimagenmetafile).

l Lasoperacionesautorizadasparaelobjetoseleccionado(copia,desplazamiento...).

Private Sub txtorigen_MouseMove(ByVal sender As Object, ByVal e As System.


Windows.Forms.MouseEventArgs) Handles txtorigen.MouseMove
If e.Button = MouseButtons.Left Then
txtorigen.DoDragDrop(txtorigen.Text, DragDropEffects.Move +
DragDropEffects.Copy)
End If
End Sub

b.Configuracindeloscontrolesparalarecepcin

Conviene antes que nada configurar los controles de destino para que acepten la recepcin de un elemento
modificandolapropiedadAllowDropatrue.

Despus,debemosgestionareleventoDragEnterqueseproducecuandoelratnentraenlasuperficiedelcontrol
conunelementopegado.Enlagestindeesteevento,sedebedeterminarquesloqueestpegadoalcursor
delratnparasabersielcontrollopuedeaceptar.Finalmente,hayquedeterminarsielusuariodeseadesplazaro
hacerunacopiadelelementopegadoalcursordelratn.

Para hacerlo en el cdigo, tenemos a nuestra disposicin el parmetro e en el evento DragEnter, que es una
instanciadelaclaseDragEventArg.Estaclasenosproporcionamuchaspropiedadesparaayudarnosennuestras
decisiones:

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
AllowedEffect

PermitesaberculessonlasoperacionesautorizadasporelcontroldeorigendelDragandDrop.

Data

Contienelosdatospegadosalcursordelratn.Atravsdeestapropiedad,sepuedeobtenereltipo
dedatollamandoalmtodoGetDataPresentuobtenerlosdatosllamandoalmtodoGetData.

Effect

Indicalaaccinautorizadaporelcontroldedestino.Estapropiedadseutilizaparacontrolarel
aspectodelcursordelratn.

KeyState

Indicaelestadodelasteclas[Mays],[Ctrl],[Alt]quenospermitensabersielusuariodesearealizar
undesplazamientoounacopia.

X, Y

Indicalascoordenadasdelratnenelcontrol.

Private Sub txtdestino_DragEnter(ByVal sender As Object, ByVal e As System.


Windows.Forms.DragEventArgs) Handles txtdestino.DragEnter
qu lleva pegado?
If e.Data.GetDataPresent(DataFormats.Text) Then
est la tecla Ctrl pulsada?
If (e.KeyState And 8) = 8 Then
cursor copia
e.Effect = DragDropEffects.Copy
Else
cursor mueve
e.Effect = DragDropEffects.Move
End If
End If
End Sub

c.Recuperacindelelementopegado

Cuandoelusuariodejadepulsarelbotndelratn,seproduceeleventoDragDropenelcontroldedestino.En
este evento, hay que recuperar el elemento pegado y colocarlo en el control de destino. Si se trata de un
desplazamiento,tambinsedebeeliminarlainformacindelcontrolfuente.Problema:quineselcontrolfuente?
No tenemos informacin sobre su identidad. La solucin consiste en almacenar en una variable una referencia
haciaelcontroldeorigendelaoperacindeDragandDropalprincipiodelaoperacin.

Dim ctrlOrigen As TextBox

Private Sub txtorigen_MouseMove(ByVal sender As Object, ByVal e As System.


Windows.Forms.MouseEventArgs) Handles txtorigen.MouseMove
If e.Button = MouseButtons.Left Then

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
ctrlOrigen = txtorigen
txtorigen.DoDragDrop(txtorigen.Text, DragDropEffects.Move +
DragDropEffects.Copy)
End If
End Sub
Private Sub txtdestino_DragDrop(ByVal sender As Object, ByVal e As System.
Windows.Forms.DragEventArgs) Handles txtdestino.DragDrop
recuperamos la informacin almacenada en el control de destino
txtdestino.Text = e.Data.GetData(DataFormats.Text)
comprobamos si es una copia o un desplazamiento
If (e.KeyState And 8) <> 8 Then
borramos del control origen
ctrlOrigen.Clear()
End If
End Sub

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Loscuadrosdedilogo

Loscuadrosdedilogosonventanasquetienenunafuncinespecialdentrodelaaplicacin.Sesuelenutilizarpara
pedir al usuario que introduzca datos. Para asegurarse de que esa informacin est bien recuperada antes de
continuar con la ejecucin de la aplicacin, los cuadros de dilogo se muestran a menudo en modalidad modal, es
decir,queelrestodelaaplicacinestbloqueadamientraselcuadrodedilogoquedavisualizado.Esfrecuenteque
enunaaplicacinsenecesitelamismainformacin:unnombredearchivoparaabrir,unafuentedeletra,etc.Para
evitarnostenerquecrearcadavezunnuevocuadrodedilogo,tenemosanuestradisposicinunaseriedecuadros
dedilogopredefinidos.

1.Elcuadroderecogida

Elcuadroderecogidapermitepedirlealusuarioqueintroduzcaunacadenadecaracteres.Sepuedeaccederaesta
posibilidadpormediodelafuncinInputBox.Estafuncinesperatresparmetros:

l Eltextomostradoenelcuadro(engeneral,lapreguntahechaalusuario).

l Elttulodelcuadrodedilogo.

l Unvalorpredeterminadomostradoenlazonadeintroduccindetexto.

Lafuncindevuelveunacadenadecaracteresquecorrespondealtextointroducidoporelusuario,siestevalidalo
tecleadoconelbotnAceptar.Porelcontrario,devuelveunacadenadecaracteresvaca.

Dim resultado As String


resultado = InputBox("Introduzca sus apellidos", "identificacin",
"apellidos")

2.Elcuadrodemensaje

Loscuadrosdemensajepermitenmostrarunainformacinalusuarioyledanlaposibilidaddecontestaratravsde
botonesdecomandodelcuadrodemensaje.

ElcuadrodemensajeestdisponibleatravsdelmtodoShow,enlaclaseMessageBox.Estemtodoaceptamuchos
parmetros para configurar el cuadro de dilogo. El primer parmetro corresponde al mensaje mostrado. El
parmetrosiguienteespecificaelttulodelcuadrodemensaje.Lossiguientesparmetrosdebenserelegidosentre
lasconstantespredefinidasparaindicarrespectivamente:

l Losbotonesdisponiblesenelcuadrodemensaje.

l Eliconomostradoenelcuadrodemensaje.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
l Elbotnseleccionadopordefectoalmostrarelcuadrodemensaje.

Lasconstantesdisponiblesson:

l Paralaeleccindelosbotones:

Constante Significado

MessageBoxButtons.OK BotnOKsolo

MessageBoxButtons.OKCancel BotonesOKyCancelar

MessageBoxButtons.AbortRetryIgnore BotonesAbandonar,ReintentaryCancelar

MessageBoxButtons.YesNoCancel BotonesS,NoyCancelar

MessageBoxButtons.YesNo BotonesSyNo

MessageBoxButtons.RetryCancel BotonesReintentaryCancelar

l Paralaeleccindelosiconos:

Constante Significado

MessageBoxIcon.IconInformation

MessageBoxIcon.IconExclamation

MessageBoxIcon.IconError

MessageBoxIcon.IconQuestion

l Paraelbotnpordefecto:

Constante Significado

MessageBoxDefaultButton.DefaultButton1 Primerbotn

MessageBoxDefaultButton.DefaultButton2 Segundobotn

MessageBoxDefaultButton.DefaultButton3 Tercerbotn

Paraobtenerelcuadrodemensajesiguiente:

utilizaremoselcdigosiguiente:

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim respuesta As Integer
MessageBox.Show("Quiere guardar al cerrar la aplicacin?", _
"Fin del programa", MessageBoxButtons.YesNoCancel, _
MessageBoxIcon.Question,MessageBoxDefaultButton.Button1)

Como le hacemos una pregunta al usuario, tenemos que recuperar su respuesta para decidir qu hacer en la
aplicacin.Paraello,elmtodoShowreenvaunvalorqueindicaelbotnutilizadoparacerrarelcuadrodemensaje.
Aqutambinsedefinenunaseriedeconstantesparaidentificarcadaposiblecaso.

Valordevuelto Botnutilizado

DialogResult.Ok BotnOK

DialogResult.Cancel BotnCancelar

DialogResult.Abort BotnAbandonar

DialogResult.Retry BotnReintentar

DialogResult.Ignore BotnIgnorar

DialogResult.Yes BotnS

DialogResult.No BotnNo

Podemosluegoevaluarlarespuesta:

Select Case respuesta


Case DialogResult.Yes
...
Case DialogResult.No
...
Case DialogResult.Cancel
...
End Select

3.LoscuadrosdedilogodeWindows

MuchoscuadrosdedilogoyaestndefinidosaniveldelpropiosistemaoperativoWindows.Parapoderlosutilizar
en nuestras aplicaciones, tenemos a nuestra disposicin una serie de clases. Vamos a ver cmo configurarlas y
utilizarlasenunaaplicacin.

a.Dilogodeaperturadearchivo

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Estecuadrodedilogonospermiteseleccionarunoomsnombresdearchivo,conlaposibilidaddedesplazarse
enlaestructuraenrboldelamquina.SeutilizalaclaseOpenFileDialog.Debemosentoncescrearunainstancia
ennuestraaplicacin.

Dim dlgAbrir As OpenFileDialog


dlgAbrir = New OpenFileDialog()

Tambinconvieneconfigurarnuestrocuadrodedilogo.LapropiedadInitialDirectoryindicaeldirectorioenel
queseencuentraelcuadrodedilogoenelmomentodesuapertura.Esposiblemostrarsoloalgunosarchivosen
losdirectoriosquesevern.Paraello,hayqueconfiguraratravsdelapropiedad Filterlascorrespondencias
entreladescripcindelcontenidoylaextensinasociada.LapropiedadFilteralmacenalainformacinenforma
de cadena de caracteres. La descripcin y la extensin se separan en la cadena con el carcter | ([AltGr] 1). Si
existenmuchasextensiones disponiblesparaunamismadescripcin,debensepararseconunpuntoycomaenla
cadena. Tambin puede indicar si se debe agregar una extensin a los nombres de los archivos escritos
manualmente,siestosnolallevan.

La propiedadDefaultExt contiene la extensin que se debe agregar y AddExtensionindicasiestaextensinse


agregaautomticamente.Sisepermitealusuarioescogermanualmenteelrecorridoyelnombredelarchivoque
quiereabrir,puedeconfiarlealcuadrodedilogolatareadeverificarqueelnombreyelrecorridodeaccesosean
correctos. Las propiedades CheckFileExist y CheckPathExist gestionan estas comprobaciones. Tambin puede
autorizarlaseleccinmltipleatravsdelapropiedadMultiselect.

Finalmente,paramostrarelcuadrodedilogo,seusaelmtodoShowDialog:

dlgAbrir.InitialDirectory = "c:\dos"
dlgAbrir.Title = "seleccione el archivo que quiere abrir"
dlgAbrir.Filter ="Todos|*.*|Imagenes|*.bmp;*.gif;*.jpg|texto|*.txt"
dlgAbrir.DefaultExt = "txt"
dlgAbrir.AddExtension = True

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
dlgAbrir.CheckFileExists = False
dlgAbrir.Multiselect = True
dlgAbrir.ShowDialog()

Los nombres del archivo o de los archivos seleccionados estn disponibles en la propiedad FileName para una
seleccin nica o en la propiedad FileNames para las selecciones mltiples. Esta propiedad FileNames es una
matriz de cadenas de caracteres que contiene en cada casilla el nombre completo de uno de los archivos
seleccionados.

Dim nombrearchivo As String


For Each nombreArchivo In dlgAbrir.FileNames
System.Console.WriteLine(nombreArchivo)
Next

b.Dilogodegrabacindearchivo

Elcuadrodedilogodegrabacindearchivoesparecidoalanterior,aunquelapropiedadMultiselectdesaparece
ylaspropiedadesCreatePromptyOverwritePromptpermitenmostrarunmensajedeaviso,sielnombredelarchivo
elegidonoexisteo,alrevs,siyaexiste,ysevaasobreescribir.

c.Dilogodeseleccindedirectorio

Este cuadro de dilogo se utiliza para la seleccin o la creacin de un directorio. Se crea a partir de la clase
FolderBrowserDialog, y contiene algunas pocas propiedades. La ms utilizada es ciertamente la propiedad
SelectedPath,quepermitelarecuperacindeunarutadeaccesoaldirectorioseleccionado.Eldirectoriorazdel
cuadro de dilogo est indicado por la propiedad RootFolder. Esta propiedad recibe uno de los valores de la
enumeracin Environment.SpecialFolder, que representa los principales directorios caractersticos del sistema,
como por ejemplo el directorioMis Documentos.Siseutilizaestapropiedad,laseleccindeberhacerseenun
subdirectoriodebajodeldirectorioraz.ModificandolapropiedadShowNewFolderButton,podemosagregarunbotn
que permita la creacin de un nuevo directorio. El mtodo ShowDialog permite la visualizacin del cuadro de
dilogo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
dlgSelecDirectorio.RootFolder = Environment.SpecialFolder.MyDocuments
dlgSelecDirectorio.ShowDialog()
MsgBox(dlgSelecDirectorio.SelectedPath, , Directorio Seleccionado)

Ntesetambinquelarutadeaccesoretornadaporestecuadrodedilogoesunarutaabsoluta,comomuestra
elsiguienteejemplo:

d.Dilogodeeleccindeuncolor

ElcuadrodedilogodeeleccindecolorcreadoapartirdelaclaseColorDialogpuedetenerdosconfiguraciones.

Unaversinsencillaenlaquesoloestndisponiblesloscoloresdebase:

Unaversincompletaenlaqueelusuariopodrcrearcolorespersonalizados:

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LapropiedadColorpermiteinicializarelcuadrodedilogoantesdesuvisualizacinydespusrecuperarelcolor
elegido por el usuario. Puede prohibir la utilizacin de colores personalizados o, todo lo contrario, mostrar el
cuadro de dilogo completo desde su apertura. Para prohibir la visualizacin de los colores personalizados, se
modificalapropiedadAllowFullOpen.Paraforzarlavisualizacincompleta,seusalapropiedadFullOpen.

LavisualizacindelcuadrodedilogoserealizatambinconelmtodoShowDialog.Paraconservarunacalidadde
visualizacin correcta, tambin puede autorizar solo la utilizacin de los colores puros (los colores obtenidos
sobreponiendodiferentespxelesseeliminarndelasposiblesopciones).Estaopcinsedebeusarsisetieneuna
tarjetagrficaconfiguradaen256colores.

Esteejemplomodificaelcolordefondodelapgina.

Dim dlgColor As ColorDialog


dlgColor = New ColorDialog()
dlgColor.FullOpen = True
dlgColor.SolidColorOnly = True
dlgColor.Color = Me.BackColor
dlgColor.ShowDialog()
Me.BackColor = dlgColor.Color

e.Dilogodeeleccindefuente

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
LaclasebaseutilizadaparalaseleccindeunafuenteeslaclaseFontDialog.LapropiedadFontpermitedefinirla
fuentedecaracteresutilizadaparainicializarelcuadrodedilogoo,despusdecerrarlo,pararecuperarlafuente
seleccionada.Tambinpuedemostraruncuadrodedilogosimplificadosinlaeleccindecolorodelosefectos.
Parahacerlo,laspropiedadesShowColoryShowEffectscontrolanlavisualizacindeestosparmetrosenelcuadro
dedilogo.Paragarantizarquelosparmetrosseleccionadoscorrespondanaunafuenteexistenteenlamquina,
puede utilizar la propiedad FontMustExist. Esta propiedad obligar a que el cuadro de dilogo verifique la
existencia de una fuente correspondiente en el sistema operativo antes de cerrarse. Algunas fuentes contienen
muchos juegos de caracteres. Puede autorizar a los usuarios a elegir uno de esos juegos de caracteres
modificando la propiedad AllowScriptChange. La dimensin de la fuente seleccionada puede limitarse con las
propiedadesMaxSizeyMinSize.

Parainspeccionarelefectodelafuenteseleccionada,existeunavistapreviadealgunoscaracteres.Siestavista
previanoessuficiente,tienelaposibilidaddemostrarunbotnAplicar en su cuadro de dilogo a travs de la
propiedadShowApply.Estebotnactivaunevento Applyenelcuadrodedilogo.Enlagestindeesteevento,
puede utilizar la propiedad Font del cuadro de dilogo para visualizar el efecto de la fuente actualmente
seleccionada en su texto. La variable que hace referencia al cuadro de dilogo debe declararse con la palabra
claveWithEventsporlotanto,fueradeunprocedimiento.

Unpequeoejemploparavisualizarlautilizacindeestaspropiedades:

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Public Class PruebaFuente
Inherits System.Windows.Forms.Form
Dim WithEvents dlgFont As FontDialog
Private Sub cmdFuente_click(ByVal sender As System.Object, _
ByVal e As System.EventArgs)Handles cmdFuente.Click
dlgFont = New FontDialog()
dlgFont.ShowApply = True
dlgFont.ShowColor = True
dlgFont.ShowEffects = True
dlgFont.MaxSize = 20
dlgFont.MinSize = 12
dlgFont.FontMustExist = True
dlgFont.AllowScriptChange = True
dlgFont.ShowDialog()
txtPrueba.Font = dlgFont.Font
End Sub
Private Sub dlgFont_Apply(ByVal sender As Object, ByVal e
As System.EventArgs)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Handles dlgFont.Apply
txtPrueba.Font = dlgFont.Font
End Sub
End Class

f.Dilogodeconfigurarpgina

Atravsdeestecuadrodedilogo,podrconfigurarlossiguientesparmetrosdemaquetacindesudocumento
(mrgenes,orientacin...).

EstecuadrodedilogosecreaapartirdelaclasePageSetupDialog.Paratrabajar,estaclasenecesitadosclases
auxiliares:laclasePageSettingssirveparaalmacenarlaconfiguracindelamaquetacinlaclasePrinterSettings
almacena la configuracin de la impresora seleccionada. Hay que crear una instancia de estas dos clases y
asociarlasalaspropiedadesPageSettingsyPrinterSettingsdelcuadrodedilogo.Debeimportarelespaciode
nombresSystem.Drawing.Printingparapoderutilizarestasdosclases.

La utilizacin de diferentes campos del cuadro de dilogo puede prohibirse a travs de la modificacin de las
siguientespropiedades:

l AllowMarginsparalamodificacindelosmrgenes.

l AllowOrientationparalamodificacindelaorientacin.

l AllowPaperparalaeleccindelpapel.

l AllowPrinterparalaeleccindelaimpresora.

Laseleccionesdelusuarioserecuperarndespus,usandolaspropiedadesPageSettingsyPrinterSettingsdel
cuadrodedilogo.

Veamosunejemplodeutilizacin:

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Imports System.Drawing.Printing
Public Class Form2
Inherits System.Windows.Forms.Form

Private Sub TestPgSetup_Click(ByVal sender As System.Object, ByVal e


As System.EventArgs) Handles testPgSetup.Click
Dim configPg As PageSettings
Dim configPrt As PrinterSettings
configPg = New PageSettings()
configPrt = New PrinterSettings()
dlgPgSetup.PageSettings() = configPg
dlgPgSetup.AllowPrinter = True
dlgPgSetup.PrinterSettings = configPrt
dlgPgSetup.ShowDialog()
MessageBox.Show("ha elegido la impresora " _
& dlgPgSetup.PrinterSettings.PrinterName _
& " en papel " _
& dlgPgSetup.PageSettings.PaperSize.PaperName _
& " en formato " _
&(IIf(dlgPgSetup.PageSettings.Landscape, "horizontal", "vertical")))
End Sub
End Class

g.Dilogodeconfiguracindeimpresin

Conestecuadrodedilogo,puedeconfigurarlosparmetrosdeimpresindesudocumento.Secrearapartirde
laclasePrintDialog.

Comoparaelcuadrodedilogodemaquetacin,elcuadrodedilogodeconfiguracindelaimpresinnecesita
unainstanciadelaclasePrinterSettingsparaalmacenarlosdatosdeconfiguracindelaimpresora.

Lautilizacindediferentescampospuedeprohibirseatravsdelamodificacindelassiguientespropiedades:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
l AllowSelection autoriza la utilizacin del botn Seleccin. En general, este botn es accesible solo si hay algo
seleccionadoeneldocumentoquequiereimprimir.

l AllowSomePages autoriza la seleccin de una pgina de inicio y fin para la impresin del documento. Este botn
debeestardisponiblesieldocumentocontienevariaspginas.

l AllowPrintToFile indica si la opcin Imprimir a un archivo est disponible. Esta funcionalidad permite, por
ejemplo,lageneracindeunarchivoenformatoPostScriptparaexportarloaotraaplicacin.

El resultado de las diferentes opciones seleccionadas est disponible despus de cerrar el cuadro de dilogo, a
travsdelapropiedadPrinterSettings.

Heaquunnuevoejemploparaestecuadrodedilogo.

Dim configPrt As PrinterSettings


Dim dlgprinter As PrintDialog
configPrt = New PrinterSettings()
dlgprinter = New PrintDialog()
dlgprinter.PrinterSettings = configPrt
dlgprinter.AllowSomePages = True
dlgprinter.AllowSelection = True
dlgprinter.ShowDialog()
Select Case dlgprinter.PrinterSettings.PrintRange
Case PrintRange.AllPages
MessageBox.Show("ha pedido la impresin de todo el documento")
Case PrintRange.SomePages
MessageBox.Show("ha pedido la impresin de la pgina " _
& dlgprinter.PrinterSettings.FromPage & " a la pgina " _
& dlgprinter.PrinterSettings.ToPage)
Case PrintRange.Selection
MessageBox.Show("ha pedido la impresin de la seleccin")
End Select

4.Cuadrodedilogopersonalizado

Despus de este breve resumen sobre los cuadros de dilogo predefinidos, vamos a ver cmo crear nuestros
propioscuadrosdedilogo.Labaseparalacreacindeuncuadrodedilogoesunaventanaclsicaenlaquese
modificanlassiguientespropiedades:

l Elestilodelborde,paraobtenerunaventanaquenotengauntamaovariable.

l LapropiedadShowInTaskBar,queestcolocadaenFalseparaquelaventananoaparezcaenlabarradetareas.

l Estambinnecesariodisponerdeunbotndevalidacinyunbotndeanulacinparaelcierredelcuadrodedilogo.

Puede crear un cuadro de dilogo cambiando manualmente estas propiedades en una ventana normal, o
seleccionarlaopcinCuadrodedilogoenelmomentodeagregarunelementoalproyecto.

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LavisualizacindelcuadrodedilogoseharconlallamadaalmtodoShowDialogenvezdelmtodoShow,porque
el mtodo ShowDialog muestra la ventana en modalidad modal (nuestro cuadro de dilogo ser la nica parte
utilizabledelaaplicacinunavezabierta).

Al cerrar el cuadro de dilogo, es necesario determinar qu botn ha provocado el cierre. La solucin nos la
proporciona el mtodo ShowDialog. Este mtodo nos devuelve uno de los valores de la enumeracin
System.Windows.Forms.Dialog-Result.Elvalorretornadonoapareceporazar.Enelmomentodedisearelcuadro
de dilogo, estamos obligados a suministrar el valor que se debe retornar para cada uno de los botones que
provocanelcierredelcuadrodedilogo.EstoesfactiblemediantelapropiedadDialogResultdelcuadrodedilogo
en el evento Click de cada uno de los botones o modificando la propiedad DialogResult de los botones
correspondientesalcierredelcuadrodedilogo.NtesequeenestecasonosegenerareleventoClickdelbotn
para provocar el cierre del cuadro de dilogo. Si se utilizan estas dos soluciones simultneamente, la propiedad
DialogResultdelcuadrodedilogoserprioritariaparadeterminarelvalordevueltoporelmtodoShowDialog.

Ahoraquesabemoscmoconfigurarymostraruncuadrodedilogo,nosquedalomsdifcil:crearlainterfazvisual
delcuadrodedilogo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Utilizacindeloscontroles

Los controles nos permitirn crear la interfaz entre la aplicacin y su usuario. Es a travs de ellos que el usuario
podr actuar sobre el funcionamiento de la aplicacin escogiendo el texto, eligiendo las opciones, lanzando la
ejecucindeunaparteespecficadenuestraaplicacin,etc.

Los controles estarn disponibles en VB.NET a travs de una serie de clases que deberemos instanciar durante la
ejecucindelaaplicacin.

EstasdiferentesclasesdependendeunajerarquaquecomienzaporlaclasebaseControl.Estaclasegarantizalas
funciones elementales de los controles (posiciones, dimensiones...) y una clase derivada agrega funcionalidades
adicionales,yashastalaclasefinaldelajerarqua.

1.Agregarcontroles

Loscontrolespuedenagregarseaunaventanadedosmanerasdiferentes.Lamssencillayrpidaeslautilizacin
delcuadrodeherramientas.Existentresposibilidadesparaagregarcontroles:

l Hacer doble clic en el control en el cuadro de herramientas. Este mtodo permite colocar un ejemplar con unas
dimensionespordefectoenelcentrodelaventana.

l Arrastrarentreelcuadrodeherramientasylaventana.Desdequesobrevuelalaventana,elcursordelratnleindica
conunpequeosignoms(+)quevaaagregaralgoasuventana.Laposicinenlaquesuelteelbotndesuratn
corresponder a la posicin de la esquina superior izquierda de su control. Las dimensiones sern los valores por
defecto.

l Seleccionar el control en el cuadro de herramientas y luego hacer clic, en la ventana, en el lugar en el que desea
colocar la esquina superior izquierda de su control. Despus, sin dejar de pulsar el botn del ratn, dibujar un
rectngulohastaalcanzarlasdimensionesdeseadasparasucontrol.

Siquierecolocarmuchosejemplaresdelmismocontrolensuventana,esposiblebloquearlaseleccinenelcuadro
deherramientasutilizandolatecla[Ctrl]cuandoseleccionaelcontrolenelcuadrodeherramientas.Podrcolocar
entonces diferentes ejemplares del mismo control sin tener que volver a seleccionarlos en el cuadro de
herramientas manteniendopresionadalatecla[Ctrl].

Algunos controles no tienen interfaz visible en el momento de disear la ventana. Para evitar sobrecargar la
superficie de la ventana, se colocan en una zona situada debajo de la ventana de concepcin grfica. Es por
ejemploelcasodeloscontrolesImageListyTimer,queveremosunpocomsadelanteenestecaptulo.Esposible
agregar controles al cuadro de herramientas. Estos controles pueden ser controles .NET o controles ActiveX. La
utilizacindecontrolesActiveXconllevaralgunosinconvenientesparasuaplicacin.Elcdigodesuaplicacinser
menoseficaz(seprecisarnalgunasoperacionesadicionalesparaaccederalcontrolActiveX).

SuaplicacinnecesitarmodificacionesenelregistrodelasmquinaspararegistrarloscontrolesActiveX.

LoscontrolesagregadossonnombradosautomticamenteporVisualStudio,aunqueestosnombresnoseanmuy
explcitos.

Elsiguientecdigonoleparecermuyntido.

Button1.Enabled = False
TextBox1.Clear()
CheckBox1.Checked = True
RadioButton1.Checked = False
RadioButton2.Checked = True

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Esprimordial,paraqueelcdigosealegible,renombrarloscontrolespreferentementedurantesucreacinoms
tarde, pero antes de ser utilizados en el cdigo. Es suficiente con cambiar la propiedad NAME de cada uno en la
ventana de propiedades. No hay una regla absoluta que sea preciso respetar a la hora de dar nombre a los
controles.Unasolucinfrecuentementeutilizadaconsisteenasociarunprefijorepresentativodeltipodelcontrola
unnombreexplicitadoparalaaplicacin.Losprefijosnoestnnormalizados,perolareglasiguienteexistedesde
lasprimerasversionesdeVisualBasic.

Prefijo Control

cbo ComboBox

lst ListBox

chk CheckBox

opt RadioButton

cmd Button

txt TextBox

lbl Label

Utilizandoestasconvencionesyunpocodesentidocomn,elcdigoesnotablementemsclaro:

cmdValidacion.Enabled = False
txtNombre.Clear()
chkCursiva.Checked = True
optAzul.Checked = False
optVerde.Checked = True

2.Posicinydimensindeloscontroles

Despusdecolocarloscontrolesenlaventana,esposiblemoverlosovolveradimensionarlos.Cuandodesplazael
ratnporencimadeuncontrol,elcursorcambiadeaspectoparaindicarlaposibilidaddedesplazarelcontrol.

Es suficiente hacer clic en el control y despus desplazar el ratn. El control seguir entonces a su cursor, para
representar la futura posicin del control. Las lneas de gua se visualizan durante el desplazamiento del control
para facilitar su alineacin con los otros controles ya ubicados en la ventana. Las lneas azules representan las
alineacionesposiblesenlosbordesdelosotroscontroles,laslneasrosasrepresentanlasalineacionesposiblesen
lasetiquetasdeloscontroles.Elcontrolserefectivamentedesplazadoenelmomentoenquesesueltaelbotn
delratn.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Tambinesposibleusarlasflechasdelteclado,queademsaportanmayorprecisinaldesplazamiento.

IgualmentesepuedemodificarlaposicindeuncontrolconsupropiedadLocationenlaventanadepropiedades.
Estapropiedadsemodificacuandodesplazauncontrolconelratnoconelteclado.

Finalmente, la ltima posibilidad es modificar con el cdigo las propiedades Left y Top del control. El siguiente
fragmentodecdigopermitedesplazarelbotnaunaposicinaleatoriacadavezquehagaclicencimadel.

Private Sub cmdtest_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdtest.Click
cmdtest.Left = Rnd() * (Me.ClientSize.Width - cmdtest.Size.Width)
cmdtest.Top = Rnd() * (Me.ClientSize.Height - cmdtest.Size.Height)
End Sub

Una funcionalidad ms avanzada permite colocar los controles en funcin de la posicin de otros controles. Para
poderlasutilizar,esnecesarioseleccionarvarioscontrolesensuventana.Parahacerlo,haydossoluciones:

l Dibujarunrectngulodeseleccinconelratnalrededordeloscontroles.

l Hacerclicenloscontrolesunotrasotro,manteniendolatecla[Ctrl]pulsada.Elprimercontrolseleccionadoaparece
conunospuntosdeseleccinblancos.

LasopcionesdelmenFormatodeVB.NETahoraestndisponiblesyleproporcionanmuchasopcionesparacolocar
loscontroles.Elcontrolqueapareceenlaseleccinconpuntosdeseleccinblancosseconsideracomoreferencia

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
paralaalineacin.

Existenmuchasotrasopcionesparaorganizarlacolocacindeloscontrolesensuventana.

Elcambiodedimensionesdeloscontrolesestambinmuysencillo,yaqueessuficienteseleccionarelcontrololos
controlescuyadimensindeseacambiarycolocarelcursorenunodelospuntosdeseleccin,paraqueaparezca
unaflechaqueleindiqueenqudireccinpuedecambiarladimensindelcontrol.Luegohayquehacerclicenel
cuadradocorrespondienteydesplazarelratnhastaqueelcontrolhayaadquiridolasdimensionesdeseadas.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Tambinpuedeutilizarlasflechasdeltecladoenasociacinconlatecla[Mays]paradimensionarloscontroles.

El cambio de dimensiones con el cdigo utiliza el mtodo SetBounds, que permite a la vez fijar la posicin y las
dimensionesdelcontrol.Elsiguientecdigodisminuyelasdimensionesdelbotncadavezquesehaceclicencima.

Private Sub cmdDisminuir_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdDisminuir.Click
cmdDisminuir.SetBounds(cmdDisminuir.Left, cmdDisminuir.Top,
cmdDisminuir.Size. Width - 5, cmdDisminuir.Size.Height - 5)
End Sub

Despus de muchos esfuerzos para colocar y dimensionar los controles, sera una pena que un error de
manipulacinloestropearatodo.Paraevitarqueesopase,esposibleprotegerloscontrolesenlaventana,atravs
delmenFormatoBloquearcontroles.Estecomandobloqueaeldesplazamientoyelcambiodedimensionesde
todosloscontrolespresentesenlaventana,ascomoelcambiodedimensionesdelapropiaventana.Loscontroles
pueden desprotegerse despus con la misma opcin de men. Tambin puede desproteger individualmente los
controlesconlapropiedadLocked.

Si crea una aplicacin en la que el usuario pueda cambiar el tamao de la ventana durante la ejecucin, los
controles deben seguir las modificaciones de dimensin de la ventana. Para autorizar el cambio automtico del
tamaodeuncontrol,puedeutilizarlapropiedadAnchordelcontrol.Atravsdeella,indicaqueladistanciaentre
losbordesdelcontrolylasposicionesdeanclajeseguardarduranteelcambiodeltamaodelaventana.Cuando
se crean, los controles estn anclados a los bordes superior e izquierdo de la ventana. La modificacin de esta
propiedadserealizaconunpequeoasistente,disponibleenlaventanadepropiedades.

Para modificar la propiedad Anchor, hay que seleccionar el rectngulo correspondiente al lado con que quiere
realizarunanclaje,oeliminarunanclajeexistente.

Porejemplo,paralasiguienteventana,loscontrolesestnancladosalaizquierdayaladerecha.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Sicambiamoseltamaodelaventana,loscontrolessiguenlamaximizacinhorizontaldelaventana.

Tambinpuedeindicarqueuncontroldebeadaptarunaomsdesusdimensionesalasdesucontenedor.Para
hacerlo,utilicelapropiedadDockdelcontrol,indicandoenqubordedesucontenedordebeadaptarelcontroluna
desusdimensiones.

Porejemplo,podemoscolocaruncontrolPictureBoxpidiendoquesefijealbordeinferiordelaventana.

NuestroPictureBoxseadaptaautomticamentealaanchuradelaventanaysequedapegadoasubordeinferior.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
3.Pasodelfocoentrecontroles

Cuandocreasuaplicacin,debepensarenlaspersonasalasquenolesgustausarelratn,peroquedebenpoder
utilizar la aplicacin. Conviene, por lo tanto, crear la aplicacin de manera que pueda funcionar utilizando solo el
teclado(sintecladoniratnsermuchomsdifcil!).

EnunaaplicacindeWindows,sedicequeuncontroltienefococuandoestlistoparaqueelusuarioloutilice.El
foco se puede mover de un control a otro utilizando la tecla [Tab]. Dos propiedades de los controles manejan el
pasodelfococonlatecla[Tab].

l LapropiedadTabStopindicasiuncontrolpodrfocalizarseutilizandolatecla[Tab].

l LapropiedadTabIndexindicaelordenenqueelfocopasadeuncontrolaotro.

Pordefecto,laspropiedadesTabIndexsenumeransegnelordenenelqueloscontrolessehancreado.

Paramodificaresteorden,puedemodificardirectamentelapropiedadTabIndexdecadacontrolousarelmenVer
Orden de tabulacin. Los controles se muestran entonces con el valor de su propiedad TabIndex en la esquina
superiorizquierda.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Despusdebehacerclicenloscontroles,enelordenenquequierequesepaseelfoco.

Elsiguienteordenparecemuchomslgicoparaestecuadrodedilogo.

DespuspuedevolveralmodonormalutilizandootravezelmenVer Ordendetabulacinoutilizandolatecla
[Esc].

4.Tecladeaccesorpido

Algunosusuariosconprisaquierenpodersituarsedirectamenteenuncontrolsintenerquepasarportodoslosque

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
leprecedenenelordendelastabulaciones.Paraello,puedeagregarunatecladeaccesorpidoqueseactivara
travsdelatecla[Alt]msuncarcter.Paraespecificarelcarcterquesedebeutilizarparaactivarelcontrol,hay
queagregarenlapropiedadTextdelcontroluncarcter&delantedelcarcterutilizadoparalatecladeacceso
rpidoasociadaalcontrol.Estohacequeseactiveelatajoysesubrayeelcarctereneltextoqueapareceenel
control.

Siquiereinsertaruncarcter&enlaleyendadesucontrol,hayquerepetirlodosvecesensupropiedadText.

Paraalgunoscontroles(botones,checkbox,botonesdeopcin...)lautilizacindelatajodetecladoequivaleaun
clic del ratn y lanza la accin correspondiente. Para otros, el atajo de teclado coloca simplemente el foco en el
controlcorrespondiente.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Para los controles que no tienen leyenda, habr que utilizar un control LABEL, que les servir de leyenda y que
activartambinelatajodeteclado.Veremostodoestomsadelanteenestecaptulo.

Ahoraquesabemosutilizarloscontrolesenunaaplicacin,vamosaanalizardetalladamentelosmsusados.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LoscontrolesdeVB.NET
Cada control utilizable en VB.NET est representado por una clase, de la que vamos a poder crear instancias para
disear la interfaz de la aplicacin. La mayora de los controles derivan de la clase Control, de la que heredan un
buennmerodepropiedades,mtodosyeventos.

VamosaestudiarloselementosmstilesdelaclaseControl.

1.LaclaseControl

a.Dimensionesyposicin

Las propiedades Left, Top, Width, Height permiten colocar los controles. Estas propiedades pueden ser
modificadasindividualmenteyaceptanvaloresdeltipoInteger.

Esposible,pues,utilizarennuestrocdigolasiguientesintaxis:

TextBoxNombre.Left = 100
TextBoxNombre.Top = 50
TextBoxNombre.Width = 150
TextBoxNombre.Height = 50

Otrasdospropiedadespermitentrabajarconlaposicinylasdimensionesdeuncontrol:lapropiedadLocation
acepta un objeto del tipo Point, gracias al que podemos especificar la posicin de nuestro control del mismo
modo, la propiedad Size, que acepta un objeto del tipo Size, gestiona las dimensiones del control. Las lneas
anterioressepuedenreemplazarcon:

TextBoxNombre.Location = New Point(100, 50)


TextBoxNombre.Size = New Size(150, 50)

En las que construiremos una instancia de Point y de Size, antes de asociarlas a las propiedades
correspondientes.

Unaterceraposibilidadnospermitemanipularalavezlaposicinylasdimensionesdeloscontroles:lapropiedad
BoundsesperaunainstanciadelaclaseRectanguloparadefinirlascaractersticasdelcontrol.Nuestrocdigose
resumeentoncesenunasolalnea:

TextBoxNombre.Bounds = New Rectangulo(100, 50, 150, 50)

ElmtodoSetBoundspermitemodificarlasposicionesydimensionesdeloscontrolessintenerquecrearunanueva
instanciadelaclaseRectangulo,peromodificandolaqueyaestasociadaalcontrol.

TextBoxNombre.SetBounds(100, 50, 150, 50)

La modificacin de estas propiedades conlleva la activacin de los eventos Resize y Move en el control. Por
supuesto, estos eventos se activan cuando el valor de las propiedades se modifica en el cdigo, pero tambin
cuando,porejemplo,lamodificacindelasdimensionesdelaventanaconllevalanecesidaddevolveracolocaro
adimensionarelcontrol.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
El comportamiento de los controles cuando la ventana cambia de tamao est especificado en las propiedades
Anchor y Dock. Hemos visto cmo modificar estas propiedades a travs de la ventana de propiedades. Para
modificarlas con el cdigo, es suficiente asignarles uno de los valores definidos en las enumeraciones
AnchorStyles yDockStyle.

Hasta ahora, las posiciones con las que hemos trabajado eran posiciones expresadas con relacin a la esquina
superior izquierda del contenedor del control. En algunos casos, puede ser til obtener las coordenadas de un
puntodelcontrolnoconrelacinalaesquinasuperiorizquierdadelcontrol,sinoconrelacinalaesquinasuperior
izquierdadelapantalla.ElmtodoPointToScreenpermiteestaconversin.

Espera,comoparmetro,unainstanciadelaclasePointconlascoordenadasexpresadasconrelacinalcontroly
reenvaunanuevainstanciadelaclasePointconlascoordenadasexpresadasconrelacinalapantalla.

ElsiguientecdigoconvierteencoordenadasdepantallalaposicinsuperiorizquierdadeuncontrolTextBox:

System.Console.Write("Control/ventana:")
System.Console.WriteLine(Button2.Location)
Dim p As Point
p = Button2.PointToScreen(Button2.Location)
System.Console.Write("Control/pantalla:")
System.Console.WriteLine(p)

Resultado:

Control/ventana:{X=107,Y=72}
Control/pantalla:{X=306,Y=255}

La operacin contraria se puede realizar con el mtodo PointToClient, que toma como parmetro un punto en
coordenadas de pantalla y reenva un punto expresado en coordenadas relativas al control. Si se realiza la
operacincontraria,esdecir,partiendodelascoordenadasdepantalla,seobtieneelmismovalor:

System.Console.WriteLine("control / ventana relativo a la pantalla " &


Button2.PointToClient(p).ToString)

Resultado:

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
control / ventana relativo a la pantalla{X=107,Y=72}

b.Aspectodeloscontroles

El color de fondo del control se puede modificar con la propiedad BackColor, mientras que el color del texto del
controlsemodificaconlapropiedadForeColor.

Se pueden asignar a estas propiedades valores definidos en el espacio de nombre System.Drawing.Color para
obtenercolorespredefinidosenVisualBasic.

TextBoxNombre.BackColor = System.Drawing.Color.Yellow

TambinsepuedenutilizarlasconstantesdefinidasenelespaciodenombresSystem.Drawing.SystemColorspara
utilizar uno de los colores definidos a nivel del sistema operativo. En este caso, su aplicacin se adaptar en
funcindelaconfiguracindelamquinaenlaquefuncione.

TextBoxNombre.BackColor=System.Drawing.SystemColors.InactiveCaptionText

Latercerasolucinconsisteenrealizarunamezcladecolores,utilizandolafuncinFromArgbyespecificandocomo
parmetrolacantidaddecadacolorbase(Rojo,Verde,Azul).

TextBoxNombre.BackColor = System.Drawing.Color.FromArgb (127, 0, 127)

La fuente se puede modificar con la propiedadFont del control. Se puede crear una nueva instancia de la clase
Fontyasignarlaalcontrol.ExistentrececonstructoresdiferentesparalaclaseFont,oseatrecemanerasdistintas
decrearunafuentedeletra.Nosotrosvamosausarlamssencilla,indicandosimplementeeltipodefuenteylas
dimensiones.

TextBoxNombre.Font = New Font(System.Drawing.FontFamily.Generic


Monospace, 16)

Despusdehaberrealizadolasmodificacionesdeestaspropiedades,esposiblevolveraunaconfiguracinnormal
llamando a los mtodos ResetBackColor, ResetForeColor, ResetFont. Las correspondientes propiedades se
reinicianconlosvaloresdefinidosporelcontenedordelcontrol.

La propiedad BackgroundImage permite especificar una imagen que se utilizar de fondo para el control. Si la
imagennoessuficientementegrandeparacubrirelcontrol,sereproduceenmosaico:

BtnValidar.BackgroundImage = New Bitmap("cut.bmp")

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Aveceselresultadoesdesconcertante!

Paravolveraalgomsclsico:

BtnValidar.BackgroundImage = Nothing

LapropiedadCursorpermiteelegirelaspectodelcursorcuandoelratnseencuentraenlasuperficiedelcontrol.
MuchoscursoresestnpredefinidosenWindows.

EstoscursoresestnenlacoleccinCursorsypuedenutilizarsedirectamenteasignndolos alapropiedadCursor
delcontrol.

BtnValidar.Cursor = Cursors.WaitCursor

Sinoleinteresaningunodeellos,puedeutilizaruncursorpersonalizadocreandounainstanciadelaclaseCursor
yasignndoloalapropiedadCursordelcontrol.

BtnValidar.Cursor = New Cursor("h_nodrop.cur")

La deteccin de la entrada y de la salida del ratn en el control y la modificacin del cursor se gestionan
automticamente.

Comoparalafuentedecaracteres,esposiblerestaurarelcursorpordefectollamandoalmtodoResetCursor.

La modificacin de la mayora de las propiedades de los controles desencadena un evento. Estos eventos se
identifican con el nombre de la propiedad seguido del sufijo Changed. Pueden utilizarse para guardar las
preferenciasdeunusuarioypersonalizarlaaplicacin.

Private Sub Form1_BackColorChanged(ByVal sender As Object, ByVal e As


System.EventArgs) Handles Me.BackColorChanged

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
My.Settings.ColorFondo = Me.BackColor
My.Settings.Save()
End Sub

c.Comportamientodeloscontroles

Los controles colocados en una ventana se pueden ocultar modificando la propiedad Visible o desactivar
modificandolapropiedadEnabled.Enestecaso,elcontrolestsiemprevisible,peroaparececonunaspectogris
paraindicarlealusuarioqueestecontrolestinactivoporelmomento.

BtnValidar.Enabled = False

Obviamente,loscontrolesenesteestadonopuedenrecibirelfocoenlaaplicacin.Puedeverificarloexaminando
lapropiedadCanFocus,quereenvaunBooleano.Puedeverificartambinsiuncontroltieneelfocoenunmomento
dado controlando la propiedad Focused o la propiedad ContainsFocus. Esta ltima se tiene que utilizar con los
controles contenedores (es decir, los controles que pueden contener otros controles). En este caso, esta
propiedadsecolocaenTruesiunodeloscontrolessituadosdentrodelcontenedorestfocalizado.

Elfocopuedecolocarseenuncontrolsinlaintervencindelusuario,llamandoelmtodoFocusdelcontrol.

BtnValidar.Focus()

Paracontrolarelpasodelfocodeuncontrolaotro,existencuatroeventos:

l Enterindicaquelafocalizacinllegaaunodeloscontrolesdeuncontenedor.

l GotFocusindicaqueuncontrolenparticularharecibidoelfoco.

l LostFocusindicaqueuncontrolhaperdidoelfoco.

l Leaveindicaqueelfocoyanoestenunodeloscontrolesdeuncontenedor.

Por ejemplo, para destacar que un control est focalizado, se puede utilizar el siguiente cdigo, que modifica el
colordeltextocuandoelcontrolrecibeopierdeelfoco:

Private Sub TxtNombre_GotFocus(ByVal sender As Object, ByVal e As System.


EventArgs) Handles TextBoxNombre.GotFocus
TextBoxNombre.ForeColor = System.Drawing.Color.Red
End Sub

Private Sub TxtNombre_LostFocus(ByVal sender As Object, ByVal e


As System.EventArgs) Handles TextBoxNombre.LostFocus
TextBoxNombre.ResetForeColor()
End Sub

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Enalgunoscasos,esdeseableverificarlosdatosintroducidosporelusuarioenunformularioantesdecontinuar
enlaaplicacin.Estaverificacinpuederealizarsealcerrarelformulariooamedidaqueserellenanlosdiferentes
controlesdelformulario.

Cada control se puede configurar para permitir la verificacin de estos datos modificando la propiedad
CausesValidationaTrue.Justoantesdequeelcontrolpierdaelfoco,eleventoValidatingseactivaparapermitir
laverificacindelosdatosintroducidosporelusuario.Silotecleadonoescorrecto(enfuncindeloscriteriosque
hemos establecido), podemos bloquear el paso del foco hacia otro control modificando la propiedad Cancel del
objetoCancelEventArgquesepasacomoparmetro.Enestecaso,elfocosequedaenelcontrolcorrespondiente
a los datos introducidos que no son correctos. Si los datos son correctos, el evento Validated se activa en el
controlyelfocosedesplazaalcontrolsiguiente.

Por ejemplo, para introducir un nmero de telfono, podemos verificar que se han introducido solo valores
numricos.Encasodeerror,generamosunbeep,modificamoselcolordeltextoybloqueamoselpasodelfocoa
otrocontrol.

Private Sub TxtTel_Validating(ByVal sender As Object, ByVal e As System.


ComponentModel.CancelEventArgs) Handles txtTel.Validating
If Not IsNumeric(txtTel.Text) And txtTel.Text <> "" Then
Beep()
txtTel.ForeColor = System.Drawing.Color.Red
e.Cancel = True
End If
End Sub

Private Sub TxtTel_Validated(ByVal sender As Object, ByVal e As System.


EventArgs) Handles txtTel.Validated
txtTel.ResetForeColor()
End Sub

Dospropiedadessontilescuandotrabajamosconcontrolescontenedor.LapropiedadHasChildrennospermite
sabersihaycontrolescolocadosennuestrocontenedor.Sieselcaso,lacoleccin Controlscontienelalistade
todosestoscontroles.Porejemplo,podemosmodificarelcolordeltextodetodosloscontrolesdeuncontenedor
cuandoelfocoestcolocadoenunodeellos.

Private Sub GroupBox1_Enter(ByVal sender As Object, ByVal e


As System. EventArgs) Handles GrBoxIdent.Enter
If GrBoxIdent.HasChildren Then
Dim x As Object
For Each x In GrBoxIdent.Controls
x.forecolor = System.Drawing.Color.YellowGreen
Next
End If
End Sub

Private Sub GroupBox1_Leave(ByVal sender As Object, ByVal e


As System.EventArgs) Handles GrBoxIdent.Leave
If GrBoxIdent.HasChildren Then
Dim x As Object
For Each x In GrBoxIdent.Controls
x.resetforecolor()
Next
End If

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Sub

Laoperacinopuestatambinesposible,esdecir,queapartirdeuncontrolpodemosrecuperarlaspropiedades
desucontenedor.LapropiedadParentproporcionaunareferenciahaciaelcontenedordelcontrol.Podemos,por
ejemplo,hacerqueelcolordefondodecadacontrolcambiealmismotiempoqueeldesucontenedor.

Private Sub GrBoxIdent_BackColorChanged(ByVal sender As Object,


ByVal e As System.EventArgs) Handles GrBoxIdent.BackColorChanged
If GrBoxIdent.HasChildren Then
Dim x As Object
For Each x In GrBoxIdent.Controls
x.backcolor = x.parent.backcolor
Next
End If
End Sub

Ahoraquehemosexploradolaspropiedadescomunesdelosdistintoscontrolesdisponibles,vamosaestudiarlos
unoporunoanalizandosusparticularidades.

2.Loscontrolesdevisualizacindeinformacin

a.ElcontrolLabel

El control Label se usa para mostrar, en un formulario, un texto que el usuario no podr modificar. Sirve
esencialmenteparaproporcionarunaleyendaaloscontrolesquenolaposeen(zonasdetextoporejemplo,lista
desplegable...).Enestecaso,permitirtambinproporcionarunatajodetecladoparaelcontrol.

EltextomostradoporelcontrolseindicaconlapropiedadText.Estapropiedadpuede,porsupuesto,modificarse
con el cdigo de la aplicacin. Por lo tanto, hay que tener cuidado, porque por defecto el control conserva las
dimensionesquelehanasignado ensucreacin.SilanuevacadenadecaracteresasignadaalapropiedadText
es ms larga que la especificada en el momento de la creacin, solo se podr ver el inicio. Para evitar este
problema, hay que pedirle al control Label que adapte su anchura en funcin del texto que se va a mostrar,
modificandolapropiedadAutoSizeenTrue.

Por defecto, el control Label no tiene borde. Puede aadirlo modificando la propiedadBorderStyle, y utilizando
unodelostresvaloresdisponibles.

TambintienelaposibilidaddeindicarlaposicindeltextoenelcontrolatravsdelapropiedadTextAlign.Enel
cdigo,utilizarunadelasconstantespredefinidas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Mediantelaventanadepropiedades,essuficienteconhacerclicenlaposicindeseadaparaeltextodentrodesu
control.

HayqueresaltarquelapropiedadTextAlignmodificarlaposicindeltextosolosilapropiedad AutoSize est en


False.

LoscontrolesLabeltambinpuedenmostrarimgenes.Puedeindicarlaimagenquedeseamostrarutilizandola
propiedad Image. Otra solucin consiste en usar un control ImageList, que servir, de alguna manera, para
almacenarlasimgenesdelaaplicacin.Enestecaso,indicamosconlapropiedadImageListenqucontrolvamos
abuscarlaimagenyconlapropiedadImageIndexenqulugarseencuentraenelcontrolImageList.Siutilizaun
controlImageList,lapropiedadImagedesucontrolseignorar.Comoparaeltexto,puedemodificarlaposicinde
la imagen en el control gracias a la propiedad ImageAlign, con las mismas constantes que para la propiedad
TextAlign.

HemosindicadoqueelcontrolLabelsepodautilizarcomoatajodetecladoparaotrocontrol.Parahacerlo,hay
quetomartresprecauciones.

l Como con los otros controles, agregar un & en la propiedad Text para el carcter utilizado como tecla de acceso
rpido.

l IndicaralcontrolLabelsupapeldegestordeatajodetecladomodificandolapropiedadUseMnemonicenTrue.

l Verificarqueelcontrolquedeberecibirlafocalizacinestinmediatamentedespusdelcontrol Labelenelorden
delastabulaciones(propiedadTabIndex).

b.ElcontrolLinkLabel

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ElcontrolLinkLabelheredatodaslascaractersticasdelcontrolLabelysoloagregafuncionalidadesdeenlacede
estilo Web. Las propiedades adicionales en relacin con el control Label gestionan los diferentes parmetros del
enlace.

LapropiedadLinkAreaindicaquporcindeltextoactivarelenlace.Estapropiedadsepuedemodificaratravs
delaventanadepropiedades,conunpequeoasistenteenelquetienequeseleccionarlaporcindetextoque
constituyeelvnculo.

Loscoloresutilizadosparaelenlacesepuedenmodificarcontrespropiedades:

LinkColor Colordelenlaceenelestadonormal.

VisitedLinkColor Colordelenlacedespusdeunaprimerautilizacin.

ActiveLinkColor Colordelenlaceenelmomentoenquesehaceclic.

LaaparienciadelenlacesepuedemodificarconlapropiedadLinkBehavior.

Loscuatrovaloresposiblespermitenrespectivamente:

l Utilizarlamismaconfiguracinparalosenlacesqueparasunavegador.

l Tenerlosenlacessiempresubrayados.

l Tenerlosenlacessubrayadoscuandoelratnpasaencimadeellos.

l Notenernuncalosenlacessubrayados.

Cuandoelusuariohaceclicenelenlace,eleventoLinkClickedseactivaenlaaplicacin. Eselusuarioquiendebe
escribirelcdigoparaejecutarunaaccinensuaplicacin.

Tiene tambin que modificar la propiedad LinkVisited colocndola en True, para indicar que este enlace ya ha
sidoutilizadoenlaaplicacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
LaaccinpuedeserlaaperturadeunapginadeunsitioWebenelnavegadorpordefecto,comoenelsiguiente
ejemplo:

Private Sub LinkMicrosoft_LinkClicked(ByVal sender As System.Object,


ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs)
Handles LinkLabel1.LinkClicked
System.Diagnostics.Process.Start(" http://www.microsoft.es ")
LinkLabel1.LinkVisited = True
End Sub

Otambinlavisualizacindeunanuevaventanaennuestraaplicacin,comoenelsiguienteejemplo:

Private Sub LinkMicrosoft_LinkClicked(ByVal sender As System.Object,


ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles
LinkMicrosoft. LinkClicked
Dim ventana As dlgPerso
ventana = New dlgPerso()
ventana.ShowDialog()
LinkMicrosoft.LinkVisited = True
End Sub

c.ElcontrolStatusStrip

ElcontrolStatusStripseusanormalmenteparapresentarinformacinalusuarioacercadelfuncionamientodela
aplicacin.Puedemostrarlainformacinendistintaszonas.Losdatossepuedenmostrarenformadetexto,de
barradeprogreso,demenodebotndecomandoasociadoaunmen.Uneditorespecfico,accesibledesdela
propiedadItemsdelcontrol,permitesuconfiguracin.

Cada elemento agregado al control StatusStrip debe configurarse individualmente a continuacin. Las
propiedadesdeloselementosquepuedenutilizarseparalaconstruccindeunStatusStripsonmuyparecidasa

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
lasdeloscontrolesnormales.Porejemplo,elelementoToolStripStatusLabelesprcticamenteidnticoalcontrol
LinkLabel.

d.ElcontrolToolTip

Estecontrolpermitemostrarunaetiquetadeayudaasociadaauncontrol.Estecontrolnotieneinterfazvisible:se
colocar en la zona situada por debajo de la ventana de diseo. Realiza mucho trabajo sin ningn esfuerzo de
programacin.Controlasiempre,porejemplo,dndeseencuentraelratn.Siestencimadeuncontrol,verificasi
existeunasugerenciaasociadaalcontrolysiesnecesariomuestralasugerenciacorrespondientealapropiedad
AutoPopDelay.

Parapoderfuncionar,elcontrolToolTipdebeasociarunacadenadecaracteresacadaunodeloscontrolesdela
interfaz. Para hacerlo, cuando un control ToolTip est disponible en una ventana, se agrega una propiedad
ToolTipacadacontrol,permitiendoasespecificareltextodelasugerenciaasociadaalcontrol.

Las cadenas de caracteres asociadas a cada control pueden indicarse con el cdigo, llamando el mtodo
SetToolTipeindicandocomoparmetroselnombredelcontrolylacadenadecaracteresalasociada.

ToolTip1.SetToolTip(RadioButton3, " Color azul para el texto ")

Estatcnicapermiteconservarleyendasrelativamentebrevesparaloscontroles,peroquealavezproporcionan
lainformacinsuficientesobrelautilizacindelaaplicacin.

e.ElcontrolErrorProvider

Estecontrolpermiteindicarfcilmentealusuariolosproblemasrelativosalosdatoselegidosenunformulario.En
general, interviene en la fase de validacin de los datos del formulario, mostrando frente a cada control un

pequeoicono parallamarlaatencindeeste.Sepuedeproporcionarinformacinadicionalconunmensaje

asociadoalcontrolErrorProvider.

UnmismocontrolErrorProvidersepuedeutilizarparatodosloscontrolesdeunformulario.

LaactivacindelcontrolErrorProvidersepuederealizarenelmomentodecerrarelformulario,cuandoelusuario
hace clic en el botn Aceptar, pero tambin es posible controlar la eleccin en el momento en que se realiza,
gestionandoporejemploloseventosValidating.Esteeventoseactivaenuncontrolenelmomentoenqueeste
pierde el foco. Podemos, en este caso, verificar inmediatamente el valor escogido en el control y reaccionar
mostrandonuestrocontrolErrorProvider.Parahacerlo,llamamoselmtodoSetErrorespecificandoelnombredel
controlquenoscausaelproblemaylacadenadecaracteresmostradaenlasugerenciaasociadaalcontrol.Sino
hayerrores,hayquereiniciarlacadena,paraquedesaparezcaeliconodelcontrolErrorProvider.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Private Sub TextBox1_Validating(ByVal sender As Object, ByVal e As System.
ComponentModel.CancelEventArgs) Handles TextBox1.Validating
If Not IsNumeric(TextBox1.Text) Then
ErrorProvider1.SetError(TextBox1, " Valor numrico obligatorio ")
Else
ErrorProvider1.SetError(TextBox1, "")
End If
End Sub

f.ElcontrolNotifyIcon

Estecontrolseusaprincipalmenteparamostrarinformacinsobreelfuncionamientodeunprocesoenejecucin
comotareadefondoenlaaplicacin.Semuestraenlazona deestadodelsistemaoperativo.LapropiedadIcon
delcontroldeterminaeliconomostrado.LapropiedadTextrepresentalaleyendamostradacuandoelratnpasa
porencimadelcontrol.

GestionandoeleventoDoubleClickdelcontrol,puedemostraruncuadrodedilogoquepermitalaconfiguracin
delprocesoasociadoalcontrol.

Private Sub IconService_DoubleClick(ByVal sender As Object, ByVal e As


System.EventArgs) Handles IconService.DoubleClick
Dim dlg As ConfigService
lg = New ConfigService
dlg.ShowDialog()
End Sub

Tambinesposibleasociarunmencontextual,utilizandolapropiedadContextMenuStrip.Estemenpuede,por
ejemplo,controlarelfuncionamientodelprocesoalqueestasociadoelcontrol.

g.ElcontrolHelpProvider

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ElcontrolHelpProvidergarantizalarelacinentreelarchivodeayudaylaaplicacin.Elarchivodeayudadebeser
generado por la herramienta Html Help Workshop, disponible en el sitio de Microsoft. Para nuestros ejemplos,
utilizaremos un archivo de ayuda existente en el sistema operativo: el archivo C:\WINDOWS\Help\charmap.chm,
que corresponde a la Tabla de caracteres. Este archivo se debe asociar al control a travs de la propiedad
HelpNamespace. La presencia de un control HelpProvider en una ventana agrega automticamente tres
propiedadesacadacontrolpresenteendichaventana:

HelpKeyword

Indicalapalabraclaveasociadaalcontrolenelarchivodeayuda.

HelpNavigator

Indicalaaccinejecutadadurantelavisualizacindelaayuda.

HelpString

Contienelacadenadecaracteresmostradadurantelautilizacindelbotn deuncuadrode
dilogo.Paraqueestebotnestdisponibleenelcuadrodedilogo,hayquemodificarlapropiedad
HelpButtondelaventanaaTrueyocultarlosbotonesdemaximizacinydeminimizacindela
ventana,modificandolaspropiedadesMaximizeBoxyMinimizeBoxafalse.

El siguiente ejemplo asocia al botn de comando CmdOk el men de ayuda Visin de conjunto de la tabla de
caracteres del archivo charmap.chm y configura el sistema de ayuda, para que este men se muestre
automticamentecuandoseutilizalatecla[F1].

h.ElcontrolProgressBar

Estecontrolseutilizaparainformaralusuarioacercadelprogresodeunaaccinlanzadaenlaaplicacin.Muestra
esta informacin en forma de una zona rectangular, que se llenar ms o menos en funcin del estado de
progreso de la accin ejecutada. Se controla el aspecto de la ProgressBarconsupropiedad Style. Existen tres
valores:

Continuous

Elprogresosemuestraconunabarraazulllena.

Blocks

Elprogresosemuestraconunaseriedepequeosrectngulos.

Marquee

Estapresentacinesidnticaalaanterior,conunmovimientoademsdentrodelaProgressBar.

LaposicindelabarradeprogresinestcontroladaporlapropiedadValue.Estapropiedadpuedevariarentre
losdosextremosindicadosporlaspropiedadesMinimumyMaximum.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Existentrestcnicasdisponiblesparaquesemuevalabarradeprogreso:

l ModificardirectamentelapropiedadValuedelcontrol.Hayquenotar,queenesecaso,sielvalordeestapropiedad
superalosextremos,seactivaunaexcepcin.

l Utilizar el mtodo PerformStep, que aumenta a cada llamada la propiedad Value con el valor contenido en la
propiedad Step.Elcontrolverifica,enestecaso,elvalorcontenidoenlapropiedad Valueyseaseguradequeno
superelosextremos.

l Utilizar el mtodo Increment indicando como parmetro el valor utilizado como incremento para la propiedad
Value.ElvalordelapropiedadValueseverificatambindurantelaejecucindeestemtodo.

Sila ProgressBartieneelestiloMarquee,lapropiedadValuenotieneningnefectoenlasdimensionesdelabarra
deprogresoynoconvieneutilizarlosmtodosPerformStepeIncrementporquesegeneraunaexcepcin.

ElejemplosiguientepresentaunoriginalrelojenelquelahorasemuestraatravsdetresProgressBar:

Public Class Reloj


Public Sub New()
This call is required by the Windows Form Designer.
InitializeComponent()
Add any initialization after the InitializeComponent() call.
pgbHora.Minimum = 0
pgbHora.Maximum = 23
pgbHora.Style = ProgressBarStyle.Continuous
pgbMinuto.Minimum = 0
pgbMinuto.Maximum = 59
pgbMinuto.Style = ProgressBarStyle.Continuous
pgbSegundo.Minimum = 0
pgbSegundo.Maximum = 59
pgbSegundo.Style = ProgressBarStyle.Continuous
Timer1.Interval = 500
Timer1.Enabled = True
End Sub

Private Sub Timer1_Tick(ByVal sender As Object, ByVal e


As System.EventArgs) Handles Timer1.Tick
pgbHora.Value = Now.Hour
pgbMinuto.Value = Now.Minute
pgbSegundo.Value = Now.Second
End Sub
End Class

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
3.Loscontrolesdeedicindetexto

a.ElcontrolTextBox

ElcontrolTextBoxseutilizaparapermitiralusuariointroducirdatos.Sepuedeconfigurarelcontrolparainsertar
texto en una o varias lneas. El tamao mximo del texto vara de 2.000 a 32.000 caracteres, segn la
configuracindelcontrol(lneasimpleolneasmltiples).Elcontroltambinescapazdegestionarlaseleccinde
textoylasoperacionesconelportapapeles.Paratrabajarconestecontrol,haydisponiblesmuchaspropiedadesy
mtodos. El texto mostrado en el control puede ser modificado o recuperado mediante la propiedad Text. Es
posible modificar el formato de visualizacin del texto mediante distintas propiedades. La propiedad Autosize
permitepedirlealcontrolTextBoxquecambiesutamaoenfuncindelasdimensionesdelafuentedecaracteres.
EstapropiedadsesitacasisiempreenTrue.LapropiedadCharacterCasingautorizaacontrolparaquemodifique
todosloscaractereselegidos,tantolasminsculascomolasmaysculas.

LapropiedadLinespermiterecuperareltextointroducido,lneaalnea.Estapropiedadesunamatrizdecadenas
de caracteres que contiene tantas casillas como lneas. Esta propiedad solo tiene inters si el control est
configuradoparaaceptarlaintroduccindedatosenvariaslneasconlapropiedadMultilineenposicinTrue.En
estecaso,tambinhayquepreverlaposibilidaddepoderdesplazareltextoaadiendobarrasdedesplazamiento
con la propiedad ScrollBars. Las distintas posibilidades permitirn tener una barra de deslizamiento horizontal,
vertical o ambas. Cuidado, sin embargo, ya que la barra de desplazamiento vertical solo ser visible si la
propiedadWordWrapestenFalse.Encasocontrario,elcontrolgestionaporsmismoelsaltodelneacuandola
longituddelalneasuperalaanchuradelcontrol.Enestecaso,losretornosdecarroaadidosautomticamente
noseinsertaneneltexto.

En este ejemplo, la propiedad Lines contendr dos elementos, porque el primer retorno de carro se agrega
simplementeconelcontrolparasuvisualizacin.

Lines(0)>HoyhacebuentiempoenMadrid

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Lines(1)>Quesignaas!

LalongitudmximadeltextodelcontrolsefijaconlapropiedadMaxLength.Hayquetenerencuentaque,enel
casodeuncontroldelneasmltiples,loscaracteresderetornodecarroydesaltodelneatambincuentan.Se
suele utilizan esta propiedad cuando se hace uso del control TextBox para introducir una contrasea. En este
caso, la propiedad PasswordChar indica el carcter utilizado durante la visualizacin para ocultar la insercin del
usuario.Sesueleutilizarelcarcter*o#.Estapropiedadsoloinfluyeenlavisualizacinyloscaractereselegidos
porelusuarioserecuperansiempreenlapropiedadText.

Lagestindelaseleccindeltextolarealizaelcontroldeformaautomtica.LapropiedadSelectedTextpermite
recuperar la cadena de caracteres actualmente seleccionada en el control. Las propiedades SelectionStart y
SelectionLengthindicanrespectivamenteelcarcterdeliniciodelaseleccin(elprimercarcterdendice0)yel
nmerodecaracteresdelaseleccin.

Tambin se utilizan estas propiedades para insertar texto en el control: la propiedad SelectionStart indica en
este caso el punto de insercin y la propiedad SelectedText, el texto que hay que insertar. Para aadir texto
despus del ya existente en el control, resulta ms prctico emplear el mtodo AppendText pasndole como
parmetrolacadenadecaracteresquedeseaagregar.

La sustitucin de una porcin de texto en el control TextBox se ejecuta en dos etapas. Ante todo, hay que
seleccionar el texto que se desea sustituir utilizando las propiedades SelectionStarty SelectionLength luego
hayqueindicareltextosustitutivoconlapropiedadSelectedText.Eltextosustituidoyeldesustitucinnotienen
porqutenerelmismotamao.

TextBox1.SelectionStart = 28
TextBox1.SelectionLength = 11
TextBox1.SelectedText = "Mediterrneo"

TambinlaseleccindetextopuedeefectuarseconelmtodoSelect,indicandoelcarcterdeiniciodelaseleccin
yelnmerodecaracteresdelaseleccin.

TextBox1.Select(28,11)
TextBox1.SelectedText = "Mediterrneo"

LaseleccindelatotalidaddeltextosepuedeefectuarconelmtodoSelectAll.Porejemplo,sepuedeforzarla
seleccindetodoeltextocuandoelcontrolrecibeelfoco.

Private Sub TextBox1_GotFocus(ByVal sender As Object, ByVal e As System.


EventArgs) Handles TextBox1.GotFocus
TextBox1.SelectAll()
End Sub

Clsicamente,encuantouncontrolpierdeelfoco,laseleccindetextoqueestabaenelinteriordeltextoyanoes
visible.LapropiedadHideSelectionenFalsepermiteconservarlaseleccinvisible,inclusosielfocoyanotieneel
foco.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Para la gestin del portapapeles, el control TextBox dispone de un men contextual que permite realizar las
operacioneshabituales.Sinembargo,existelaposibilidaddellamarlosmtodosCopy,CutyPasteparagestionar
lasoperacionesdecopiarpegardeotramanera,porejemplounmendelaaplicacin.Lasoperacionescortary
pegarnosernposiblessielcontrolTextBoxestconfiguradoensololecturaconlapropiedadReadOnlyenTrue
lamodificacindeltextoporelusuarioesimposibleenestecaso.

Comotodoelmundosepuedeequivocar,elcontrolTextBoxnosproponeelmtodoUndo,quepermitecancelarla
ltimamodificacindetextoefectuadaenelcontrol.Estemtodoyasepuedeutilizarconlaopcincancelardel
mencontextualdelcontrolTextBoxoporelatajodeteclado[Ctrl]Z.Tambinselapuedellamargraciasaotro
mendesuaplicacin.SoloexisteunniveldeUndo,nopodrvolveraltextoqueescribihacedoshoras!

En este control tambin est disponible el evento TextChanged, que se produce cuando la propiedad Text del
control se ha modificado (con el cdigo de la aplicacin o porque lo hace el usuario). No se debe modificar la
propiedadTextdesucontrolenelcdigodeesteevento,sopenadegenerarundesbordamientodepilaenla
ejecucindelaaplicacin,comoenelejemplosiguiente.

Private Sub TextBox1_TextChanged(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles TextBox1.TextChanged
TextBox1.Text = Rnd()
End Sub

b.ElcontrolMaskedTextBox

Este control es una mejora del control TextBox, porque permite verificar automticamente que la informacin
elegidasecorrespondaconloquelaaplicacinespera.LapropiedadMaskdeterminaelformatodelosdatosque
se pueden introducir en el control. El editor, accesible desde la ventana de propiedades, permite elegir una
mscaraexistenteoconfigurarsupropiamscara.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
EnlapropiedadMaskalgunoscaracterestienenunsignificadoespecial:

0representaunacifraobligatoria(0a9).

9representaunacifraounespacioopcional.

Lrepresentaunaletraobligatoria(deaaz,odeAaZ).

?representaunaletraopcional.

Crepresentauncarctercualquiera.

.representaelseparadordecimal.

,representaelseparadordemiles.

:representaelseparadorhorario.

/representaelseparadordefecha.

$representaelsmbolomonetario.

<lossiguientescaracteresserntransformadosenminsculas.

>lossiguientescaracteresserntransformadosenmaysculas.

|cancelaelefectodedoscaracteres>y<.

\carcterdeescapequehaceperdersusignificadoespecialalsiguientecarcter.

Todoslosotroscaracteressevisualizantalycomoaparecenenelcontrol.

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lasiguientemscarapuedeutilizarse,porejemplo,paralaintroduccindeunadireccinIP :

000\.000\.000\.000

c.ElcontrolRichTextBox

El control RichTextBox permite la visualizacin, la introduccin y la modificacin de texto con formato. Posee las
mismasfuncionalidadesqueelcontrolTextBox,peroademsescapazdegenerardistintasfuentesdecaracteres,
distintos colores, imgenes, etc. Ofrece todas las funcionalidades de base de una aplicacin de tratamiento de
texto.Acontinuacinvamosadetallarlasfuncionesprincipales:

Cargayregistrodearchivo

Los mtodos LoadFile y SaveFile permiten la carga y el registro desde o hacia un archivo. El nico parmetro
obligatorioparaestasdosfuncionesrepresentalarutadeaccesocompletahaciaelarchivoquedeseacargaro
guardar.Elformatodearchivoutilizadopordefectoparaestasdosfuncioneseselformatortf(RichTextFormat).Si
fueranecesarioutilizarotrosformatosdearchivo,deberemosespecificarloconunsegundoparmetroqueesuna
constantedelaenumeracinRichTextBoxStreamType.Enelcasodeunalecturadearchivo,esimportantequelos
datoscontenidosenelarchivoconcuerdenconlaconstanteutilizada.

Porejemplo,lalecturadeunarchivodetextonormalconlasiguientelneadecdigoactivarunaexcepcin.

rtb.LoadFile(dlgAbrir.FileName, RichTextBoxStreamType.RichText)

Encambio,nohayproblemaparaelregistro,yaqueelcontrolRichTextBoxgestionaporsmismoelformatodelos
datosinscritosenelarchivo.Elnicoriesgoconsisteenperderlosdatosdeconfiguracindepginacontenidosen
elcontrolsiseutilizaunformatoderegistroinadecuado.Porejemplo,lasiguientelneaharquesepierdantodos
losdatosdeformateoduranteelregistrodelarchivo.

rtb.SaveFile(dlgGrabar.FileName, RichTextBoxStreamType.PlainText)

Insertartexto

ElcontrolRichTextBoxadministrasucontenidograciasadospropiedades:

l La propiedad Text que, como para los dems controles, define los datos visualizados en el control. En esta
propiedadsealmacenaeltextoenbruto.

l La propiedad Rtf tambin contiene el texto mostrado por el control, pero adems incorpora informacin
concernientealapresentacindeltexto.

Para agregar texto a un control, podemos utilizar la propiedadText o la propiedad Rtf. En este segundo caso,
tambinesnecesarioincluirloscaracteresdeformatoutilizadosporelcontrolparaelformatodeltexto.Puesto
queloscdigosRtfdistanmuchodesersencillos,raravezseutilizaestasolucin.Afortunadamente,existeuna
solucinmsfacil.

ElmtodoAppendTextpermiteagregarunacadenadecaracteresalcontenidodelcontrolRichTextBox.Elformato
delacadenaquehayqueagregarpuededefinirsepreviamentemediantelaspropiedadesdelaseleccin.

LapropiedadSelectionFontdeterminalafuenteutilizadaparavisualizareltextoagregado.Paraagregartextoen

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 19 -
negritaysubrayado,esnecesariomodificarlascaractersticasdelafuente.Msexactamente,esnecesariocrear
la fuente deseada, ya que no es posible modificar las caractersticas de una fuente existente, puesto que sus
propiedadessondesololectura.

Lasintaxissiguienteeslacorrectaparalamodificacindelascaractersticasdelafuenteexistente:

rtb.SelectionFont = New Font (rtb.SelectionFont, FontSyle.Bold +


FontSyle.Underline)

LoscoloresdeltextoydelfondoestndeterminadosporlaspropiedadesSelectionColorySelectionBackColor.

rtb.SelectionBackColor = Color.Beige
rtb.SelectionColor = Color.Red

La alineacin del texto est representada por la propiedad SelectionAlignment, que es a la que usted debe
asignarunodelosvaloresdelaenumeracinHorizontal-Alignment.

rtb.SelectionAlignment = HorizontalAlignment.Center

4.Loscontrolesdeactivacindeacciones

a.ElcontrolButton

El control Button se utiliza principalmente para lanzar la ejecucin de una accin en una aplicacin. Esta accin
puedeserlaejecucindeunaporcindecdigooelcierredeuncuadrodedilogo.Comoenloscontrolesvistos
hastaahora,elttulodelbotnsepuedemodificarconlapropiedadTextdelcontrol.EstapropiedadTextpuede
contener un & para crear un atajo de teclado. Cuando utilice el botn para cerrar un cuadro de dilogo, debe
indicar, mediante la propiedad DialogResult, el valor que ser devuelto cuando el botn cierre el cuadro de
dilogo. Los valores que se pueden utilizar para esta propiedad corresponden a los botones estndar de
Windows.

- 20 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Cuandosecreauncuadrodedilogo,suelehaberalmenosunbotndevalidacinyunbotndecancelacin.Se
puedeindicarque,enestecuadrodedilogo,lautilizacindelatecla[Intro]seaequivalenteaunclicenelbotn
devalidacinylautilizacindelatecla[Esc]equivalgaalusodelbotndecancelacin.Convieneparaelloindicar
enlapropiedadAcceptButtondelaventanaelnombredelcontrolcorrespondientealbotndevalidaciny,enla
propiedadCancelButton,elnombredelcontrolutilizadoparalaanulacin.

b.ElcontrolMenuStrip

Lamayoradelasaplicacionesdisponendeunabarrademens.Atravsdeestosmens,elusuariopodractivar
las diferentes funcionalidades de la aplicacin. Los mens se componen de elementos de men que permiten
lanzar acciones en la aplicacin o mostrar submens. En este caso, un pequeo tringulo al lado del ttulo del
meninformaalusuariodelapresenciadeunsubmen.Losmenspuedenservirigualmenteparaactivarono
unaopcin.Enestecaso,semuestradelantedelttulodelmenunpequeosignoparamarcarlaactivacindela
opcin. Para los aficionados al teclado, tambin es posible asociar a un men una combinacin de teclas que
equivalgaaunclicenelmen.

Lasiguientefigurapresentatodasestasnociones.

Veamosahoracmoponertodoestoenprctica.LoprimeroesinsertaruncontrolMenuStripenlaventana.Este
controlseubicaendoslugareseneldiseador:

l Enlazonareservadaparaloscontrolesinvisibles.

l Directamenteenlaventana,enellugardeunabarrademensestndar.

A partir de este lugar, podr componer el men. El diseador de men le propone las diferentes zonas en las
cualesleserposibleintroducirlosdatosqueconstituyenelmen.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 21 -
Aspodrcomponertotalmentelabarrademenymostrarsuaspectoamedidaquelavadiseando.

Cada vez que inserte un elemento, el diseador crea una nueva instancia de la clase ToolStripMenuItem y la
insertaenlacoleccinItems,paralosttulosdemens,yenlacoleccinDropDownItems,paraloselementosde
menydesubmen.

Elmencontextual,quesepuedeverhaciendoclicconelbotnsecundariodelratn,permiteagregarunabarra
deseparacin.

Quedaporconfigurarlaspropiedadesdecadaunodeloselementosdemen.

Vamosaverlaspropiedadesmsinteresantes:

Text

- 22 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Contieneelttulodelmen.

Visible

Permiteenmascararunelementodemen.

Enabled

Permiteprohibirlautilizacindelelemento.Entoncesapareceengrisenelmen.

Checked

Indicasielelementodemenestmarcadoono.

CheckOnClick

Permitecambiarautomticamenteelestadodelmenacadaclic.ElvalordelapropiedadChecked,en
estecaso,seinvierteconcadaclicenelmen.

ShortcutKeys

Definelacombinacindeteclasequivalenteaunclicenelmen.

Estapropiedadsemodificafcilmentedesdelaventanadepropiedades:

LapropiedadShowShortCutKeysautorizalavisualizacindelaccesodirectodetecladoalladodelttulodelmen.

Estas propiedades tambin se pueden modificar con el cdigo. Por ejemplo, si una barra de herramientas est
disponible,lasaccionesrealizadasconelladebenactuar,porsupuesto,enelestadodelmencorrespondientey
alcontrario.

Private Sub btnNegrita_Click(ByVal sender As System.Object, ByVal e As System.


EventArgs) Handles btnNegrita.Click
MnuNegrita.Checked = btnNegrita.Checked
End Sub
Private Sub btnCursiva_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles btnCursiva.Click
MnuCursiva.Checked = btnCursiva.Checked
End Sub

Private Sub btnSubrayado_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles btnSubrayado.Click
MnuSubrayado.Checked = btnSubrayado.Checked
End Sub

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 23 -
Private Sub MnuNegrita_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles MnuNegrita.Click
btnNegrita.Checked = MnuNegrita.Checked
End Sub

Private Sub MnuCursiva_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MnuCursiva.Click
btnCursiva.Checked = MnuCursiva.Checked
End Sub

Private Sub MnuSubrayado_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MnuSubrayado.Click
btnSubrayado.Checked = MnuSubrayado.Checked
End Sub

Enalgunoscasos,esnecesarioagregarelementosdinmicamenteduranteelfuncionamientodelaaplicacinpara
aadir,porejemplo,lalistadelosltimosarchivosutilizadosenlaaplicacin.

LasolucinconsisteenagregaralacoleccinDropDownItemsunnuevoelemento,utilizandoelmtodoAdd.

Mnuarchivo.DropDownItems.Add("prueba.txt")

Esta operacin agrega efectivamente un elemento al men, pero no nos ser de gran utilidad! De hecho, es
imposiblerecuperarloseventosClickenestemen.

Para resolver este problema, debemos utilizar una sintaxis distinta del mtodoAdd, que nos permita asociar un
gestordeeventosalnuevoelementoagregado.

Primerohayquecrearelprocedimientoqueseutilizarparalagestindeesteevento:

Private Sub archivosRecientes_Click(ByVal sender As System.Object,


ByVal e As System.EventArgs)

End Sub

Luego, en el momento de agregar el elemento de men, debemos indicar que nuestro procedimiento ser
responsabledelagestindeloseventosClickenelmen.

Mnuarchivo.DropDownItems.Add("prueba.txt", Nothing,
New System.EventHandler
(AddressOf archivosRecientes_Click))

c.ElmenContextMenuStrip

El men contextual permite asociar a los diferentes controles de la interfaz de la aplicacin un men que se
mostrar al hacer clic con el botn secundario del ratn en el control. Primero se deben disear los mens
aadiendosobrelahojacontrolesContextMenuStrip.

- 24 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Este control aparece en la barra de mens de la aplicacin, para que pueda elegir los distintos elementos del
men.Unmencontextualnollevattulo,sinoquepermitesimplementeelegirelementosdemenydesubmen.
Despus hay que asociar a cada control el men contextual correspondiente, a travs de la propiedad
ContextMenuStrip.

Elmensevisualizarautomticamentecuandoelusuariohagaclicconelbotnsecundariodelratnenelcontrol
correspondiente.

d.ElcontrolToolStrip

ElcontrolToolStripytodaslasclasesasociadasseutilizanparalacreacindelasbarrasdeherramientas.Este
control sirve en realidad de contenedor para los elementos que constituyen una barra de herramientas. Estos
elementosseagreganalcontrol ToolStripmedianteelmenquesemuestraalhacerclicenlapequeaflecha
presentealaizquierdaenelcontrol.

EstasolucinpermitecrearunabarradeherramientasdelaAalaZagregandotodosloselementosunoauno.
En muchas aplicaciones, las barras de herramientas incluyen un conjunto de botones estndar. Con objeto de
facilitarnos la tarea, el control ToolStrip contiene un asistente para generar automticamente una barra de
herramientas con todas las funcionalidades bsicas de una aplicacin. Para ello, debe hacer clic en la pequea
flecha presente a la derecha del control y elegir la opcin Agregar elementos estndares. La barra de
herramientasadoptaentonceslaaparienciasiguiente.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 25 -
Automticamente se aaden los botones clsicos a la barra de herramientas. La magia del asistente acaba
aqu, ya que por supuesto no hay cdigo generado automticamente para reaccionar a los clics en estos
diferentesbotones.Deber,porlotanto,escribirlocomohahechoparaelrestodeloscontrolesdelainterfazde
laaplicacin.

e.ElcontrolToolStripContainer

El propsito de este control es facilitar la creacin de una ventana que contiene varias barras de herramientas.
Este control est ubicado generalmente en una ventana con la propiedad Dock en Fill para ocupar toda la
superficiedisponibledelaventana.

Dispone de un contenedor en cada uno de sus bordes para acoger las diferentes barras de herramientas. Por
defecto,estoscontenedoresnosonvisiblesy,porlotanto,hayqueactivarlosantesdepoderagregarelementos.
Paraello,deberhacerclicenlaspequeasflechaspresentesenlosbordesdelcontrol.

Unooms ToolStrippuedenubicarseenlanuevazonaquesehaactivado.Cuidado,lasdiferenteszonassolo
puedencontenercontrolesToolStrip.Lazonacentral,encambio,puedecontenercualquiercontrol.

LaventajadelautilizacindelcontrolToolStripContainerresideenlaposibilidaddemodificarladisposicindelas
barrasdeherramientasdurantelaejecucindelaaplicacin.Paradesplazarlabarradeherramientas,elusuario
debehacerclicenlostrespuntosquesemuestranymoverlahastaunodelosbordesdelaventana.Labarrade
herramientasseanclaenelbordecorrespondiente.

- 26 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
5.Controlesdeseleccin

a.ElcontrolCheckBox

SeutilizaelcontrolCheckBoxparaproponeralusuariovariasopcionesentrelasquepodrelegirunaovarias.El
control CheckBox suele poder tomar dos estados: marcado cuando la opcin est seleccionada, o no marcado
cuando la opcin no est seleccionada. Una tercera posibilidad corresponde a un estado indeterminado de la
casilla. En este caso, aparece en gris. El estado de la casilla se puede verificar o modificar con la propiedad
Checked.EstapropiedadproporcionaunBooleanoquereflejaelestadodelacasilla.Silacasillaestconfigurada
para funcionar con tres estados posibles, al poner la propiedad ThreeState en True, la propiedad CheckState
indicaelestadodelacasillaatravsdeunodelosvaloresdefinidosenlaenumeracin.

Como para los otros controles, la propiedad TextAlign permite modificar la posicin del texto en el control. La
propiedadCheckAlign,quesigueelmismoprincipio,permitemodificarlaposicindelacasillaconrespectoaltexto.

Pordefecto,elmismocontrolCheckBoxgestionalavisualizacindelacasillaylamodificacindelaspropiedades
Checked yCheckState en funcin de las acciones del usuario. Puede asumir la responsabilidad de la gestin del
estadodelacasillamodificandolapropiedadAutoCheckaFalse.Enestecaso,debergestionareleventoClicky
modificarconelcdigo,enlagestindeesteevento,lapropiedadCheckedolapropiedadCheckState.

ElsiguientecdigopermitemodificarlascaractersticasdelafuentedeletradeuncontrolTextBox.

Enesteejemplo,trabajaremosconeleventoCheckedChangeddelcontrolCheckBox,quenosindicacualquiercambio

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 27 -
enelestadodelacasilla.

Private Sub chkNegrita_CheckedChanged(ByVal sender As System.Object, ByVal


e As System.EventArgs) Handles chkNegrita.CheckedChanged
Dim style As Integer
style = TxtEjemplo.Font.Style
If chkNegrita.Checked Then
style = style Or FontStyle.Bold
Else
style = style And Not FontStyle.Bold
End If
TxtEjemplo.Font = New Font(TxtEjemplo.Font, style)
End Sub

Private Sub chkCursiva_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles chkCursiva.CheckedChanged
Dim style As Integer
style = TxtEjemplo.Font.Style
If chkCursiva.Checked Then
style = style Or FontStyle.Italic
Else
style = style And Not FontStyle.Italic
End If
TxtEjemplo.Font = New Font(TxtEjemplo.Font, style)
End Sub

Private Sub chkSubrayado_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles chkSubrayado.CheckedChanged
Dim style As Integer
style = TxtEjemplo.Font.Style
If chkSubrayado.Checked Then
style = style Or FontStyle.Underline
Else
style = style And Not FontStyle.Underline
End If
TxtEjemplo.Font = New Font(TxtEjemplo.Font, style)

- 28 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Sub

b.ElcontrolRadioButton

ElcontrolRadioButtonpermiteproponeralusuariodistintasopcionesentrelasquenopodrseleccionarmsde
una. Como su nombre indica, este control funciona como los botones que permiten seleccionar una estacin de
radio(nosepuedenescuchartresemisorasderadioalavez!).Laspropiedadessonestrictamenteidnticasalas
queestndisponiblesenelcontrolCheckBox,menoslapropiedadCheckState,porqueestecontrolnopuedetener
msdedosestadosyessuficienteunBooleanopararepresentarelestadodelcontrol.

Completemosnuestroejemploaadiendoopcionesparalaalineacindeltexto:

Private Sub optIzda_CheckedChanged(ByVal sender As System.Object,


By Val e As System.EventArgs) Handles optIzda.CheckedChanged
If optIzda.Checked Then
TxtEjemplo.TextAlign = HorizontalAlignment.Left
End If
End Sub

Private Sub optDecha_CheckedChanged(ByVal sender As System.Object,


By Val e As System.EventArgs) Handles optDecha.CheckedChanged
If optDecha.Checked Then
TxtEjemplo.TextAlign = HorizontalAlignment.Right
End If
End Sub

Private Sub optCentro_CheckedChanged(ByVal sender As System.Object,


By Val e As System.EventArgs) Handles optCentro.CheckedChanged
If optCentro.Checked Then
TxtEjemplo.TextAlign = HorizontalAlignment.Center
End If

CuandolainterfazdesuaplicacincontienecontrolesRadioButton,convienequesiemprehayaunoseleccionado
enlavisualizacindelformulario(correspondientealaopcinpordefecto).

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 29 -
Completemosnuestraaplicacinaadiendolaeleccindelcolordeltexto:

Private Sub optNegro_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles optNegro.CheckedChanged
TxtEjemplo.ForeColor = System.Drawing.Color.Black
End Sub
Private Sub optVerde_CheckedChanged(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles optVerde.CheckedChanged
TxtEjemplo.ForeColor = System.Drawing.Color.Green
End Sub

Private Sub optRojo_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles optAzul.CheckedChanged
TxtEjemplo.ForeColor = System.Drawing.Color.Red
End Sub

Tenemos algn problema en el funcionamiento de nuestra aplicacin, ya que es imposible elegir una opcin de
alineamiento y una opcin de color simultneamente. Los controles RadioButton estn diseados para que no
pueda haber dos seleccionados a la vez en un mismo contenedor. Por lo tanto, la solucin a nuestro problema
pasa por el uso de un contenedor para aislar unos controles de otros. Es lo que veremos con los controles
GroupBoxyPanel.

c.ElcontrolListBox

El controlListBox propone al usuario una lista de opciones en la que podr seleccionar una o varias. El control
gestiona automticamente la visualizacin de los elementos con, en su caso, la insercin de una barra de
desplazamiento en el control. Los elementos mostrados en la lista se pueden elegir durante la creacin, en la
ventana de propiedades, o se pueden modificar con el cdigo. Los elementos de la lista suelen ser cadenas de
caracteres, pero pueden ser cualquier tipo de objeto. Por defecto, el control ListBox propone los elementos en
formadelistaconundesplazamientovertical.

- 30 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LapropiedadMultiColumncolocadaenTruepermitetenerundesplazamientohorizontaldelalista.

En este caso, la propiedad ColumnWidth indica la anchura de cada una de las columnas. La propiedad
IntegralHeightevitatenerunelementodelalistasolovisibleparcialmente.

SiestapropiedadestenTrue,lalistacambiadetamaoparamostrarnicamenteelementoscompletos.

LoselementosdelalistasegestionanenformadecoleccingraciasalapropiedadItems.Porlotanto,podemos
agregarelementosalalistautilizandoelmtodoAdddelacoleccinypasandocomoparmetroelobjetoquese
hadeinsertarenlalista.Enlamayoradeloscasos,elobjetoinsertadoesunacadenadecaracteres,perose
puedeutilizarcualquierotroobjeto.Sinembargo,elobjetoagregadodebedisponerdeunmtodoToStringpara
permitirlavisualizacinporelcontrolListBox.

Public Class color


Public nombre As String
Public valor As System.Drawing.Color

Public Sub New(ByVal n As String, ByVal v As System.Drawing.Color)


nombre = n
valor = v
End Sub

Public Overrides Function toString() As String


Return nombre
End Function

End Class

...
...
LstColores.Items.Add(New color("rojo", System.Drawing.Color.Red))
LstColores.Items.Add(New color("verde", System.Drawing.Color.Green))

Loselementosseaadenalfinaldelalista,salvosilapropiedadSortedestenTrue,yaque,enestecaso,los
elementosdelalistaestnorganizadosporordencreciente.Elmtodo Insertaadeunelementoalalista,en
unaubicacinprecisa(elprimerelementodelalistaseencuentraenlaubicacincero).Parainsertarunelemento
ensegundaposicin,utilizaremoselsiguientecdigo:

LstColores.Items.Insert(1, New color("Amarillo",System.Drawing.


Color.Yellow))

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 31 -
LaeliminacindeunelementodelalistaseefectaconelmtodoRemoveAtpasandocomoparmetroelndicedel
elementoquedeseaeliminar.

LstColores.Items.RemoveAt(0)

TambinsepuedeefectuarunalimpiezacompletadelalistaconelmtodoClear.

LstColores.Items.Clear()

Dos mtodos son tiles si, en el momento de agregar elementos a la lista, queremos evitar los duplicados. El
mtodo FindString busca el primer elemento de la lista que empiece por la cadena de caracteres especificada.
Estafuncindevuelveelndicedelelementoquecorrespondealcriterio,oelvalor1sinoseencuentranada.Se
puedehacerlomismoconelmtodoFindStringExactpero,enestecaso,esnecesariaunaconcordanciaexacta
delascadenasdecaracteres.

Por defecto, las ListBox solo autorizan la seleccin de un elemento. La propiedad SelectionMode permite elegir
cuatromodosdeseleccin:

l El primero (None) puede ser frustrante para el usuario, ya que la ListBox ser completamente funcional, pero el
clicdelratnnoproducirningnefecto.

l La opcinOneeselvalorpordefecto,dondecadaclicdelratnseleccionaelelementoydeseleccionaelelemento
anteriormenteseleccionadoenlalista.

l Con la opcin MultiSimple, cada clic en un elemento invierte su estado. Puede haber varios elementos
seleccionadosalmismotiempo.

l La ltima opcin, MultiExtended, tambin permite seleccionar varios elementos, pero ofrece la posibilidad de
seleccionarvarioselementossucesivosrpidamente.Seleccionandoelprimero,utilizandolatecla[Shift]yhaciendo
clicenelltimo,todosloselementospresentesentrelosdostambinquedanseleccionados.

Por supuesto, hay que recuperar en el cdigo la seleccin o las selecciones del usuario. En el caso de una
seleccin simple, la propiedad SelectedIndex indica el ndice, en la coleccin Items, del elemento seleccionado,
mientrasquelapropiedadSelected Itemfacilitaunareferenciahaciaelobjetoseleccionadoenlalista.

Paralasseleccionesmltiples,elprincipiodefuncionamientoeselmismo,perolosdatossedevuelvenenformade
coleccin. La coleccin SelectedIndices nos propone la lista de los ndices de los elementos seleccionados,
mientrasquelacoleccinSelectedItemsnosdalalistadelosobjetosseleccionados.Enlosdoscasos,hayque
recorrerlalistaparaextraerloselementos.

Dim o As Object
For Each o In ListBox1.SelectedItems
System.Console.WriteLine(o)
Next

- 32 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
El hecho de almacenar objetos en la coleccin Items nos permite tener acceso, a travs de la propiedad
SelectedItem, a todas las propiedades del objeto. De esta manera podemos, por ejemplo, utilizar la propiedad
valor,enelcasodequehayamosutilizadoobjetosdecolor.

En el siguiente ejemplo, modificamos el color de fondo de la hoja en funcin de la seleccin en la ListBox.Para


ello,gestionamoseleventoSelectedIndexChangedqueseproduceconcadanuevaseleccindelusuario.

Private Sub LstColor_SelectedIndexChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles ListBox2.SelectedIndexChanged
Me.BackColor = ListBox2.SelectedItem.valor
End Sub

d.ElcontrolNumericUpDown

El control NumericUpDown es la asociacin de una zona de texto y de dos botones. Los botones sirven para
incrementar o disminuir el valor visualizado en la zona de texto. Este control es muy sencillo. El valor que se
encargadegestionarsealmacenaenlapropiedadValue.Puedeevolucionarentredosextremosrepresentados
por las propiedades Minimum y Maximum. El incremento est definido por la propiedad Increment. Todos estos
valores pueden ser valores decimales. El formato de visualizacin puede ser modificado por la propiedad
DecimalsPlaces,quepermiteespecificarlacantidaddedecimalesquesevanamostrar.Estapropiedadinterviene
nicamente a nivel de visualizacin y no cambia el valor de la propiedad Value. Veamos como ejemplo una
pequeaporcindecdigoquesimulaelfuncionamientodeuntermostatodecalefaccin.Latemperaturadesu
oficinanocambiarconestaaplicacin,peroselcolordefondodelaventana,quepasardelazul,fro,alrojo,
calor.

Private Sub NumericUpDown1_ValueChanged(ByVal sender As Object, ByVal e


As System.EventArgs) Handles Termostato.ValueChanged
Me.BackColor = Color.FromArgb(25 * (Termostato.Value
- 15), 0, 25 * (25 - Termostato.Value))
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)


Handles Me.Load
Me.Termostato.DecimalPlaces = 1
Me.Termostato.Increment = 0.1
Me.Termostato.Maximum = 25
Me.Termostato.Minimum = 15
Me.Termostato.Value = 15
End Sub

e.ElcontrolTrackBar

Este control propone un aspecto ms visual del control NumericUpDown a la vez que facilita las mismas
funcionalidades.Sepresentaenformadeunpotencimetroenelquesepuededesplazaruncursorparaajustar
unvalornumrico.AdiferenciadelcontrolNumericUpDown,elvalornosemuestraysolopuedecontenernmeros
enteros.LosdosvaloresextremossondefinidosporlaspropiedadesMinimumyMaximum.

TambinestndisponiblesdospasosdeincrementoconlaspropiedadesSmallChangeyLargeChange.Lapropiedad
SmallChange se utiliza para incrementar o disminuir el valor con el uso de las flechas de desplazamiento del

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 33 -
teclado. La propiedad LargeChange se utiliza tras pulsar las teclas de pgina siguiente y pgina anterior. Si el
cursordelpotencimetroesdesplazadoconelratn,lapropiedadValuecorrespondealaubicacindelcursor.En
estecaso,noseutilizaningunodelosdospasosdeincremento.Parafacilitarelajustedeunvalor,seagregan
unospuntosdereferenciaalpotencimetro.Ladistanciaentreesospuntosvienedeterminadaporlapropiedad
TickFrequency.

f.ElcontrolDomainUpDown

EstecontroltieneprcticamenteelmismofuncionamientoqueelcontrolListbox.Sepresentacomounazonade
texto a la que se han asociado dos botones que permiten el desplazamiento por una lista de elementos. La
principal propiedad de este control es Items, que contiene los elementos propuestos en la lista. Las nicas
diferenciasconelcontrolListboxsonlaseleccinmltiple,queesimposibleparaestecontrol,ylapropiedadWrap,
quepermitelanavegacincircularporlalista.

g.ElcontrolCheckedListBox

EstecontrolesunamejoradelcontrolListBoxyportantofuncionaprcticamentedelamismamanera.Elnico
lmite respecto al control ListBox es que no acepta las selecciones mltiples. La evolucin respecto al control
ListBoxresideenlascasillaspresentesdelantedeloselementosdelalista.Sepuedemarcarestascasillasde
maneraindependientedelaseleccindeloselementos.Larecuperacindelascasillasmarcadasesposiblepor
mediodelapropiedadCheckedItems.Estacoleccincontienetodosloselementosmarcadosdelalista.

For Each elt In CheckedListBox1.CheckedItems


Console.WriteLine(elt.ToString)
Next

Otrasolucinparaobtenerloselementosmarcadosdelalistaconsisteenrecorrerlayenprobarconelmtodo
GetItemCheckedsilacasillacorrespondienteestmarcada.

For i = 0 To CheckedListBox1.Items.Count - 1
If CheckedListBox1.GetItemChecked(i) Then
Console.WriteLine(CheckedListBox1.Items(i))
End If
Next

Lapropiedad CheckOnClickdeterminasilaactivacinodesactivacindelacasilladeverificacinserealizaenel
primerclicdeunelementodelalista(true)osiesnecesarioundobleclicparacambiarelestadodelacasillade
verificacin(false).

h.ElcontrolComboBox

El control ComboBox es la asociacin de un control ListBox y de un control TextBox. Segn la modificacin del
control,elusuariopodrelegirunelementoenlalistaointroducirtexto.

LapropiedadDropDownStyleindicaelmododefuncionamientodelaComboBox.

- 34 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Simple

Elusuarioseleccionaunelementoenlalistaointroducetextoenlazonadetexto.Lalistase
visualizademanerapermanente.

DropDown

Configuracinidntica,perolalistasolosemuestraapeticindelusuario.

DropDownList

Elusuarioyanopuedeintroducirdatosenlazonadetexto:solopuedeelegirunelementodela
lista,despusdehaberpedidosuvisualizacin.

El estado de la visualizacin de la lista est controlado por la propiedad DroppedDown. Por ejemplo, se puede
escribircdigoparaquelalistaseabraencuantoelcontrolrecibeelfoco.

Private Sub ComboBox1_GotFocus(ByVal sender As Object, ByVal e


As System.EventArgs) Handles ComboBox1.GotFocus
ComboBox1.DroppedDown = True
End Sub

Noesposiblerealizarseleccionesmltiplesconelcontrol ComboBox.Eltextosepuederecuperarenlapropiedad
Text.Estapropiedadseactualizaaunqueelusuariohayaseleccionadounelementoenlalista.Enestecaso,la
propiedadSelectedIndexesigualalndicedelelementoseleccionado.Sielusuariohaelegidotextodirectamente,
estapropiedadesiguala1.

i.ElcontrolTreeView

ElcontrolTreeViewpermitelapresentacindedatosenformaderbol,idnticoalapresentacindelosarchivosy
de las carpetas en el explorador de Windows. Cada elemento se representa en forma de nodo que puede
contener nodos hijos. Cada elemento se puede mostrar en forma desarrollada o reducida por medio del signo
(ms(+)omenos())quesevisualizadelantedecadanodo.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 35 -
La propiedad Nodes contiene la lista de todos los nodos de primer nivel del rbol. Cada uno de ellos dispone
tambin de una propiedadNodes, que almacena a su vez la lista de todos sus nodos hijos y as sucesivamente
hastaelltimoniveldelrbol.EstaspropiedadesNodessepuedenmodificarenelmomentodelacreacin,conun
editorespecficoaccesibleenlaventanadepropiedades.

El botn Agregar raz aade un elemento raz a la propiedad Nodes del control TreeView. Para cada elemento,
convieneindicareltextoconlapropiedadText,laimagenmostradaenelnodoconlapropiedadImageIndexyla
imagenmostradacuandoelnodoestseleccionadoenelrbolconlapropiedadSelectedImageIndex.

Estas imgenes se extraen del control ImageList que usted ya habr asociado a la propiedad Imagelist del
control. Obviamente, se debe crear y llenar el controlImageList antes de modificar las propiedades del control
TreeView.

Por lo tanto, cada nodo posee una imagen para su visualizacin normal, y una imagen para su visualizacin

- 36 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
cuandoestseleccionado.Elvalor(Default)paraestasdosimgenesindicaqueelnodonoutilizarunaimagen
especfica,sinolasimgenespordefectoqueseindicanenlaspropiedadesImageIndexySelectedImageIndexdel
controlTreeView.Deestamanera,podrutilizarimgenesidnticasparatodoslosnodos.Sololosquetienenuna
visualizacinparticularnecesitarnlamodificacindelosvalorespordefecto.

Agregarunnodoalrbolconelcdigoesunpocomscomplicado.Hayquecrearunnuevonodoinstanciandola
claseTreeNodeeindicandoenlallamadadelconstructordelaclaselaleyendamostradaenelnodo.Laimageny
laimagendeseleccintambinsedebenprecisarsinoquiereutilizarlosvalorespordefecto.Lacreacindeun
nodopuedehacersedelasdosformassiguientes:

Dim nodo As TreeNode


nodo = New TreeNode("Twingo")

Dim nodo As TreeNode


nodo = New TreeNode("Twingo ", 2, 3)

indicando,enestecaso,elndicedelaimagenparalavisualizacinnormal,seguidodelndiceparalavisualizacin
cuandoelnodoestseleccionado.

LuegohayquearraigarestenuevonodoaunaramadenuestrorbolutilizandoelmtodoAdddelnodoqueva
aserelpadredelrecinllegado.

As,paraaadirunhijoalasegundarazdelrbol,utilizaremoselsiguientecdigo:

TreeView1.Nodes(1).Nodes.Add(nodo)

Tambinsepuedeeliminarunnodoconelcdigoutilizandoelmtodo RemoveAtdelacoleccincorrespondiente.
Porejemplo,paraelimimarelPeugeot207,utilizaremoselsiguientecdigo:

TreeView1.Nodes(0). Nodes.RemoveAt(0)

CuandosetrabajaconelcontrolTreeView,senecesitasaberamenudoenquelementodelcontrolhahechoclic
elusuario(paravisualizarlascaractersticasdelvehculoennuestrocaso).

EneleventoAfterSelect del controlTreeView,estdisponible,atravsdelparmetro e,unareferenciaalnodo


enelqueelusuariohahechoclic.LapropiedadTextdeesteelementonospermiteentoncesidentificarelnododel
controlTreeViewyreaccionarenconsecuencia.

Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e


As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
Select Case e.Node.Text
Case "Peugeot"
System.Console.WriteLine("Peugeot")
Case "Renault"
System.Console.WriteLine("Renault")
Case "Opel"

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 37 -
System.Console.WriteLine("Opel")
End Select
End Sub

j.ElcontrolListView

Estecontrolofrecelaposibilidaddepresentardatosalusuariodecuatromanerasdistintas,talycomolopermite
lafichaderechaenelexploradordeWindows.

Como para el control TreeView, este control dispone de una coleccin Items que almacena la informacin que
desea visualizar. Desde la ventana de propiedades de VB, se puede acceder a un editor especfico que permite
rellenarestacoleccin.

- 38 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Esteeditorpermiteagregaroeliminarelementosenlavisualizacindelcontroly,paracadaunodeellos,modificar
laleyendaporlapropiedadTextylaimagenasociadaporlapropiedadImageIndex.LapropiedadSubItemsesuna
coleccinqueseutilizadurantelavisualizacindetallada.Estacoleccincontienelosdatosquesemuestranen
cadaunadelascolumnasdelmododetallado.

LascolumnassecreanconlapropiedadColumnsdelcontrol.Hayuneditorespecficodisponibleparalagestinde
lascolumnas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 39 -
La propiedad Text corresponde al ttulo de las columnas. Cada columna est asociada a los elementos que se
habrnelegidoenlapropiedadSubItems.Resumamostodoelloconlapresentacindenuestrosvehculosydesus
caractersticas.

Para cada vehculo que deseamos mostrar, hay que insertar un elemento en la coleccin Items del control
ListView.Paracadaunodeestoselementos,lapropiedadSubItemsdebecontenerlainformacinutilizadaparala
visualizacinenmodalidaddetallada(eltipodevehculo,suprecioysupotencia).

DespushayqueagregartrescolumnasalapropiedadColumnsdelcontrolListView(tipo,precio,potencia).

Para terminar la configuracin, las propiedades LargeImageList y SmallImageList indican respectivamente los
controlesImageList,dondeserecuperarnlasimgenesparalavisualizacinenlamodalidadIconosgrandeso
Iconospequeos.

EltipodepresentacindelavisualizacinsepuedemodificarconlapropiedadView:

Private Sub optGrande_CheckedChanged(ByVal sender As System.Object, ByVal


e As System.EventArgs) Handles optGrande.CheckedChanged
ListView1.View = View.LargeIcon
End Sub

Private Sub optPequenio_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles optPequenio.CheckedChanged
ListView1.View = View.SmallIcon
End Sub

Private Sub optLista_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles optLista.CheckedChanged
ListView1.View = View.List
End Sub

Private Sub optDetalle_CheckedChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles optDetalle.CheckedChanged
ListView1.View = View.Details
End Sub

6.Loscontrolesdeagrupamiento

a.ElcontrolGroupBox

ElcontrolGroupBoxpermitelaagrupacinlgicayvisualdecontrolesenunformulario.Elcontrolposeeunbordey
unaleyendaqueapareceenelmargensuperior.Estecontrolfacilitatambinlaubicacindeloscontrolesenla
ventana,yaque,despusdehabercolocadoloscontrolesenelGroupBox,estossedesplazanenbloque.Tambin
permiteaislarlosRadioButtonscuandodebenfuncionardemaneraindependiente.

b.ElcontrolPanel

El control Panel dispone de las mismas funcionalidades que el control GroupBox. No dispone sin embargo de la
propiedad Text y no permite por tanto la visualizacin de una leyenda. En cambio, posee una propiedad
BorderStylequepermiteeliminarlavisualizacindelborde.Enestecaso,tenemoscontrolesqueestnagrupados

- 40 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
lgicamente sin indicacin visible de este agrupamiento. La propiedad AutoScroll del control permitir mostrar
automticamente barras de desplazamiento si su superficie no es suficiente para mostrar el conjunto de los
controlesqueseletransmiten.

En esos dos controles, la modificacin de la propiedadEnabled desactivar tambin el conjunto de los controles
quesecolocanensuinterior,sintenerquemodificarestapropiedadparacadacontrol.

c.ElcontrolTabControl

ElcontrolTabControlmuestravariaspestaassimilaresalosseparadoresdeunarchivador.Laprincipalutilizacin
deestecontroleslacreacindecuadrosdedilogoconvariaspestaas.

LapropiedadprincipalTabPagescontienelalistadetodaslaspginasasociadasalcontrol.Uneditorespecficonos
permitelamanipulacindeestaspginas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 41 -
Cadapestaaseconsideracomounapginaenlaquesepodrncolocarcontroles.Paracadapestaa,seofrecen
muchaspropiedadesyadisponiblesenlasventanas.

Lainsercindecontrolesserealizaseleccionandopreviamentelapestaadedestino,yacontinuacindibujando
los controles, del mismo modo que en una ventana clsica. Si su cuadro de dilogo contiene muchas pestaas,
puedeelegirmostrarlasendistintasfilas,modificandolapropiedadMultilinedelcontrol.

- 42 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Tambin es posible prohibir la utilizacin de todos los controles presentes en una pestaa, modificando la
propiedadEnableddelapestaa.Porejemplo,paraprohibirelusodelapestaaColor:

TabControl1.TabPages(1).Enabled = False

Comoparamuchosotroscontroles,unapropiedadImageListpermiteasociarimgenesdebitmapacadapestaa,
atravsdelapropiedadImageIndexdecadapestaa.

d.ElcontrolSplitContainer

Este control permite la creacin de la interfaz de usuario, comparable con el explorador de Windows. Separa la
ventanaendospartesconunabarrahorizontalovertical.Elusuariopuededesplazarestabarraparacambiarel
tamaodecadaunadelaszonasdelimitadas.SeasociaamenudoconuncontrolTreeViewensuparteizquierda
y un conjunto de controles en la parte derecha, permitiendo la modificacin del elemento seleccionado en el
TreeView. Esta presentacin se utiliza en la herramienta MMC (Microsoft Management Console), con la que se
puedenconfigurarmuchosparmetrosdefuncionamento.Cadapartedelcontrolsepuedeusarcomocontenedor
paraotroscontroles.

La propiedad Orientation indica el sentido en el que se corta la superficie del control. El dimensionamiento de
cadazonasepuedeprohibirconlapropiedadIs SplitterFixedenTrue.Tambinesposibleprohibirelcambiode

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 43 -
tamaodeunasolazonaconlapropiedadFixedPanel.Enestecaso,silasdimensionesdelcontenedordelcontrol
(la ventana) se modifican, cambian las dimensiones de una sola zona. La propiedadOrientation determina, por
supuesto,elsentidodelaseparacindelcontrol.

e.ElcontrolFlowLayoutPanel

ElcontrolFlowLayoutPanelorganizaautomticamentelaubicacindeloscontrolesqueseleasignan.Enfuncin
delvalordelapropiedadFlowDirection,loscontrolessedispondrn:

l Deizquierdaaderecha.

l Dederechaaizquierda.

l Dearribahaciaabajo.

l Deabajohaciaarriba.

Sielespaciodisponiblenoessuficienteparaagregaruncontroladicional,lapropiedadWrapContentsindicasise
haaadidounanuevacolumnaolnea,enfuncindelaorientacinenlaqueelcontrolFlowLayoutPaneltrabajao
siloscontrolesadicionalesestntruncados.

f.ElcontrolTableLayoutPanel

Avecesesimportantequeunformularioconserveunaspectocorrectocuandoselecambianlasdimensiones.La
primera solucin que nos viene en mente consiste en administrar uno de los eventos que aparecen cuando se
redimensionalaventana,Resize,Layoutporejemplo,ymodificarlasposicionesydimensionesdeloscontrolesen
consecuencia. Esta solucin es muy pesada de aplicar y se debe repetir para cada formulario. La otra solucin,
mseficaz,consisteenpediraungestordeubicacinquegestioneeltamaoylaposicindeloscontrolesquese
leconfan.ElcontrolTableLayoutPanelestespecializadoenestetrabajo.Estecontenedororganizasucontenido
enformadecuadrcula,unpococomounamatrizenlenguajeHTML.

Primerohayquecolocarenelformulariouncontrol TableLayoutPanel.Pordefecto,elcontrolsegeneracondos
lneasydoscolumnas.Paramodificarestadisposicin,solohacefaltaactivarlasopcionesdelcontrolhaciendoclic
enlapequeaflechasituadaenlaesquinasuperiorderechayluegoutilizandolaopcincorrespondiente.

- 44 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Unavezcreadas,sepuedemodificarcadalneaycadacolumnaeligiendolaopcinEditarfilasycolumnas.

Luegosepuedencolocarloscontrolesencadaunadelascasillas.Solopuedehaberuncontrolporcasilla.

Elprincipalintersdeestecontrolseencuentraeneldimensionamientodelformulario,yaqueloscontrolessiguen
automticamente las modificaciones de tamao del formulario. Para ello, el control TableLayoutPanel debe estar
ancladoenlosbordesizquierdoyderechodelformulario.

OcurrelomismoparatodosloscontrolescolocadosenelTableLayoutPanel.

Trascambiareltamaodelaventana,conservaremosunaspectocorrectodelformulario.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 45 -
Para entender el inters del controlTableLayoutPanel, intente la siguiente manipulacin: aada un formulario y
luego copie y pegue dos zonas de texto y dos botones en este formulario. Ejecute la aplicacin y modifique el
tamaodelformulario.Elresultadodemuestralautilidaddeestecontrol.

7.Loscontrolesgrficos

a.ElcontrolPictureBox

ElcontrolPictureBoxseutilizaparamostrarimgenesenunaaplicacin.Estecontrolaceptavariosformatosde
archivos:

l LosarchivosBitmap(*.bmp)

l LosarchivosIconos(*.ico)

l LosarchivosGif(*.gif)

l Losmetarchivos(*.wmf)

l LosarchivosJPEG(*.jpg)

El contenido del control se especifica en la propiedad Picture. En la ventana de propiedades, puede buscar el
archivoquedeseacargarenelcontrolgraciasalsiguientecuadrodedilogo.

- 46 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ElbotnBorrarpermitereiniciarlapropiedadparaeliminarunarchivoyapresente.

Paramodificarlaimagenvisualizadamedianteelcdigo,debemoscargarelcontenidodelarchivoyasignarloala
propiedad Picture, que espera una instancia de la claseImage. Para crear esta instancia, utilizamos el mtodo
estticoFromFiledelaclaseImage,quetomacomoparmetroelnombredelarchivoyquedevuelvelainstancia
delaclaseImagecreada.

PictureBox1.Image = Image.FromFile("foto.gif")

Paraborrarunaimagenconelcdigo,puedeutilizarelcdigosiguiente:

PictureBox1.Image = Nothing

AtravsdelapropiedadSizeMode,puedeelegir,dequmaneraadaptarnsustamaoselcontrolylaimagen:

Normal

Losdoselementosconservansusdimensiones.Seubicalaimagenenlaesquinasuperiorizquierda
delcontrol.

StretchImage

Laimagenseamplaparaocupartodalasuperficiedelcontrol.Enelcasodeimgenesno
vectoriales,elresultadopuedeseravecesdecepcionante.

AutoSize

Elcontrolseadaptaaltamaodelaimagen.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 47 -
CenterImage

Losdoselementosconservansusdimensiones,perolaimagensecentraenrelacinconelcontrol.

Zoom

Laimagenseamplaoreduceparaocupartodalaanchuraolaalturadelcontrol,peroseutilizala
mismaproporcinverticalyhorizontalmente.

b.ElcontrolImageList

Se utiliza el control ImageList en una aplicacin como almacn de imgenes. No proporciona ninguna
funcionalidadparalavisualizacindelasimgenes,peropermitesualmacenamientoenlaaplicacin.Sepueden
utilizarmuchostiposdearchivosenestecontrol(bmp,ico,gif,jpg...).Sinembargo,lasimgenesalmacenadasen
estecontrolnotienenporquserdelmismotipo.Sepuedenmezclar,porejemplo,archivosbmpyarchivosico.
Sinembargo,existeunalimitacin:noseadmitenlasimgenesprocedentesdeunmetarchivo(wmf).Estecontrol
notieneinterfazvisibleenelmomentodelaejecucinporlotanto,noseubicardirectamenteenlaventana,
sinoenunazonareservadaparaestetipodecontrolesenlainterfazdediseogrfico.

Este control se utilizar en combinacin con cualquier tipo de control que posea una propiedad ImageList,
SmallImageList o LargeImageList. Para estos controles, otra propiedad, normalmente la ImageIndex, indica la
imagen almacenada en el control ImageList que usted le quiere asociar. De este modo, puede cambiar
rpidamente la imagen mostrada en un botn, modificando la propiedad ImageIndex del botn, para seleccionar
unadelasimgenesdisponiblesenelcontrolImageList.

La propiedad Images es la propiedad principal del control ImageList. Se trata de una coleccin en la que se
almacenanlasimgenes.Cadaimagenesaccesibleatravsdesundiceenlacoleccin.

Estapropiedadsepuedemodificarenelmomentodelacreacindelaaplicacin,atravsdelaventanadeleditor
decoleccionesdeimgenesquesemuestracuandosemodificalapropiedadImagesdelcontrol.

- 48 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Utilizando este editor, se puede, en particular, agregar imgenes, quitar otras o modificar su ordenacin en la
coleccin.Sinembargo,nohayposibilidaddemodificarlaimagenunavezinsertadaenlacoleccin.Enestecaso,
hayquesuprimirlaeinsertarunanuevaconelcontenidodelarchivocorrespondiente.

LainsercindeunaimagentambinsepuedeefectuarpormediodelcdigoutilizandoelmtodoAdddisponibleen
lacoleccinImagesdelcontrol.

ImageList1.Images.Add(Image.FromFile("foto.bmp"))

De la misma manera, se puede eliminar, por medio del cdigo, una imagen ya presente en la lista utilizando el
mtodoRemoveAteindicandoelndicedelelementoquesedeseaeliminar.

ImageList1.Images.RemoveAt(6)

Elmtodo ClearpermitevaciarcompletamentelacoleccinImageseliminandoastodaslasimgenesdelcontrol
ImageList.

Para todas las imgenes de la lista, puede indicar a travs de la propiedad ColorDepth el nmero de colores
gestionadosporelcontrolImageList.LapropiedadImageSizeindicaeltamaodelasimgenes.Estetamaoser
idntico para todas las imgenes colocadas en el control. Las imgenes insertadas se ampliarn o reduciran,
segnelcaso,paraadaptarseaestetamao(losresultadospuedenllegaraserdecepcionantes).

8.Loscontrolesdegestindeltiempo

Hay dos controles disponibles para introducir fechas. El controlDateTimePicker permite la eleccin de una fecha,
mientrasqueelcontrolMonthCalendarpermitelaeleccindeunintervaloentredosfechas.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 49 -
a.ElcontrolDateTimePicker

Estecontrolasociaunazonadetextoyuncalendario.Lafechapodrintroducirsededosformas:directamenteen
lazonadetexto(conunaverificacindelosdatosintroducidos)o,muchomsfcilmente,pulsandoelbotnque
seencuentraalladodelazonadetextoparaabrirelcalendario(comoenuncomboBox).

La propiedad Value permite recuperar la fecha elegida o, al revs, especificar la fecha seleccionada en el
calendarioparasuvisualizacin.Pordefecto,elcalendarioseiniciaconlafechadelda.

b.ElcontrolMonthCalendar

EnrealidadestecontrolcorrespondealcalendarioasociadoalcontrolDateTimePickerconalgunasfuncionalidades
adicionales. Por ejemplo, se puede indicar una lista de fechas que aparecern en negrita en el calendario (por
ejemplo,losdasfestivos).LapropiedadAnnuallyBoldedDatescontienelalistadetodosestosdasespeciales.

- 50 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
La propiedad MonthlyBoldedDates permite indicar los das que aparecern en negrita cada mes (el da en que
debepagarunafactura,porejemplo!).

El inters principal de este control es que permite la seleccin de un intervalo de fechas. La propiedad
MaxSelectionCount indica el nmero mximo de das de la seleccin (por defecto, 7). Sin embargo, queda un
problema, ya que no existe una solucin sencilla para elegir un intervalo de fechas entre varios meses. Los
calendarios de los meses incluidos en la seleccin deben estar todos visibles, para permitir la seleccin de un
intervalo de fechas en distintos meses. La solucin consiste en configurar el control para que visualice varios
mesessimultneamente.LapropiedadCalendarDimensionsfijaelformatodelcalendario.

Por ejemplo, una aplicacin utilizada para gestionar un planing de vacaciones podra utilizar la siguiente
configuracin:

indica los das festivos para mostrarlos en negrita


Me.Planning.AnnuallyBoldedDates = New Date() {New Date(2013, 7, 14, 0, 0,
0, 0), New Date(2013, 8, 15, 0, 0, 0, 0)}
muestra tres meses a lo largo por un mes a lo ancho
Me.Planning.CalendarDimensions = New System.Drawing.Size(3, 1)
Me.Planning.Location = New System.Drawing.Point(40, 128)
limita las posibilidades de eleccin desde el 1 de junio al 31 de
agosto del 2013
Me.Planning.MinDate = New Date(2013, 6, 1, 0, 0, 0, 0)
Me.Planning.MaxDate = New Date(2013, 8, 31, 0, 0, 0, 0)
Autoriza la seleccin de como mximo 28 das (4 semanas de vacaciones)
Me.Planning.MaxSelectionCount = 28
Me.Planning.Name = "Planning"
Me.Planning.TabIndex = 6
Me.Planning.TodayDate = New Date(2013, 6, 4, 0, 0, 0, 0)

Luego, puede obtener el intervalo seleccionado utilizando la propiedad SelectionRange, que contiene una
propiedad Start y una propiedad End. El evento DateSelected se activa cuando uno de los extremos de la
seleccinsemodifica.Assepuedeutilizarparaactualizarunazonadetexto,comoenelsiguienteejemplo.

Private Sub Planning_DateSelected(ByVal sender As Object, ByVal e As


System.Windows.Forms.DateRangeEventArgs) Handles
Planning.DateSelected

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 51 -
TxtVacaciones.Text = "Tus vacaciones son del " & Planning.Selection
Range.Start & " al " & Planning.SelectionRange.End
End Sub

c.ElcontrolTimer

Estecontrolnosvaapermitiractivareventosaintervalosregularesenlaaplicacin.Esmuysencillo,porquesolo
poseedospropiedades.

Interval

Indicaelplazoentredoseventos.Esteplazoseexpresaenmilisegundos.

Enabled

Indicasielcontrolgeneraeventososiestinactivo.

Cadavezquesecumpleunintervalodetiempo,seactivauneventoTick.

Sinembargo,hayqueserprudentealutilizarestecontrolytenerencuentalassiguientesobservaciones:

l Si el sistema est muy cargado (porque efecta operaciones de entrada/salida de la red, por ejemplo), es posible
quenoselancenregularmenteloseventosTick.

l LaprecisindelcontrolTimernoesdignadeunrelojsuizo.Porejemplo,nosedebeincrementarunavariableenel
evento Tickconuncontrol Timerparamedirunperiododetiempoparaelloesmejorutilizarelrelojdelsistema
operativo,comoenelsiguienteejemplo:

Dim comienzo As Date

Private Sub Form16_Load(ByVal sender As Object, ByVal e As System. EventArgs)


Handles MyBase.Load
comienzo = Now
End Sub

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.


EventArgs) Handles Timer1.Tick
Dim duracion As Double
clculo de la duracin hora actual-hora de comienzo y conversin en das
duracin = DateDiff(DateInterval.Second, comienzo, Now) / (24 * 3600)
conversin del valor en fecha y formateo en minutos: segundos
lblDuracion.Text = Format(Date.FromOADate(duracion),"llevas trabajando
mm minutos ss segundos")
End Sub

d.ElcomponenteBackGroundWorker

A veces tenemos que efectuar operaciones relativamente largas en una aplicacin, como por ejemplo cargas de
imgenes o bsquedas en un disco duro. Estas operaciones provocan un bloqueo de la aplicacin durante su
ejecucin.Elusuariotienelasensacindequelaaplicacinyanorespondeypuedeestartentadodecerrarlade
maneraabrupta.Unasolucinposibleconsisteenfacilitaralusuarioinformacinsobreelavancedeltratamiento
con, por ejemplo, la visualizacin de una barra de progreso. Pero, incluso con esta solucin, el usuario est

- 52 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
obligado a esperar el final del tratamiento para poder seguir utilizando la aplicacin. El componente
BackGroundWorker soluciona este problema permitindole la ejecucin de operaciones de forma asincrnica en
segundoplano.Elcdigoseejecutasobreunthreaddiferentedelthreadprincipaldelaaplicacin,queseguir
administrandolainterfazdeesta.SolotienequeindicaralBackGroundWorkerelcdigoquedebeejecutaryluego
llamar su mtodo RunWorkerAsync. Al finalizar la ejecucin, le avisar lanzando el evento RunWorkerCompleted.
Vamos a probar esto realizando una aplicacin que calcula cuntos nmeros primos existen entre 0 y un valor
determinado.Enprimerlugar,veamoselcdigodeunafuncinquecompruebasiunnmeroesprimo.

Public Function esPrimo(ByVal num As Integer) As Boolean


If num < 2 Then
Return False
End If
If num = 2 Then
Return True
End If
If num Mod 2 = 0 Then
Return False
End If
Dim i As Integer
i = 3
Do While (i * i <= num)
If num Mod i = 0 Then
Return False
Else
i = i + 1
End If
Loop
Return True
End Function

Conrespectoaltiempodeclculonecesariopararealizarlaoperacin,estecdigoestlejosdesereficaz,pero
estenlalneadelobjetivoquebuscamos.Lasegundafuncincalculacuntosnmerosprimosexistenentrecero
yunvalorpasadocomoparmetro.

Public Function cuantosPrimos(ByVal max As Integer)


Dim i, num As Integer
For i = 0 To max
If esPrimo(i) Then
num = num + 1
End If
Next
Return num
End Function

LuegodebemoscolocarenelformulariouncontrolBackGroundWorker,dosTextBoxydosButton.Laprimerazona
detextoservirparaintroducirelvalormximodelclculo,lasegundaparalavisualizacindelresultado.Elprimer
botnlanzarelclculomedianteelBackGroundWorker,elsegundolanzardirectamenteelclculo.Paraverificarla
reactividaddelaaplicacin,aadimostambinuncontrolTextBoxmultilnea,porejemplo.

Escribimos ahora los gestores de eventos para los dos botones. El primero es sencillo, ya que invocaremos la
funcin cuantosPrimos pasndole el valor introducido en la zona de texto txtNumCalculo y visualizaremos el
resultado en la zona de texto txtResultado. Modificando las propiedades Enabled de los botones evitamos el

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 53 -
lanzamientodeunasegundatareadeclculodurantelaejecucindelaprimera.

Private Sub cmdNormal_Click(ByVal sender As System.Object, ByVal e


As System.EventArgs) Handles cmdNormal.Click

cmdNormal.Enabled = False
cmdBackGround.Enabled = False
txtResultado.Text = cuantosPrimos(txtNumCalculo.Text)
cmdNormal.Enabled = True
cmdBackGround.Enabled = True

End Sub

El cdigo del botnBackGround tambin es muy sencillo. La nica diferencia se encuentra en la invocacin de la
funcincuantosPrimos,querealizaindirectamenteelmtodoRunWorkerAsync.Elparmetropasadoaestemtodo
seenvaalafuncincuantosPrimos.

Private Sub cmdBackGround_click(ByVal sender As System.Object, ByVal e


As System.EventArgs) Handles cmdBackGround.Click

cmdBackGround.Enabled = False
cmdNormal.Enabled = False
txtResultado.Text = ""
bgw.RunWorkerAsync(txtNumCalculo.Text)

End Sub

Nos queda todava precisar dos cosas para que la aplicacin sea operacional. Debemos indicar al
BackGroundWorkerqucdigodebeejecutarcomotareadefondo.Paraello,hayquegestionarsueventoDoWork,
que se ejecuta en el thread asociado al BackGroundWorker. La informacin que hay que dar a la funcin
cuantosPrimosseobtienepormediodelapropiedadArgumentdelparmetro.

Private Sub bgw_DoWork(ByVal sender As Object, ByVal e


As System.ComponentModel.DoWorkEventArgs) Handles bgw.DoWork

e.Result = cuantosPrimos(e.Argument)

End Sub

ElresultadoserasignadoalapropiedadResult.ElBackGroundWorkernosavisadequehaterminadoeltrabajo
lanzandoeleventoRunWorkerCompleted.Enrespuestaaesteevento,debemosrecuperarelresultadomediantela
propiedadResultymostrarloenlazonadetextodelresultado.

Private Sub bgw_RunWorkerCompleted(ByVal sender As Object, ByVal e As


System.ComponentModel.RunWorkerCompletedEventArgs)
Handles bgw.RunWorker Completed

txtResultado.Text = e.Result
cmdBackGround.Enabled = True

- 54 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
cmdNormal.Enabled = True

End Sub

ExisteunatrampaqueconvieneevitarenlautilizacindelBackGroundWorker.ElcdigodeleventoDoWorknodebe
accederenabsolutoalosotroscontrolesdelformulario,yaquenosongestionadosporelmismoThread.

Siintentahacerlo,obtendrlasiguienteexcepcin.

Para probar el funcionamiento, debemos proporcionar un valor (aproximadamente 10.000.000) y luego lanzar el
clculopormediodeunodelosdosbotones.Mientrasseejecutaelclculo,puedeintentarutilizareltercercontrol
TextBox.EnelcasodeltratamientoporelBackGroundWorker,sepuedeutilizarestecontrolduranteelclculo.La
llamadadirectadelafuncincuantosPrimosbloquealainterfazdelaaplicacindurantesuejecucin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 55 -
Herenciadeformularios

Quiz necesite alguna vez que un proyecto invoque a un formulario similar a otro que ya ha creado para otro
proyecto. Tambin puede crear un formulario de base que contenga parmetros como un fondo esttico o una
presentacin particular de los controles que piensa utilizar varias veces en un proyecto. Cada nueva versin del
formulario contendr modificaciones respecto del modelo original. La herencia de formularios nos permite crear un
formulariobaseyheredardelparapersonalizarlasnuevasversionesascreadas.

Parapodercrearunformularioheredado,previamentenecesitamosdisearelformulariobase.Paraquelaherencia
de formularios est disponible, el proyecto que contiene el formulario base debe haber sido obligatoriamente
compilado. Para agregar un formulario heredado, utilizamos el cuadro de dilogo clsico de agregar nuevos
elementosalproyecto,seleccionandolaopcinFormularioheredado.

Acontinuacin,asigneunnombreasuformularioyhagaclicenelbotnAgregar.Semostrarelcuadrodedilogo
Seleccindeherenciay,sielproyectoactualyacontieneformularios,sevisualizarn.Paraheredardeunformulario
disponible en otro ensamblado, haga clic en el botn Examinar, seleccione el archivo (.exe o .dll) que contenga el
formulariobasedesueleccinyconfirmeconelbotnAceptar.Deestaforma,elnuevoformularioseragregadoa
suproyecto.Enesteformulario,loscontrolesprocedentesdelaherenciaestnmarcadosconelsmbolo .

LapropiedadModifiersdecadacontroldelformulariobasedeterminalasaccionesposiblesdeestosenelformulario
heredado.Seaplicanlasreglasestndardeherencia,queseresumenacontinuacin:

l Public: se puede cambiar el tamao de los controles y tambin desplazarlos. Los controles estn accesibles
internamenteporlaclasequelosdeclarayexternamenteporotrasclases.

l Protected: se puede cambiar el tamao de los controles y tambin desplazarlos. Los controles estn accesibles
internamenteporlaclasequelosdeclarayportodaslasclasesheredadasdelaclasepadre,perolasclasesexternas
nopuedenaccederaellos.

l Protected Friend: se puede cambiar el tamao de los controles y tambin desplazarlos. Los controles estn accesibles
internamenteporlaclasequelosdeclara,portodaslasclasesqueheredandelaclasepadreyporotrosmiembrosdel
ensambladoqueloscontiene.

l Friend:todoslosaspectosdelcontrolseconsideranaccesiblesdesololectura.Nosepuedendesplazar,nicambiarde
tamao,nimodificarsuspropiedades.Elcontrolestaccesiblenicamenteporotrosmiembrosdelensambladoquelo
contiene.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
l Private:todoslosaspectosdelcontrolseconsideranaccesiblesdesololectura.Nosepuedendesplazar,nicambiarde
tamao,nimodificarsuspropiedades.Elcontrolestsolamenteaccesibleporlaclasequelodeclara.

Porsupuesto,sepuedenagregarotroscontrolesalformularioheredadoparapersonalizarsuaspecto.Sisemodifica
el formulario base despus de su utilizacin en una relacin de herencia, las modificaciones se propagarn a los
formulariosheredadosdurantelacompilacindelformulariobase.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Principiodefuncionamientodeunabasededatos

Las bases de datos se han convertido en elementos ineludibles en la mayora de las aplicaciones. Sustituyen la
utilizacin de archivos gestionados por el propio desarrollador. Esta aportacin permite una mayor productividad
duranteeldesarrolloytambinmejorademanerasignificativalasprestacionesdelasaplicaciones.Tambinpermiten
a los usuarios compartir datos entre ellos. Para poder utilizar una base de datos, debe conocer un mnimo de
vocabulariorelacionadoconestatecnologa.

1.Terminologa

Enelcontextodelasbasesdedatos,amenudoseutilizanlossiguientestrminos:

Basededatosrelacional

Unabasededatosrelacionalesuntipodebasededatosqueutilizamatricesparaalmacenar
informacin.Utilizavaloresprocedentesdedosmatricesparaasociarlosdatosdeunatablaconlosde
laotra.Engeneral,enunabasededatosrelacional,losdatossealmacenarunasolavez.

Tabla

Unatablaesuncomponentedeunabasededatosquealmacenalosdatosenregistros(filas)y
campos(columnas).Losdatosseagrupan,engeneral,entablasenfuncindesucategora.Por
ejemplo,tenemoslatabladeClientes,deProductosodePedidos.

Registro

Elregistroeselconjuntodedatosrelativosaunelementodeunatabla.Anivellgico,losregistros
sonequivalentesalasfilasdeunatabla.Porejemplo,unregistrodelatablaClientescontienelas
caractersticasdeunclienteparticular.

Campo

Unregistrosecomponedevarioscampos.Cadacampodeunregistrocontieneunnicodatorelativo
alregistro.Porejemplo,unregistroClientepuedecontenerloscamposCodigoCliente,Apellido,
Nombre...

Claveprimaria

Seutilizaunaclaveprimariaparaidentificardemaneranicacadafiladeunatabla.Laclaveprimaria
esuncampoounacombinacindecamposcuyovaloresnicoenlatabla.Porejemplo,elcampo
CodigoClienteeslaclaveprimariadelatablaCliente.Nopuedehaberdosclientesconelmismo
cdigo.

Claveexterna

Unaclaveexternarepresentaunoovarioscamposdeunatablaquehacenreferenciaaloscamposde
laclaveprimariadeotratabla.Lasclavesexternasindicanlamaneraenqueserelacionanlas
matrices.

Relacin

Unarelacinesunaasociacinestablecidaentrecamposcomunesendosmatrices.Unarelacin

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
puedeserdeunoauno,deunoavariosodevariosavarios.Graciasalasrelaciones,losresultados
delasconsultaspuedencontenerdatosprocedentesdevariasmatrices.Unarelacindeunoavarios
entrelatablaClienteylatablaPedidopermitequeunaconsultadevuelvatodoslospedidos
correspondientesauncliente.

2.EllenguajeSQL

Antes de poder escribir una aplicacin en Visual Basic utilizando datos, debe conocer el lenguaje SQL (Structured
Query Language). Este lenguaje permite dialogar con la base de datos. Existen diferentes versiones del lenguaje
SQLsegnlabasededatosutilizada.Sinembargo,SQLtambindisponedeunasintaxiselemental,normalizada,
independientedecualquierbasededatos.

a.Bsquedadedatos

El lenguaje SQL permite especificar los registros que se han de extraer, as como el orden en el que desea
extraerlos.PuedecrearunainstruccinSQLqueextraeinformacindevariasmatricessimultneamente,ocrear
unainstruccinqueextraenicamenteunregistroespecfico.

SeutilizalainstruccinSELECTparadevolvercamposespecficosdeunaovariasmatricesdelabasededatos.

LasiguienteinstruccindevuelvelalistadelosapellidosynombresdetodoslosregistrosdelatablaCliente:

SELECT Apellido,Nombre FROM Cliente

Puedeutilizarelsmbolo*enlugardelalistadeloscamposcuyovalordesearecuperar:

SELECT * FROM Cliente

Puedelimitarelnmeroderegistrosseleccionadosutilizandounoovarioscamposparafiltrarelresultadodela
consulta.Haydiferentesclusulasdisponiblesparaejecutarestefiltro.

ClusulaWHERE

Estaclusulapermiteespecificarlalistadelascondicionesquedeberncumplirlosregistrosparaformarpartede
losresultadosdevueltos.ElsiguienteejemplopermiteencontrartodoslosclientesquevivenenBarcelona:

SELECT * FROM Cliente WHERE Ciudad=Barcelona

La sintaxis de esta clusula requiere la utilizacin de comillas simples para la delimitacin de las cadenas de
caracteres.

ClauseWHERE...IN

PuedeutilizarlaclusulaWHERE ... INparadevolvertodoslosregistrosquecumplenconunalistadecriterios.


Porejemplo,puedebuscartodoslosclientesquevivenenFranciaoenEspaa:

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
SELECT * FROM Cliente WHERE Pais IN (Francia,Espaa)

ClauseWHERE...BETWEEN

Tambinpuededevolverunaseleccinderegistrosquesesitanentredoscriteriosespecificados.Lasiguiente
consultapermiterecuperarlalistadelospedidospasadosenelmesdenoviembrede2005:

SELECT * FROM Pedidos WHERE FechaPedido BETWEEN 01/11/05 AND 30/11/05

ClauseWHERE...LIKE

Puede utilizar la clusula WHERE ... LIKE para devolver todos los registros en los que existe una condicin
particular para un campo dado. Por ejemplo, la siguiente sintaxis selecciona todos los clientes cuyo apellido
empiezaconunad:

SELECT * FROM Cliente WHERE Apellido LIKE d%

Enestainstruccin,seutilizaelsmbolo%parareemplazarunasecuenciadecaracterescualquiera.

ClauseORDERBY...

PuedeutilizarlaclusulaORDER BYparadevolverlosregistrosenunordenparticular.LaopcinASCindicaunorden
creciente, la opcin DESC indica un orden decreciente. Se pueden especificar varios campos como criterio de
ordenacin. Se analizan de izquierda a derecha. En caso de igualdad en el valor de un campo, se utiliza el
siguientecampo:

SELECT * FROM Cliente ORDER BY Apellido DESC,Nombre ASC

Estainstruccindevuelvelosclientesorganizadosporordendecrecientesegnelapellidoy,encasodeigualdad,
porordencrecientesegnelnombre.

b.Insercindedatos

LacreacinderegistrosenunatablaseefectaconelcomandoINSERT INTO.Hayqueindicarlatablaenlaque
deseainsertarunafila,lalistadeloscamposparaloscualesustedespecificaunvalory,finalmente,lalistadelos
valorescorrespondientes.Porlotanto,lasintaxiscompletaeslasiguiente:

INSERT INTO cliente (codigoCliente,nombre,apellido) VALUES (1000, Pedro, Garca)

Alinsertarestenuevocliente,soloelapellidoyelnombreaparecenenlatabla.Losotroscampostomarnelvalor
NULL. Si la lista de campos no est indicada, la instruccin INSERT exige que se especifique un valor para cada
campo de la tabla. Por tanto, est obligado a utilizar la palabra clave NULL para indicar que, para un campo

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
determinado, no existen datos. Si la tabla Cliente est compuesta por cinco campos (codigoCliente, apellido,
nombre,direccin,pas),lainstruccinanteriorsepuedeescribirconlasiguientesintaxis:

INSERT INTO cliente VALUES (1000,Garca,Pedro,NULL,NULL)

Enestecaso,lasdospalabrasclaveNULLsonobligatoriasparaloscamposdireccinypas.

c.Actualizacindedatos

La modificacin de campos de registros existentes se efecta con la instruccin UPDATE. Esta instruccin puede
actualizarvarioscamposdevariosregistrosdeunatablaapartirdelasexpresionesqueselefacilitan.Paraello,
debe proporcionar el nombre de la tabla que se debe actualizar, as como el valor que hay que asignar a los
diferentes campos. La lista se indica con la palabra claveSET, seguida por la asignacin del nuevo valor de los
diferentes campos. Si desea que las modificaciones se lleven a cabo en un conjunto limitado de registros, debe
especificar la clusula WHERE, con el fin de limitar el alcance de la actualizacin. Si no se indica ninguna clusula
WHERE,lamodificacinseharenelconjuntodelosregistrosdelatabla.

Porejemplo,paramodificarladireccindeunclienteenparticular,puedeutilizarlasiguienteinstruccin:

UPDATE Cliente SET direccin= Miguel Servet 26 Zaragoza WHERE


codigoCliente=1000

Silamodificacinserealizaenelconjuntodelosregistrosdelatabla,laclusulaWHEREesintil.Porejemplo,si
deseaaumentarelpreciounitariodetodossusartculos,puedeutilizarlasiguienteinstruccin:

UPDATE catalogo SET precioUnitario=precioUnitario*1.1

d.Eliminacindedatos

LainstruccinDELETE FROMpermiteeliminarunoovariosregistrosdeunatabla.Comomnimo,sedebefacilitarel
nombredelatablaenlaquesevaaefectuarlaeliminacin.Sinoseindicanadams,todaslasfilasdelatabla
serneliminadas.Engeneral,unaclusulaWHEREseaadeparalimitarlaextensindelaeliminacin.Elsiguiente
comandoborratodoslosregistrosdelatablaCliente:

DELETE FROM Cliente

Elsiguientecomandoesmenosradicalysoloeliminaunregistrodeterminado:

DELETE FROM Cliente WHERE codigoCliente=1000

Porsupuesto,ellenguajeSQLesmuchomscompletoqueloqueacabamosdeverynosepuedelimitaraestas
cincoinstrucciones.Sinembargo,estassonsuficientesparalamanipulacindelosdatosapartirdeVisualBasic.Si
deseaprofundizarenelaprendizajedellenguajeSQL,consulteunodeloslibrosdisponiblesenestacoleccinque
trateestetemamsdetalladamente.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
PresentacindeADO.NET

ADO.NET es un conjunto de clases, interfaces, estructuras y enumeraciones que permiten la manipulacin de los
datos. Los diferentes componentes de ADO.NET permiten separar el acceso a los datos de la manipulacin de los
datos. ADO.NET facilita tambin la utilizacin del lenguaje XML, al permitir la conversin al formato XML de datos
relacionales o la importacin de datos en formato XML en un modelo relacional. Hay dos modos de funcionamiento
disponiblesenADO.NET:

l Elmodoconectado.

l Elmodonoconectado.

1.Modoconectado

En un entorno conectado, la aplicacin o el usuario estn permanentemente conectados a la fuente de datos.


Desdelosprincipiosdelainformtica,estehasidoelnicomododisponible.Estemodopresentaalgunasventajas
ensufuncionamiento:

l Esfcildegestionar:laconexinseabrealprincipiodelaaplicacinyluegosecierraalfinalizarla.

l Elaccesoconcurrenteesmsfcildecontrolar:comotodoslosusuariosestnconectadosdeformapermanente,es
msfcilcontrolarquintrabajaenlosdatos.

l Los datos estn actualizados: siempre gracias a la conexin permanente a los datos, resulta fcil avisar a todas las
aplicacionesquelosutilizandelasmodificacionesqueseacabanderealizar.

Peroexistenciertosinconvenientes:

l Laconexindereddebeserpermanente:siseutilizalaaplicacinenunordenadorporttil,puedequeelaccesoala
rednoestsiempredisponible.

l Nos arriesgamos a desaprovechar recursos del servidor: cuando se establece una conexin entre una aplicacin
cliente y un servidor, se asignan recursos del servidor para la gestin de la conexin. Estos recursos estn
monopolizadosporlaconexin,inclusoaunquenohayaningndatoqueesttransitandoporlaconexin.

Sinembargo,enciertassituaciones,lautilizacindeunmodoconectadoesineludible.Eselcaso,porejemplo,de
lasaplicacionesqueefectantratamientosentiemporeal.

2.Modonoconectado

Unmodonoconectadosignificaqueunaaplicacinounusuarionoestconectadoconstantementeaunafuentede
datos.LasaplicacionesdeInternetutilizanamenudoestemododefuncionamiento.Seabrelaconexin,seextraen
losdatosydespussecierralaconexin.Elusuariotrabajaconlosdatosdesdesunavegador,ylaconexinse
vuelveaabrirparalaactualizacindelafuentededatosoparalaobtencindeotros.Losusuariosquetrabajanen
ordenadores porttiles son los principales usuarios de entornos desconectados. Un mdico puede, por ejemplo,
cargarporlamaanaloshistorialesmdicosdelospacientesquevaavisitarduranteelda,yluego,porlatarde,
fusionarlasmodificacionesenlabasededatos.Lasventajasdeunentornodesconectadosonlassiguientes:

l Seutilizanlasconexionesduranteeltiempomscortoposible.Deestamanera,unpequeonmerodeconexiones
disponiblesenunservidorsonsuficientesparamuchosusuarios.

l Unentornodesconectadomejoralaescalabilidadylasprestacionesdeunaaplicacinaloptimizarladisponibilidadde
lasconexiones.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Sinembargo,elentornodesconectadocomportaalgunosinconvenientes:

l Losdatosdisponiblesenlaaplicacinnosiempreestnactualizados.Porejemplo,enelcasodenuestromdico,sisu
ayudanteaadelosresultadosdelanlisisdespusdequelhayarecogidolashistoriasmdicasdesuspacientes,no
podrdisponerinmediatamentedelainformacin.

l Pueden surgir conflictos cuando se actualiza la informacin en la base de datos. Este tipo de problemas se deben
solucionar en el momento de disear la aplicacin. Hay diferentes planteamientos posibles para la gestin de estos
conflictos:

n Autorizarelpredominiodelasactualizacionesmsrecientes,suprimiendolosdatosyapresentesenlabase
dedatos.

n Autorizarelpredominiodelasactualizacionesmsantiguas,rechazandolasnuevasactualizaciones.

n Prever cdigo que permita al usuario elegir lo que desea hacer en caso de conflicto en el momento de
actualizar.

3.ArquitecturadeADO.NET

LametadeADO.NETconsisteenfacilitarunconjuntodeclasesquepermiteelaccesoalasbasesdedatos.Haydos
tiposdecomponentesdisponibles:

l Losproveedoresdedatosespecficosparauntipodebasededatos.Aseguranlacomunicacinconuntipoespecfico
debasededatosypermitenlamanipulacindelosdatosdirectamenteenlabasededatosenmodoconectado.Sin
embargo,lasposibilidadessonlimitadas,yaquesoloestdisponibleunaccesoenmododesololectura.

l Lasclasesdemanipulacindedatos,independientesdeltipodebasededatos,utilizablesinclusosinbasededatos,
permitenlamanipulacinlocaldelosdatosenlaaplicacin.

4.Losproveedoresdedatos

Losproveedoresdedatossirvendepasarelaentreunaaplicacinyunabasededatos.Seutilizanpararecuperar
lainformacinapartirdelabasededatos,ytransferirloscambiosefectuadosenlosdatosporlaaplicacinhaciala
basededatos.HaycuatroproveedoresdedatosdisponiblesenelFramework.NET:

l ElproveedorparaSQLServer.

l ElproveedorparaOLEDB.

l ElproveedorparaODBC.

l ElproveedorparaOracle.

Todosellosproponenlaimplementacindecuatroclasesdebase,necesariasparaeldilogoconlabasededatos:

l LaclaseConnectionpermiteestablecerunaconexinconelservidordebasededatos.

l LaclaseCommandpermitepedirlaejecucindeunainstruccinodeunconjuntodeinstruccionesSQLaunservidor.

l La clase DataReader proporciona un acceso en solo lectura, y un desplazamiento, solo hacia delante, de los datos
(mismoprincipioqueunarchivosecuencial).

l La clase DataAdapter se utiliza para asegurar la transferencia de los datos hacia un sistema de cach local en la
aplicacin (DataSet) y actualizar la base de datos, en funcin de las modificaciones efectuadas localmente en el
DataSet.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Algunasclasesestndisponiblespara,porejemplo,lagestindelastransaccionesoelpasodeparmetrosauna
instruccinSQL.

a.SQLServer

ElproveedordedatosparaSQLServerutilizaunprotocolonativoparadialogarconelservidordebasededatos.
Adems, consume pocos recursos porque accede al servidor sin utilizar capa lgicas adicionales como OLE DB u
ODBC. Se puede utilizar con SQL Server a partir de la versin 7. Todas las clases de este proveedor de datos
estndisponiblesenelespaciodenombres System.Data.SqlClient.Enesteespaciodenombres,elnombrede
cada clase contiene el prefijo Sql. As, la clase que permite conectarse a un servidor SQL Server se llama
SqlConnection.

b.OLEDB

El proveedor OLE DB utiliza la capa lgica OLE DB para comunicarse con el servidor de base de datos. Puede
utilizaresteproveedorparadialogarconunabasededatosparalaquenoexistenproveedoresespecficos,pero
para la que est disponible el controlador OLE DB. Con esta solucin, el proveedor no contacta con el servidor
directamente,sinoquepasaporelcontroladorOLEDBparacomunicarse.Paraqueestacomunicacinseaposible,
elcontroladordebeimplementaralgunasinterfaces.Todaslasclasesestndisponiblesenelespaciodenombres
System.Data.OleDb.LosnombresdeclasedeesteespaciodenombresestnprecedidosporOleDb.Parapoder
funcionar correctamente, este proveedor exige la instalacin de MDAC 2.6 en la mquina (Microsoft Data Access
Components).

c.ODBC

El proveedor ODBC utiliza un controlador ODBC nativo para comunicarse con el servidor de base de datos. El
principio es idntico al utilizado para el proveedor OLE DB. Todas las clases estn disponibles en el espacio de
nombres System.Data.Odbc. Los nombres de clases vienen precedidos por Odbc. Para poder funcionar
correctamente,esteproveedorexigelainstalacindeMDAC2.6enlamquina(MicrosoftDataAccessComponents).

d.Oracle

El proveedor Oracle permite la conexin a una fuente de datos Oracle, a travs de las herramientas cliente de
Oracle.Estasherramientasdebeninstalarseenelsistemaoperativoparapoderseconectaraunabasededatos
Oracle. Es necesaria la versin 8.1.7 o una superior. Las clases estn en el espacio de nombres
System.Data.OracleClientyutilizanOraclecomoprefijodenombre.ParautilizarelproveedorparaOracle,deber
tambinagregarunareferenciahacialabibliotecaSystem.Data.OracleClient.dll.

5.Buscarlosproveedoresdisponibles

Paraasegurarelbuenfuncionamientodeunaaplicacinqueutilizaunaccesoalosdatos,losproveedoresdedatos
deben estar disponibles en el puesto cliente. La clase DbProviderFactories propone el mtodo compartido
GetFactoryClasses,quepermiteenumerarlosproveedoresdedatosdisponiblesenelcliente.Elejemplosiguiente
decdigomuestraelnombre,ladescripcinyelespaciodenombresrazdecadaproveedorinstaladoenelequipo
detrabajo.

Imports System.Data
Imports System.Data.Common
Module ListaProviders
Sub Main()
Dim resultado As DataTable

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
recuperacin de la lista de proveedores en un dataTable
resultado = DbProviderFactories.GetFactoryClasses()
Dim columna As DataColumn
Dim fila As DataRow
recorre las columnas del DataTable y muestra el nombre
For Each columna In resultado.Columns
Console.Write(columna.ColumnName & vbTab)
Next
Console.WriteLine()
recorre el DataTable y muestra cada fila
For Each fila In resultado.Rows
recorre cada fila y muestra cada campo
For Each columna In resultado.Columns
Console.Write(fila(columna.ColumnName) & vbTab)
Next
Console.WriteLine()
Next
Console.ReadLine()
Stop
End Sub
End Module

6.Compatibilidaddelcdigo

Enfuncindelproveedorutilizado,debeimportarelespaciodenombrescorrespondienteparatenerfcilaccesoa
lasclasesdelproveedor.Sinembargo,comolasclasesdecadaunodelosproveedoresnollevanelmismonombre,
sucdigoseraespecficodeuntipodeproveedor.Esposibleescribircdigoprcticamenteindependientedeltipo
de proveedor para ello, en vez de utilizar las clases especficas de cada uno de los proveedores, puede utilizar
comotipodedatoslasinterfacesqueimplementan.Lautilizacindeunaclaseespecficasoloesindispensablepara
crearlaconexin.Unavezcreadalaconexin,puedetrabajarnicamenteconinterfaces.Elsiguienteejemplode
cdigomuestralalistadelcontenidodeunatabladeunabaseSQLServerqueutilizanicamenteinterfaces.

Module accesoBdPorInterfaces
Dim ctn As IDbConnection
Public Sub main()
es la nica fila de cdigo especfica para un proveedor
ctn = New System.Data.SqlClient.SqlConnection("Data Source=TG;Initial
Catalog=Northwind;Integrated Security=True")
Dim cmd As IDbCommand
cmd = ctn.CreateCommand
ctn.Open()
cmd.CommandText = "select * from products"
Dim lector As IDataReader
lector = cmd.ExecuteReader
Console.WriteLine("Lectura de datos en una base de datos SQL Server")
Do While lector.Read
Console.WriteLine("nmero: {0} nombre producto: {1}",
lector.GetInt32(0), lector.GetString(1))
Loop
End Sub
End Module

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Laejecucindeestecdigomuestraelsiguienteresultado:

Lectura de datos en una base de datos SQL Server


nmero: 56 nombre producto: Gnocchi di nonna Alice
nmero: 57 nombre producto: Ravioli Angelo
nmero: 58 nombre producto: Caracoles de Lleida
nmero: 59 nombre producto: Raclette Courdavault
nmero: 60 nombre producto: Queso Roncal
nmero: 61 nombre producto: Sirope de fresa
nmero: 62 nombre producto: Tarta de azcar

Siestaaplicacindebemigrardespushaciaotrotipodebasededatos,solohayquecambiarlalnearelativaala
conexin. Si ahora los datos estn disponibles en una base Access, la creacin de la conexin toma la siguiente
forma:

ctn = New System.Data.OleDb.OleDbConnection ("Provider=Microsoft.Jet.


OLEDB.4.0;
Data Source=C:\Documents and Settings\usuario\Mis documentos\
libro vb.net 2010\
acceso a bases de datos\ejemplos\NWIND.MDB")

Laejecucindelcdigomodificadodeestaformageneraefectivamenteelmismoresultado:

Lectura de datos en una base de datos Access


nmero: 56 nombre producto: Gnocchi di nonna Alice
nmero: 57 nombre producto: Ravioli Angelo
nmero: 58 nombre producto: Caracoles de Lleida
nmero: 59 nombre producto: Raclette Courdavault
nmero: 60 nombre producto: Queso Roncal
nmero: 61 nombre producto: Sirope de fresa
nmero: 62 nombre producto: Tarta de azcar

PeroconvieneserprudenteynoutilizarinstruccionesSQLespecficasparauntipodebasededatosparticular.Para
facilitar la revisin del cdigo, es preferible agrupar todas las instrucciones SQL en forma de constantes de tipo
cadena de caracteres al principio de cada mdulo. Con esta tcnica, no tendr que buscar instrucciones SQL en
medio de centenares de lneas de cdigo Visual Basic. Tambin conviene ser prudente durante la utilizacin de
parmetrosenunainstruccinSQL.ElproveedorparaSQLServerutilizaparmetrosconnombreporlotanto,el
ordendecreacindelosparmetrosnotieneimportancia.

ElproveedorparaOLEDButilizalaposicindelosparmetrosenlainstruccinSQLparalasustitucinalahorade
la ejecucin. El orden de la creacin de los parmetros es pues, en este caso, capital para el funcionamiento
correctodelainstruccin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Utilizacindelmodoconectado

Enestecaptulo,vamosatratardelasoperacionesquepuedenserejecutadasenunabasededatosalutilizarel
modo conectado. Ciertas nociones estudiadas en este captulo sern tiles para el funcionamiento en modo
desconectado. Para probar las distintas funcionalidades estudiadas en este captulo, utilizaremos un servidor SQL
Server2010.LabasededatosutilizadaserlabaseNorthwindquesecreapordefectocuandoseinstalaelservidor.
Unapartedelaestructuradelabaseestdisponibleenelesquemasiguiente:

1.Conexinaunabasededatos

Parapodertrabajarconunservidordebasededatos,unaaplicacindebeestablecerunaconexinderedconel
servidor. La clase SqlConnection es capaz de gestionar una conexin hacia un servidor SQL Server versin 7.0 o
posterior.Comoparacualquierobjeto,enprimerlugardebemosdeclararunavariable.

Dim ctn As System.Data.SqlClient.SqlConnection

Luego,debemoscrearlainstanciadelaclaseeinicializarlainvocandounconstructor.Lainicializacinvaaconsistir
esencialmenteenindicarlosparmetrosutilizadosparaestablecerlaconexinconelservidor.Estosparmetrosse
definen en forma de una cadena de caracteres. Pueden ser indicados durante la llamada al constructor o
modificadosporlapropiedadConnectionString.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
a.Cadenadeconexin

El formato estndar de una cadena de conexin est constituido por una serie de pares palabra clave/valor,
separadasporpuntosycomas.Elsigno=seusaparalaasignacindeunvaloraunapalabraclave.Elanlisisde
lacadenaseefectadurantelaasignacindelacadenaalapropiedadConnectionString.Losvaloresasociadosa
laspalabrasclaveseextraenyseasignanalasdistintaspropiedadesdelaconexin.Siseencuentraunerrorde
sintaxis,segeneraunaexcepcininmediatamenteynosemodificaningunapropiedad.Porelcontrario,solose
podr controlar algunas propiedades durante la apertura de la conexin. En este momento se activar una
excepcinsilacadenadeconexincontieneunerror.solosepuedemodificarlacadenadeconexinsilaconexin
estcerrada.Estassonlaspalabrasclavesexistentesparaunacadenadeconexin:

ConnectTimeout

Duracinensegundosdurantelacuallaaplicacinesperarunarespuestadelservidorasupeticin
deconexin.Pasadoesteplazo,seactivaunaexcepcin.

DataSource

Nombreodireccindereddelservidorhaciaelqueseestablecelaconexin.Elnmerodelpuertose
puedeespecificardespusdelnombreodeladireccindered.Sinoestindicado,elnmerode
puertoesiguala1433.

InitialCatalog

Nombredelabasededatosenlaquesedebeefectuarlaconexin.

IntegratedSecurity

Siestevalorsecolocaenfalse,sedebefacilitarunnombredeusuarioyunacontraseaenla
cadenadeconexin.Encasocontrario,seutilizalacuentaWindowsdelusuarioparala
autenticacin.

PersistSecurityInfo

Siseposicionaestevalorentrue,elnombredelusuarioysucontraseasonaccesiblesporla
conexin.Porrazonesdeseguridad,sedebecolocarestevalorenfalse.Dehecho,esassinoindica
nadaenlacadenadeconexin.

Pwd

ContraseaasociadaalacuentaSQLServerutilizadaparalaconexin.Sinoexistecontrasea
asociadaaunacuenta,sepuedeomitirestainformacinenlacadenadeconexin.

UserID

NombredelacuentaSQLServerutilizadaparalaconexin.

ConnectionLifeTime

Indicaladuracindeunaconexinenunpooldeconexiones.Unvalorigualaceroindicauna
duracinilimitada.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ConnectionReset

Indicasilaconexinesreinicializadacuandovuelveaentrarenelpool.

MaxPoolSize

Nmeromximodeconexionesenelpool.

MinPoolSize

Nmeromnimodeconexionesenelpool.

Pooling

Indicasilaconexinsepuedeextraerdeunpooldeconexiones.

Unacadenadeconexinadoptalasiguienteformamnima:

ctn.ConnectionString = "Data Source=Minerve;Initial Catalog=Northwind;


Integrated
Security=true"

b.Pooldeconexiones

Lospoolsdeconexionespermitenmejorarlasprestacionesdeunaaplicacinalevitarlacreacindeconexiones
adicionales. Cuando una conexin est abierta, se crea un pool de conexiones que se basa en un algoritmo
basado,asuvez,enlacadenadeconexin.Ascadapoolestasociadoaunacadenadeconexinparticular.Si
se abre una nueva conexin y no hay pool que corresponda exactamente a su cadena de conexin, se crea un
nuevopool.Lospoolsdeconexionesascreadosexistirnhastaelfinaldelaaplicacin.Cuandosecreaunpool,
sepuedencrearotrasconexionesautomticamenteparasatisfacerelvalorMin Pool Sizeindicadoenlacadena
de conexin. Se podrn aadir otras conexiones al pool hasta alcanzar el valor Max Pool Size de la cadena de
conexin.Cuandoserequiereunaconexin,sepuedeobtenerapartirdeunpooldeconexiones(siexisteuno
quecorrespondeexactamentealascaractersticasdelaconexinrequerida).Porsupuesto,esnecesarioqueel
poolcontengaunadisponibleyactiva.

Sisealcanzaelnmeromximodeconexionesenelpool,lapeticinseponeenlacolahastaqueunaconexin
estdenuevodisponible.Unaconexinsevuelveaponeradisposicindelpooldurantesucierreodurantela
llamada del mtodoDispose en la conexin. Por esta razn, se recomienda cerrar explcitamente las conexiones
cuandoyanoseutilizanenlaaplicacin.Seretiranlasconexionesdelpoolcuandoestedetectaquelaconexin
nohasidoutilizadaduranteunciertotiempo,indicadoporelvalorConnectionLifeTimedelacadenadeconexin.
Tambinseretiranlasconexionesdelpoolsiestedetectaquelaconexinconelservidorhasidointerrumpida.

c.Eventosdeconexin

LaclaseSQLConnectionproponedoseventosquelepermitenseravisadocuandoelestadodelaconexincambia
ocuandoelservidorenvaunmensajedeinformacin.EleventoStateChangedseactivacuandocambiaelestado
delaconexin.ElgestordeesteeventorecibeunparmetrodetipoStateChangeEventArg,quepermiteobtener
conlapropiedadCurrentStateelestadoactualdelaconexin,yconlapropiedadOriginalState,elestadodela
conexin antes de la desactivacin del evento. Para probar el valor de estas dos propiedades, puede utilizar la
enumeracinConnectionState.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Elevento InfoMessage se activa cuando el servidor le informa de una situacin anormal, pero que no justifica la
activacin de una excepcin (gravedad del mensaje inferior a 10). El gestor de eventos asociado recibe un
parmetro de tipo InfoMessageEventArgs. Por la propiedad Errors de este parmetro, tiene acceso a objetos
SqlErrors que corresponden a las informaciones enviadas por el servidor. El siguiente cdigo muestra en la
consolalosmensajesdeinformacinqueprovienendelservidor.

Private Sub ctn_InfoMessage(ByVal sender As Object, ByVal e As System.Data.


SqlClient.SqlInfoMessageEventArgs) Handles ctn.InfoMessage
Dim info As SqlClient.SqlError
For Each info In e.Errors
Console.WriteLine(info.Message)
Next
End Sub

2.Ejecucindeuncomando

Despusdehaberestablecidounaconexinhaciaunservidordebasededatos,puedetransmitirleinstrucciones
SQL.SeutilizalaclaseSqlCommandparapediralservidorlaejecucindeuncomandoSQL.Estaclasecontienevarios
mtodosquepermitenlaejecucindediferentestiposdeconsultasSQL.LaclaseSqlCommandpuedeinstanciarsede
maneraclsica,utilizandounodesusconstructores,osepuedeobtenerunainstanciaporelmtodoCreateCommand
delaconexin.

a.Creacindeuncomando

LaprimeraposibilidadparacrearunainstanciadeSqlCommandconsisteenutilizarunodelosconstructoresdela
clase. El uso del constructor por defecto le obliga a utilizar diferentes propiedades para facilitar la informacin
relativaalainstruccinSQLquesevaaejecutar.

LapropiedadCommandTextcontieneeltextodelainstruccinSQLquesevaaejecutar.LapropiedadConnection
debehacerreferenciaaunaconexinvlidahaciaelservidordebasededatos.Elsiguientecdigoresumeestas
diferentesoperaciones:

Dim cmd As SqlCommand


cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * FROM Products"

Lasegundasolucinconsisteenutilizarunconstructorsobrecargadoqueaceptecomoparmetroslainstruccin
SQLenformadecadenadecaracteresylaconexinutilizadaporestaSqlCommand.Assepuederesumirelcdigo
anteriorconlasiguientelnea:

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim cmd As new SqlCommand( " SELECT * FROM Products",ctn)

LatercerasolucinconsisteenutilizarelmtodoCreateCommanddelaconexin.Enestecaso,sedebeespecificar
nicamentelainstruccinSQL.

Dim cmd as SqlCommand


cmd = ctn.CreateCommand
cmd.CommandText = " SELECT * FROM Products"

b.Lecturadedatos

Amenudo,lainstruccinSQLdeunSqlCommandseleccionaunconjuntoderegistrosenlabasededatos,oaveces
unvalornicoqueeselresultadodeunclculoefectuadosobrevalorescontenidosenlabase.Unainstruccin
SQL, que devuelve un conjunto de registros, debe ser ejecutada con el mtodo ExecuteReader. Este mtodo
devuelveunobjetoDataReaderquepermitirdespuslalecturadelainformacinprocedentedelabasededatos.
Silainstruccinsolodevuelveunvalornico,elmtodoExecuteScalarseencargadelaejecucinydevuelvepor
smismoelvalordelabasededatos.

Elsiguientecdigopermitesaberelnmerodepedidospasadosporuncliente:

cmd.CommandText = " select count(orderid) from orders where customerid=FRANK"


Console.WriteLine("el cliente FRANK ha pasado {0} pedidos(s)",
cmd.ExecuteScalar())

Elcasodelasinstruccionesquedevuelvenvariosregistrosesunpocomscomplejo.Despusdehaberejecutado
lainstruccinconelmtodoExecuteReaderydehaberrecuperadoelobjetoDataReader,puedeutilizaresteltimo
para recorrer los resultados devueltos. El mtodoRead de la clase DataReader permite el desplazamiento por el
conjunto de los registros devueltos. Este mtodo devuelve un booleano que indica si queda otro registro. El
desplazamiento solo es posible desde el primero hasta el ltimo registro. Este tipo de desplazamiento se llama
Forward Only. La informacin contenida en el registro actual es accesible con uno de los mtodos Get... de la
claseDataReader.Estosmtodospermitenextraerlosdatosdelregistroyconvertirlosenuntipodedatos.NET.
Existe una versin para cada tipo de datos del Framework .NET. Por supuesto, hace falta que la informacin
presenteenelregistrosepuedaconvertireneltipocorrespondiente.Silaconversinesimposible,seactivauna
excepcin. Los mtodos Get... esperan, como parmetro, el nmero del campo en el que deben recuperar la
informacin.TambinpuedeutilizarlapropiedadpordefectoItemdelDataReader,indicandoelnombredelcampo.
Enestecaso,nohayconversinyelvalordevueltoesdetipoObject.

Elsiguientecdigomuestralalistadetodaslascategorasdeproductosdisponibles:

Imports System.Data.SqlClient
Module TestExecuteReader
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " select * from categories"
lector = cmd.ExecuteReader
Do While lector.Read
Console.WriteLine("nmero de la categora:{0}" & vbTab &
"Descripcin:{1}", lector.GetInt32(0), lector("CategoryName"))
Loop
lector.Close()
ctn.Close()
End Sub
End Module

LautilizacindeunaconexinporpartedeunDataReaderseefectademaneraexclusiva.Paraquelaconexin
estdenuevodisponibleparaotrocomando,debecerrar DataReaderdespusdesuutilizacin.

c.Modificacionesdelosdatos

La modificacin de los datos en una base de datos se efecta principalmente con las instruccionesSQL INSERT,
UPDATE,DELETE. Estas instrucciones no devuelven registros procedentes de la base de datos. Para utilizar estas
instrucciones, debe crear un SqlCommand, y luego pedir la ejecucin de este comando travs del mtodo
ExecuteNonQuery. Este mtodo devuelve el nmero de registros afectados por la ejecucin de la instruccin SQL
contenidaenelSqlCommand.SilapropiedadCommandTextcontienevariasinstruccionesSQL,elvalordevueltoporel
mtodo ExecuteNonQuery corresponde al nmero total de filas afectadas por todas las instrucciones SQL del
SqlCommand.

ElsiguientecdigoaadeunanuevaempresadeentregaenlatablaShippers:

Imports System.Data.SqlClient
Module TestExecuteNonQuery
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Public Sub main()
ctn = New SqlClient.SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlClient.SqlCommand
cmd.Connection = ctn
cmd.CommandText = "Insert into shippers (companyname,phone) values
(DHL,91 123 56 87 43)"
Console.WriteLine("{0} fila(s) aadidas(s) en la tabla",
cmd.ExecuteNonQuery)
ctn.Close()
End Sub
End Module

d.Utilizacindeparmetros

La manipulacin de instrucciones SQL se puede facilitar con la creacin de parmetros permiten construir

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
instruccionesSQLgenricasquesepuedenvolverautilizarfcilmente.Elprincipiodefuncionamientoesparecidoa
los procedimientos y funciones de Visual Basic. Una alternativa a la utilizacin de parmetros podra ser la
construccindinmicadeinstruccionesSQLporconcatenacindecadenasdecaracteres.

Acontinuacin,unejemploqueutilizaestatcnicayquepermitelabsquedadeunclienteporsucdigo(luego
veremoscmomejorarestecdigoalutilizarparmetros):

Imports System.Data.SqlClient
Module TestBuscarConcat
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader
Dim codCliente As String
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
Console.Write("introducir el cdigo del cliente buscado:")
codCliente = Console.ReadLine()
cmd.CommandText = " SELECT * from Customers WHERE CustomerID = "
& codCliente & ""
lector = cmd.ExecuteReader
Do While lector.Read
Console.WriteLine("nombre del cliente:{0}", lector("ContactName"))
Loop
lector.Close()
ctn.Close()
Console.ReadLine()
End Sub
End Module

LaparteimportantedeestecdigoseencuentraenelmomentodeasignarunvaloralapropiedadCommandText.
UnainstruccinSQLcorrectasedebeconstruirporlaconcatenacindecadenasdecaracteres.Ennuestrocaso,
esto es relativamente sencillo porque solo hay un valor variable en la instruccin SQL. Si fuera necesario variar
muchosdatos,seraprecisorealizarunagrancantidaddeconcatenaciones.Loserroresclsicosquesecometen
enestasconcatenacionesson:

l Olvidarsedeunespacio.

l Olvidarsedeloscaracteres"paraenmarcarunvalordeltipocadenadecaracteres.

l Unnmerodecarcterimpar.

Todos estos errores tienen el mismo efecto: la creacin de una instruccin SQL invlida que ser rechazada
durantelaejecucinporelservidor.

Lautilizacindelosparmetrossimplificaconsiderablementelaescrituradeestetipodeconsulta.Seutilizanlos
parmetrosparamarcarunaubicacinenunrequerimientodondeestarcolocado,enelmomentodelaejecucin,
unvalorliteralcadenadecaracteresonumrico.Losparmetrospuedensernominalesoannimos.Unparmetro
annimoseintroduceenunaconsultaconelcarcter?.Losparmetrosnominalesseespecificanconelcarcter@
seguidoporelnombredelparmetro.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Laconsultadenuestroejemploanteriorpuedeadoptarlasiguienteforma:

cmd.CommandText = " SELECT * from Customers WHERE CustomerID = ?"

cmd.CommandText = " SELECT * from Customers WHERE CustomerID = @Codigo

LaejecucindelSqlCommandfracasaahorasinoseleproporcionanlosvaloresdelosparmetros.

El SqlCommand debe tener una lista de valores utilizados para reemplazar los parmetros en el momento de la
ejecucin.EstalistasealmacenaenlacoleccinParametersdelSqlCommand.AntesdelaejecucindelSqlCommand,
es necesario crear los objetos SqlParameter y aadirlos a la coleccin. Para cada SqlParameter, hay que
proporcionar:

l Elnombredelparmetro.

l Elvalordelparmetro.

l Ladireccindeutilizacindelparmetro.

Lasdosprimerasinformacionesseindicandurantelaconstruccindelobjeto:

Dim paramCodigoCliente As SqlParameter


paramCodigoCliente = New SqlParameter("@Codigo", codigoCliente)

La direccin de utilizacin indica si la informacin contenida en el parmetro es pasada al cdigo SQL para su
ejecucin(Input),osilecorrespondealaejecucindelcdigoSQLmodificarelvalordelparmetro(Output)olos
dos(InputOutput).LapropiedadDirectiondelaclaseSqlParameterindicaelmododeutilizacindelparmetro.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
El parmetro est ahora preparado para aadirse a la coleccin Parameters. Conviene comprobar en este
momento si la consulta utiliza parmetros annimos. Se deben aadir los parmetros a la coleccin
obligatoriamente en el orden de su aparicin en la consulta. Si se utilizan los parmetros nominales, no es
necesariorespetarestaregla,aunquesprudente,porsiundaelcdigoSQLesmodificadoydejadeutilizarlos
parmetros nominales. Podra ser el caso si debe cambiar de tipo proveedor de datos y el nuevo no acepta los
parmetrosnominalesenunainstruccinSQL.AhoraelSqlCommandestlistoparalaejecucin.Hayqueobservar
que,conestasolucin,notenemosquepreocuparnosdeltipodevaloresperadoporlainstruccinSQLparasaber
sidebemosenmarcarloconcaracteres.SiseutilizanparmetrosenlasalidadelainstruccinSQL,soloestarn
disponibles despus del cierre delDataReader. El siguiente ejemplo muestra, adems del nombre del cliente, el
nmerodepedidosyapasados:

Imports System.Data.SqlClient
Module TestBuscarConcat
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim lector As SqlDataReader
Dim codCliente As String
Dim paramCodCliente As SqlParameter
Dim paramNbComandos As SqlParameter

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;
Initial Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
Console.Write("introducir el cdigo del cliente buscado:")
codCliente = Console.ReadLine()
cmd.CommandText = " SELECT * from Customers WHERE CustomerID =
@Codigo;select @nbPed=count(orderid) from orders where customerid=@codigo"
paramCodCliente = New SqlParameter("@Codigo", codCliente)
paramCodCliente.Direction = ParameterDirection.Input
cmd.Parameters.Add(paramCodCliente)
paramNbPedidos = New SqlParameter("@nbPed", Nothing)
paramNbPedidos.Direction = ParameterDirection.Output
cmd.Parameters.Add(paramNbPedidos)
lector = cmd.ExecuteReader
Do While lector.Read
Console.WriteLine("nombre del cliente:{0}", lector("ContactName"))
Loop
lector.Close()
Console.WriteLine("este cliente ha pasado {0} pedido(s)",
cmd.Parameters ("@nbPed").Value)
ctn.Close()
Console.ReadLine()
End Sub

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
End Module

e.Ejecucindeunprocedimientoalmacenado

Los procedimientos almacenados son elementos de una base de datos que corresponden a un conjunto de
instrucciones SQL que pueden ser ejecutadas con una simple llamada a su nombre. Son verdaderos programas
SQLquepuedenrecibirparmetrosydevolvervalores.Adems,losprocedimientosalmacenadossonregistrados
enelcachdelservidor,conlaformacompilada,durantesuprimeraejecucin,loqueaumentasusprestaciones
paralassiguientesejecuciones.Otraventajadelosprocedimientosalmacenadosescentralizarenelservidorde
basededatostodosloscdigosSQLdeunaaplicacin.Sisedebenaportarmodificacionesenlasinstrucciones
SQL, solo tendr que hacerlo en el servidor sin que sea preciso retomar el cdigo de la aplicacin, es decir, sin
tenerquevolveragenerarydesplegarlaaplicacin.

La llamada desde Visual Basic a un procedimiento almacenado es prcticamente igual a la ejecucin de una
instruccin SQL. La propiedad CommandText contiene el nombre del procedimiento almacenado. Tambin puede
modificar la propiedad CommandType con el valor CommandType.StoredProcedure para indicar que la propiedad
CommandText contiene el nombre de un procedimiento almacenado. Como para una instruccin SQL, un
procedimiento almacenado puede utilizar parmetros en entrada o en salida. Hay un tercer tipo de parmetro
disponible para los procedimientos almacenados en el tipo ReturnValue. Este tipo de parmetro sirve para
recuperar el valor devuelto por la instruccin Return del procedimiento almacenado (mismo principio que una
funcinVisualBasic).Paraprobarestasnuevasnociones,vamosautilizarelsiguienteprocedimientoalmacenado
quedevuelveelimportetotaldetodoslospedidospasadosporuncliente.

CREATE PROCEDURE TotalCliente @code nchar(5) AS


declare @total money
select @total=sum(UnitPrice*Quantity*(1-Discount)) from Orders,
[Order Details]
where customerid=@code and Orders.orderid=[order details].orderid
return @total
GO

A nivel del cdigo Visual Basic, debemos indicar que se trata de la ejecucin de un procedimiento almacenado y
agregarunparmetropararecuperarelvalorderetornodedichoprocedimiento.Esteparmetrodebellamarse
RETURN_VALUE.

Imports System.Data.SqlClient
Module TestProcedimientoAlmacenado
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim paramCodCliente As SqlParameter
Dim paramCantidad As SqlParameter
Dim codCliente As String

Public Sub main()


Console.Write("introducir el cdigo del cliente buscado:")
codCliente = Console.ReadLine()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
ctn.Open()
cmd = New SqlCommand

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
cmd.Connection = ctn
cmd.CommandText = "TotalCliente"
cmd.CommandType = CommandType.StoredProcedure
paramCodCliente = New SqlParameter("@Cod", codCliente)
paramCodCliente.Direction = ParameterDirection.Input
cmd.Parameters.Add(paramCodCliente)
paramCantidad = New SqlParameter("RETURN_VALUE", SqlDbType.Decimal)
paramCantidad.Direction = ParameterDirection.ReturnValue
cmd.Parameters.Add(paramCantidad)
cmd.ExecuteNonQuery()
Console.WriteLine("Este cliente ha pasado {0} euros de pedido",
paramCantidad.Value)
Console.ReadLine()
ctn.Close()
End Sub
End Module

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Utilizacindelmodonoconectado

En un modo no conectado, el enlace con el servidor de base de datos no es permanente. Hay que conservar
localmentelosdatosconlosquesedeseatrabajar.Laideaesvolveracrear,conlaayudadediferentesclases,una
organizacinsimilaraladeunabasededatos.Lasprincipalesclasesvienenrepresentadasenelsiguienteesquema:

DataSet

Eselcontenedordemayornivel,juegaelmismopapelquelabasededatos.

DataTable

Comosunombreindica,eselequivalentedeunatabladebasededatos.

DataRow

Estaclasejuegaelpapeldeunregistro(fila).

DataColumn

Estaclasereemplazauncampo(columna)deunatabla.

UniqueConstraint

Eselequivalentedelaclaveprimariadeunatabla.

ForeignKeyConstraint

Eselequivalentedelaclaveexterna.

DataRelation

Representaunenlacepadre/hijoentredosDataTable.

Elesquemasiguienterepresentaestaorganizacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
Ahoravamosavercmocrearymanipulartodasestasclases.

1.RellenarunDataSetapartirdeunabasededatos

Para poder trabajar localmente con los datos, debemos traerlos desde la base de datos a un DataSet. Cada
proveedor de datos facilita una claseDataAdapter, que asegura el dilogo entre la base de datos y un DataSet.
Todoslosintercambiossehacenpormediodeestaclase,tantodesdelabasededatoshaciaelDataSetcomodel
DataSet hacia la base de datos para la actualizacin de los datos. El DataAdapter utilizar una conexin para
contactarconelservidoryunoovarioscomandosparaeltratamientodelosdatos.

a.UtilizacindeunDataAdapter

Lo primero que hay que hacer es crear una instancia de la clase SQLDataAdapter. Luego debemos configurar el
DataAdapter con el fin de indicarle qu datos deseamos traer de la base de datos. La propiedadSelectCommand
debereferenciarunobjetoCommand,quecontienelainstruccinSQLencargadadeseleccionarlosdatos.Elobjeto
Commandutilizadotambinpuedellamaraunprocedimientoalmacenado.Lanicarestriccinesquelainstruccin
SQL ejecutada por el objeto Command sea una instruccin SELECT. La clase DataAdapter tambin contiene las
propiedadesInsertCommand,DeleteCommandyUpdateCommand,quehacenreferenciaalosobjetosCommand,utilizados
durante la actualizacin de la base de datos. Si no deseamos efectuar la actualizacin de la base, estas
propiedadessonoptativas.Lasveremosmsendetalleenelcaptulodedicadoalaactualizacindelabasede
datos.

ElmtodoFilldelaclaseDataAdapterseutilizaluegopararellenarelDataSetconelresultadodelaejecucindel
comando SelectCommand. Este mtodo espera como parmetros el DataSet que debe rellenar y un objeto
DataTableounacadenadecaracteresutilizadaparanombrarel DataTable en elDataSet.El DataAdapterutiliza,
internamente,unobjetoDataReaderparaobtenerelnombreyeltipodeloscamposparacrearelDataTableenel
Dataset y despus rellenarlo con los datos. El DataTable y los DataColumn se crean solo si no existen. En caso
contrario,elmtodoFillutilizalaestructuraexistente.SisecreaunDataTable,seaadealacoleccinTablesdel
DataSet. El tipo de datos de los DataColumn se define en funcin de los mapeos previstos por el proveedor de
datos,entrelostiposdelabasededatosylostipos.NET.ElsiguienteejemplorellenaunDataSetconelcdigo,
apellido,direccinyciudaddelosclientes.

Imports System.Data.SqlClient
Module TestDataSet1
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT CustomerId,ContactName,Address,
city from Customers"
ds = New DataSet
da = New SqlDataAdapter()
da.SelectCommand = cmd
da.Fill(ds, "Customers")
End Sub

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Module

En este cdigo la conexin no se ha abierto y cerrado de manera explcita. En efecto, el mtodo Fill abre la
conexin si no est abierta y, en este caso, la vuelve a cerrar tambin al final de su ejecucin. Sin embargo, si
necesitautilizarvariasveceselmtodo Fill,esmseficazquegestioneustedmismolaaperturayelcierrede
conexin.Entodosloscasos,elmtodoFilldejalaconexinenelestadoenquelahaencontrado.

Porsupuesto,unDataSetpuedecontenervariosDataTablecreadosapartirdeDataAdapterdiferentes.Losdatos
puedenvenirdebasesdedatosdiferentesodetiposdeservidoresdiferentes.

Cuando elDataAdapter construye el DataTable, se utlizan los nombres de los campos de la base de datos para
nombrarlosDataColumn.EsposiblepersonalizarestosnombrescreandoobjetosDataTableMappingyagregndolos
a la coleccin TableMappings del DataAdapter. Estos objetos DataTableMapping contienen los objetos
DataColumnMappingutilizadosporelmtodoFill,comotraductoresentrelosnombresdeloscamposenlabasey
los nombres de los Datacolumn en el DataSet. En este caso, en el momento de la llamada del mtodo Fill,
debemosindicarleelnombredelDataTableMappingquedebeutilizar.

Si,paraunoomscampos,noexistemapeodisponible,elnombredelcampoenlabasededatosseusacomo
nombreparaelDataColumncorrespondiente.Porejemplo,podemosutilizarestatcnicaparatraducirloscampos
delabaseNorthwind.

ElsiguientecdigoefectaestatraduccinymuestraelnombredelosDataColumndelaDataTablecreada:

Imports System.Data.SqlClient
Imports System.Data.Common
Module TestTableMapping
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim mapeo As DataTableMapping
Dim dc As DataColumn

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT CustomerId,ContactName,Address,
city from Customers"
ds = New DataSet
da = New SqlDataAdapter()
da.SelectCommand = cmd
mapeo = New DataTableMapping("Customers", "Clientes")
mapeo.ColumnMappings.Add("CustomerId", "CodCliente")
mapeo.ColumnMappings.Add("ContactName", "Nombre")
mapeo.ColumnMappings.Add("Address", "Direccion")
mapeo.ColumnMappings.Add("city", "Ciudad")
da.TableMappings.Add(mapeo)
da.Fill(ds, "Customers")
For Each dc In ds.Tables("Clientes").Columns
Console.Write(dc.ColumnName & vbTab)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Next
Console.ReadLine()
End Sub
End Module

Obtenemoselresultado:

CodigoCliente Apellido Direccin Ciudad

b.AgregarrestriccionesexistentesaunDataSet

El mtodo Fill transfiere hacia el DataSet los datos que proceden de la base. A menudo se utilizan las
restriccionesdelaclaveprincipalenlabasededatosy,pordefecto,elmtodoFillnolastransfierealDataSet.
ParapoderrecuperarestasrestriccionesenelDataSet,haydossolucionesposibles:

l ModificarlapropiedadMissingSchemaActiondelDataAdapterconelvalorMissingSchemaAction.AddWithKey.

da.MissingSchemaAction = MissingSchemaAction.AddWithKey

l Proceder en dos etapas llamando primero al mtodo FillSchema del DataAdapter para crear la estructura
completadelDataTable,yluegollamaralmtodoFillpararellenarelDataTableconlosdatos.

da.FillSchema(ds, SchemaType.Mapped, "Customers")


da.Fill(ds, "Customers")

El segundo parmetro del mtodo FillSchema indica si se debe tener en cuenta el mapeo o si se utiliza la
informacinprocedentedelabase.

Es importante aadir las restricciones de clave principal, ya que el mtodo Fill se va a comportar de manera
diferentesegnsiexistenono.

SiexistenaniveldelDataSet,cuandoelmtodoFillimportaunregistrodesdelabasededatos,verificasiyano
existe una fila con el valor de clave primaria en el DataTable. Si es el caso, solo actualiza los campos de la fila
existente.Si,porelcontrario,nohayunafilaconunvalordeclaveprimariaidntico,entoncessecrealafilaenel
DataTable.

SinohayrestriccindeclaveprimariaenelDataTable,elmtodoFillaadetodoslosregistrosprocedentesdela
base. En este caso, puede que haya duplicados en el DataTable. Eso es particularmente importante cuando se
debellamaralmtodoFillvariasvecespara,porejemplo,obtenerlosdatosmodificadosporotrapersonaenla
basededatos.

2.ConfigurarunDataSetsinbasededatos

NoesnecesariodisponerdeunabasededatosparapoderutilizarlosDataSet.Puedenservircomoalternativaala
utilizacindematricesparalagestininternadelosdatosdeunaaplicacin.Enestecaso,todaslasoperaciones
efectuadas automticamente con el DataAdapter debern realizarse manualmente con el cdigo. Esto incluye, en
particular,lacreacindelosDataTableconsusDataColumn.Laprimeraoperacinquesedeberealizarconsisteen
crearunainstanciadelaclaseDataTable.ElconstructoresperacomoparmetroelnombredelaDataTable.Luego
seutilizaestenombreparaidentificarelDataTableenlacoleccinTablesdelDataSet.Trassucreacin,elDataTable
no contiene ninguna estructura. Por tanto, debemos crear uno o varios DataColumn y agregarlos a la coleccin

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ColumnsdelDataTable.

Se pueden crear los DataColumn utilizando uno de los constructores de la clase o, automticamente, cuando se
agregan a la coleccin Columns. La primera solucin aporta ms flexibilidad, ya que permite la configuracin de
numerosas propiedades del DataColumn en el momento de su creacin. Es necesario indicar, como mnimo, un
nombreyuntipodedatosparalaDataColumn.

col = New DataColumn(("PBruto", Type.GetType("int"))


table.Columns.Add(col)
table.Columns.Add("IVA", Type.GetType("decimal"))

Un DataColumn tambin se puede construir como una expresin basada en otrosDataColumn. En este caso, debe
indicar,durantelacreacindelDataColumn,laexpresinquesirveparacalcularsuvalor.Eltipodedatosgenerados
porlaexpresindebesercompatibleconeltipodedatosdelDataColumn.Tambindebetenercuidadoconeldiseo
delaexpresin,respetarlasmaysculasylasminsculasyasegurarsedenocrearunareferenciacircularentrelos
DataColumn.

table.Columns.Add("PNeto", Type.GetType("System.Decimal"),
"PBruto * (1 + (IVA /100))")

Para asegurar la unicidad de los valores de un DataColumn, es posible utilizar un tipo de DataColumn
autoincrementado. La propiedad AutoIncrement de este DataColumn se debe situar en true. Tambin puede
modificarelincrementoconlapropiedadAutoIncrementStepyelvalordesalidaconlapropiedadAutoIncrementSeed.
El valor contenido en este DataColumn se calcula automticamente cuando se agrega una fila a un DataTable en
funcindeestaspropiedadesyfilasyaexistentesenelDataTable.

EstetipodeDataColumnsesueleutilizarcomoclaveprimariadeunDataTable.Tienelaposibilidaddedefinirlaclave
primaria de un DataTable al facilitar a la propiedadPrimaryKey una tabla que contenga los diferentes DataColumn
quedebencomponerlaclaveprimaria.AlgunaspropiedadesdelosDataColumnsemodificarnautomticamente.La
propiedadUniquesesituarentrueylapropiedad AllowDBNullenfalse.Silaclaveprimariaestconstituidapor
variosDataColumn,solosemodificarlapropiedadAllowDBNullenestosDataColumn.

col = New DataColumn("Numero", Type.GetType("System.Int32"))


col.AutoIncrement = True
col.AutoIncrementSeed = 1000
col.AutoIncrementStep = 1
table.Columns.Add(col)
table.PrimaryKey = New DataColumn() {col}

3.ManipularlosdatosenunDataSet

SeacualseaelmtodoutilizadopararellenarunDataSet,elobjetivodecualquieraplicacinconsisteenmanipular
los datos presentes en el DataSet. La clase DataTable contiene muchas propiedades y mtodos que facilitan la
manipulacindelosdatos.

a.Lecturadelosdatos

La lectura de los datos es la operacin ms frecuente realizada en un DataSet. Primero hay que obtener una

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
referencia al DataTable que contiene los datos, luego podemos recorrer la coleccin Rows del DataTable. Esta
coleccinesunainstanciadelaclaseDataRowCollection.Pordefecto,disponedelapropiedadItem,quepermite
elaccesoaunafilaparticularporunndice.Lapropiedadcountpermiteconocerelnmerodefilasdisponibles.Los
quesuelenusarADOseperdernunpocoalprincipio,porqueenunDataTablenoexistelanocindepunterode
registro, de registro actual, de mtodos de desplazamiento por los resultados. Si desea gestionar todas estas
nociones,debepreverloexplcitamenteensucdigo.ElmtodoGetEnumeratorponeasudisposicinunainstancia
declasequeimplementalainterfazIEnumerator.Graciasaestainstanciadeclase,tenemosaccesoalosmtodos
MoveNext yReset, as como a la propiedadCurrent. Estos tres elementos permiten recorrer fcilmente todas las
filas DataTable. Cada fila corresponde a una instancia de la clase DataRow. Esta clase posee tambin una
propiedadItem,pordefecto,queproporcionaunaccesoalosdiferentescamposdelDataRow.Sepuedeobtener
cadacampograciasasunombreosundice.

Elsiguientecdigoilustraestasnocionesmostrandolalistadelosclientes:

Imports System.Data.SqlClient
Module TestLecturaDataTable

Dim cmd As SqlCommand


Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim en As IEnumerator

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT ContactTitle,ContactName from Customers"
ds = New DataSet
da = New SqlDataAdapter()
da.SelectCommand = cmd
da.Fill(ds, "Customers")
recuperamos el enumerador de las filas del DataTable
en = ds.Tables("Customers").Rows.GetEnumerator
nos volvemos a colocar al principio de la tabla (por seguridad)
en.Reset()
iteramos mientras el metodo MoveNext nos indique que quedan filas
Do While en.MoveNext
accedemos a los campos por el nombre
Console.Write(en.Current("ContactName") & vbTab)
o por el nmero
Console.WriteLine(en.Current(0))
Loop
Console.ReadLine()
End Sub
End Module

b.CreacinderestriccionesenunDataTable

Podemos utilizar limitaciones para poner en marcha restricciones en los datos presentes en un DataTable. Las
restriccionesconstituyenreglasqueseaplicanaunDataColumnoasusDataColumnrelacionadas.Determinanlas

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
accionesefectuadascuandosemodificaelvalorcontenidoenunafila.SolosetienenencuentaparaunDataSetsi
supropiedadEnforceConstraintsestentrue.

Esposibleutilizardostiposderestricciones:

UniqueConstraint

EstetipoderestriccingarantizaqueelvalorolosvalorespresentesenunDataColumnoungrupodeDataColumn
seannicos.LaactivacindeunarestriccinnicaseefectacreandounainstanciadelaclaseUniqueConstraint
con la lista de los DataColumn implicados en la restriccin. Luego, esta UniqueConstraint se debe aadir a la
coleccinConstraintsdelDataTable.

table.Constraints.Add(New UniqueConstraint(New DataColumn() {col}))

SilarestriccinsoloserefiereaunDataColumn,tambinesposiblemodificarsimplementelapropiedadUniquede
esteDataColumn atrue,paracrearunarestriccindetipoUnique.Hayqueobservartambinquelacreacinde
unaclaveprimariageneraautomticamenteunarestriccindetipoUnique.Locontrarionoesverdad.Laviolacin
delarestriccinalmodificarunafilageneraunaexcepcin.

ForeignKeyConstraint

LasForeignKeyConstraintcontrolancmovanacomportarselosDataTablerelacionadosdurantelamodificacino
laeliminacindeunvalorenelDataTableprincipal.Sepuedeconsiderarunaaccindiferenteparaunaeliminacin
y una modificacin. La clase ForeignKeyConstraint dispone de las propiedades DeleteRule y UpdateRule, que
indicanelcomportamientodurantelaeliminacinolamodificacin.Sepuedendarlosvaloressiguientes:

Cascade

Laeliminacinomodificacinsepropagaalafilaolasfilasrelacionadas.

SetNull

ElvalorsemodificaaDBNullenlasfilasrelacionadas.

SetDefault

Elvalorpordefectoseinsertaenlasfilasrelacionadas.

None

Noseefectaningunaaccinenlasfilasrelacionadas.

Es posible agregar una ForeignKeyConstraint creando una instancia de clase e indicndole el DataColumn o los
DataColumn delDataTable padre y el DataColumn o losDataColumn de la tabla hija. Si muchasDataColumn forman
partedelarestriccin,sefacilitanenformadetabla.

El siguiente cdigo aade una restriccin entre el DataTable Facturas y el DataTableFilasFactura, para que la
eliminacindeunafacturaconllevelaeliminacindetodassusfilas.

fkFact_LineasFact = New ForeignKeyConstraint("FK_FACT_LINEASFACT",

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
ds.Tables("Facturas").Columns("Numero"),
ds.Tables("LineasFactura").Columns("NumFact"))
fkFact_LineasFact.AcceptRejectRule = AcceptRejectRule.Cascade
fkFact_LineasFact.DeleteRule = Rule.Cascade
ds.EnforceConstraints = True

c.AgregarrelacionesentrelosDataTables

En un DataSet que contiene varios DataTable, puede aadir relaciones entre los DataTable. Estas relaciones
permiten la navegacin entre las filas de los diferentes DataTable. Se debe crear una instancia de la clase
DataRelation y agregar a la coleccin Relations del DataSet. La creacin se puede hacer directamente con el
mtodoAdddelacoleccinDataRelations.Lainformacinquesedebefacilitares:

l ElnombredelarelacinquepermiteencontrarlaDataRelationenlacoleccin.

l ElDataColumnolosDataColumnpadresenformadeunatabladeDataColumnsihaymuchos.

l ElDataColumnolosDataColumnhijosenformadeunatablasihaymuchos.

ElcdigosiguienteaadeunarelacinentrelatablaCustomersylatablaOrders:

ds.Relations.Add("Cliente_Pedidos", ds.Tables("Customers").
Columns ("CustomerId"),
ds.Tables("Orders").Columns("CustomerId"))

Hay que observar que las DataRelation funcionan en paralelo con las ForeignKeyConstaint y las
UniqueConstraint.Pordefecto,lacreacindelarelacincolocarunaUniqueConstraintenlatablapadreyuna
ForeignKeyConstraintenlatablahijo.Sinodeseaqueestasrestriccionesseaadanautomticamentecuandono
existen,usteddebeagregarunboleanofalsecomocuartoparmetroalaadirlaDataRelation.

d.Recorrerlasrelaciones

ElobjetivoprincipaldelasrelacionesconsisteenpermitirlanavegacindeunDataTablehaciaotroenelinterior
deunDataSet.AspodemosobtenertodoslosobjetosDataRowdeunDataTablerelacionadosconunDataRowde
otroDataTable.Porejemplo,despusdecargarlasmatricesCustomersyOrdersenelDataSetyestableceruna
relacinentreestasdostablas,podemos,desdeunafiladelDataTableCustomers,obtenerdelDataTableOrders
todoslospedidosdeestecliente.ElmtodoGetChildRowsdevuelve,enformadetabladeDataRow,todaslasfilas
quecontienenlospedidosdeestecliente.

Este mtodo toma como parmetro el nombre de la DataRelation utilizada para seguir el enlace. El siguiente
ejemplodecdigoaplicatodoello,mostrandoparacadaclienteelnmeroylafechadesuspedidos:

Imports System.Data.SqlClient
Module TestRelaciones
Dim cmdCustomers, cmdOrders As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim daCustomers, daOrders As SqlDataAdapter
Dim filaCliente, filaPedidos As DataRow

Public Sub main()

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ds = New DataSet
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
cmdCustomers = New SqlCommand
cmdCustomers.Connection = ctn
cmdCustomers.CommandText = " SELECT * from Customers"
daCustomers = New SqlDataAdapter()
daCustomers.SelectCommand = cmdCustomers
daCustomers.Fill(ds, "Customers")
cmdOrders = New SqlCommand
cmdOrders.Connection = ctn
cmdOrders.CommandText = " SELECT * from Orders"
daOrders = New SqlDataAdapter()
daOrders.SelectCommand = cmdOrders
daOrders.Fill(ds, "Orders")
ds.Relations.Add("Cliente_Pedidos", ds.Tables("Customers").
Columns ("CustomerId"), ds.Tables("Orders").Columns("CustomerId"))
For Each filaCliente In ds.Tables("Customers").Rows
Console.WriteLine(filaCliente("ContactName"))
For Each filaPedidos In filaCliente.GetChildRows("Cliente_Pedidos")
Console.WriteLine(vbTab & "pedido N {0} del {1}",
filaPedidos ("OrderId"), filaPedidos("OrderDate"))
Next
Next
End Sub
End Module

La navegacin de una fila hijo hacia una fila padre tambin es posible, utilizando el mtodo GetParentRow, que
tambinesperacomoparmetroelnombredelarelacinutilizadacomoenlace.

Elfragmentodecdigosiguientemuestraelnombredelclientequehapasadocadapedido:

For Each lineaPedidos In ds.Tables("Orders").Rows


Console.WriteLine("el pedido {0} lo ha hecho {1}",
lineaPedidos("OrderId"), lineaPedidos.GetParentRow("Cliente_Pedidos")
("ContactName"))
Next

e.EstadoyversionesdeunDataRow

La clase DataRow es capaz de seguir las diferentes modificaciones aportadas a los datos que contiene. La
propiedadRowStatepermitecontrolarlasmodificacionesaportadasalafila.

Paraestapropiedadexistencincoposiblesvaloresdefinidosenunaenumeracin:

Unchanged

LafilanohacambiadodesdeelllenadodelDataSetconelmtodoFillolavalidacindelas
modificacionesconelmtodoAcceptChanges.

Added

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Sehaaadidolafila,perolasmodificacionesannohansidovalidadasporelmtodoAcceptChanges.

Modified

Unoovarioscamposdelafilahansidomodificados.

Deleted

Sehaborradolafila,perolasmodificacionesannohansidovalidadasporelmtodoAcceptChanges.

Detached

Sehacreadolafila,peroannoformapartedelacoleccinRowsdeunDataTable.

Lasdiferentesversionesdeunafilatambinestndisponibles.Cuandoaccedaalosvalorescontenidosenuna
fila,puedeespecificarlaversinqueleinteresa.

Paraello,laenumeracinDataRowVersionproponecuatrovalores:

Current

Versinactualdelafila.EstaversinnoexisteparaunafilacuyoestadoesDeleted.

Default

Versinpordefectodelafila.ParaunafilacuyoestadoesAdded,Modified,Unchanged,esequivalente
alaversinCurrent.ParaunafilacuyoestadoesDeleted,esequivalentealaversinOriginal.Para
unafilacuyoestadoes Detached,esigualalaversinProposed.

Original

Versinoriginaldelafila.ParaunafilacuyoestadoesAdded,noexiste.

Proposed

Versintransitoriadisponibleduranteunaoperacindemodificacindelafilaoparaunafilaqueno
formapartedelacoleccinRowsdeunDataTable.

SedebeespecificarlaversindeseadaduranteelaccesoauncampoparticulardeunDataRow.Paraello,hayque
utilizarunadelasconstantesanteriores,acontinuacindelnombreodelndicedelcampo,durantelautilizacin
delapropiedadItem,pordefecto,delDataRow.

Durante la actualizacin de la base de datos se utilizarn estas distintas versiones para gestionar los accesos

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
concurrentesporejemplo.

f.Agregardatos

SepuedeaadirunafilaaunDataTableagregandosimplementeunDataRowalacoleccinRowsdeunDataTable.
PreviamentehacefaltacrearunainstanciadelaclaseDataRow.Esenestepuntodondeencontramosunproblema.

No hay constructor disponible para la clase DataRow. No es un error de Visual Basic, sino que simplemente no
existe un constructor para esta clase. En efecto, cuando necesitamos una nueva instancia de un DataRow, no
queremos un DataRow cualquiera, sino un DataRow especfico para el esquema de nuestro DataTable. Por esta
raznseleconfaalDataTablelatareadecrearlainstanciaquenecesitamospormediodelmtodoNewRow.

Dim nuevaFila As DataRow


nuevaFila = ds.Tables("Customers").NewRow()

Elestadodeestafilaes,demomento,Detached.Luegopodemosaadirdatosaestanuevafila.

nuevaFila("ContactName") = "Alfonso"

Despus,nosquedaporaadirlafiladelacoleccinRowsdelDataTable.

ds.Tables("Customers").Rows.Add(nuevaFila)

ElestadodeestanuevafilaesahoraAdded.

g.Modificacindedatos

La modificacin de los datos contenidos en una fila se realiza simplemente al asignar a los campos
correspondientes los valores deseados. Estos valores estn almacenados en la versin Current de la fila. El
estado de la fila es entonces Modified. Esta solucin presenta un pequeo inconveniente. Si hay que modificar
varioscamposdeunafila,losestadostransitoriospuedenviolarvariasrestriccionescolocadasenlaDataTable.Es
elcaso,porejemplo,siexisteenlaDataTableunarestriccindeclaveprimariacolocadaendosDataColumn.Esto
tienecomoefectoactivarunaexcepcin.Parapaliaresteproblema,podemospedirtemporalmentelasuspensin
delaverificacindelasrestriccionesparaestafila.Elmtodo BeginEditpasalafilaamodoedicinysuspende
entonces la verificacin de las restricciones para esta fila. Los valores asignados a los campos no estn
almacenadosenlaversinCurrentdelafila,sinoenlaversinProposed.Cuandotodaslasmodificacionessehan
efectuadoenlafila,laspuedevalidarocancelarllamandoalmtodoEndEditoalmtodoCancelEdit.

Tambinpuedeverificarlosvalores,gestionandoeleventoColumnChangeddelDataTable.Enelgestordeeventos,
recibir un argumento del tipo DataColumnChangeEventArg que permite saber qu DataColumn se ha modificado
(args.Column.ColumnName)yelvalorpropuestoparaesteDataColumn(args.ProposedValue)permitiendoanularlas
modificaciones(args.row.CancelEdit).EncasodevalidacinconelmtodoEndEdit,laversinProposeddelafila
se vuelve a copiar en la versin Current y su estado se convierte en Modified. Si por el contrario cancela las
modificaciones con el mtodoCancelEdit, la versinCurrent no se modifica y el estado de la fila no cambia. En

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
todos los casos, despus de la llamada de uno de estos dos mtodos, se reactiva la verificacin de las
restricciones.

Elsiguienteejemplopermitelamodificacindelcdigopostaldeunclienteverificandoqueseanumrico:

Imports System.Data.SqlClient
Module TestModificacionFila
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim codCliente As String
Dim codigoPostal As String
Dim paramCodCliente As SqlParameter
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim WithEvents tabla As DataTable
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial Catalog=
Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
Console.Write("escoger el cdigo del cliente:")
codCliente = Console.ReadLine()
cmd.CommandText = " SELECT * from Customers WHERE CustomerID = @Codigo"
paramcodCliente = New SqlParameter("@Codigo", codCliente)
paramCodigoCliente.Direction = ParameterDirection.Input
cmd.Parameters.Add(paramCodCliente)
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
tabla.Rows(0).BeginEdit()
Console.Write("introducir el nuevo cdigo postal del cliente:")
codigoPostal = Console.ReadLine()
tabla.Rows(0)("PostalCode") = codigoPostal
tabla.Rows(0).EndEdit()
Console.WriteLine("el nuevo cdigo postal es: {0}",
tabla.Rows(0) ("PostalCode"))
Console.ReadLine()
End Sub

Private Sub table_ColumnChanged(ByVal sender As Object, ByVal e


As System. Data.DataColumnChangeEventArgs) Handles table.ColumnChanged
If e.Column.ColumnName = "PostalCode" Then
If Not IsNumeric(e.ProposedValue) Then
e.Row.CancelEdit()
End If
End If
End Sub
End Module

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
h.Eliminardatos

Haydossolucionesdisponibles.Puedeborrarunafilaoeliminarla.Elmatizessutilentreestasdossoluciones:

LaeliminacindeunafilasehaceconelmtodoRemove,queretiradefinitivamenteelDataRowdelacoleccinRows
delDataTable.Estaeliminacinesdefinitiva.

ElmtodoDeletedsolomarcalafilaparaeliminarlaposteriormente.ElestadodelafilapasaaDeletedysoloenel
momentodelavalidacindelasmodificacionesseeliminarrealmentelafiladelacoleccinRowsdelDataTable.Si
secancelanlasmodificaciones,lafilasequedaenlacoleccinRows.

ElmtodoRemoveesunmtododelacoleccinRows(actadirectamenteensucontenido),mientrasqueelmtodo
DeleteesunmtododelaclaseDataRow(solocambiaunapropiedaddelafila).

borra la fila
table.Rows(1).Delete()
elimina la fila
table.Rows.Remove(table.Rows(1))

i.Validarocancelarlasmodificaciones

Hasta ahora, las modificaciones efectuadas en una fila son temporales todava es posible volver a la versin
anterior o, al contrario, validar de manera definitiva las modificaciones en las filas (pero no en la base). Los
mtodos AcceptChanges o RejectChanges permiten respectivamente la validacin o la anulacin de las
modificaciones.SepuedenaplicaraunDataRow individual, unDataTable o unDataSetentero.Cuandoelmtodo
AcceptChangesseejecuta,serealizanlassiguientesacciones:

l ElmtodoEndEditesllamadoimplcitamenteparalafila.

l Sielestadodelafilaera AddedoModified,seconvierteenUnchangedylaversinCurrentsevuelveacopiaren
laversinOriginal.

l SielestadodelafilaeraDeleted,seeliminalafila.

ElmtodoRejectChangesejecutalassiguientesacciones:

l ElmtodoCancelEditesllamadoimplcitamenteparalafila.

l SielestadodelafilaeraDeletedoModified,seconvierteenUnchangedylaversinOriginalsevuelveacopiar
enlaversinCurrent.

l SielestadodelafilaeraAdded,seeliminalafila.

Si existen restricciones de clave exterior, la accin del mtodo AcceptChangeso RejectChanges se propaga a las
filashijosenfuncindelapropiedadAcceptRejectRuledelarestriccin.

j.Filtraryordenardatos

A menudo es necesario limitar la cantidad de datos visibles en un DataTable o incluso modificar el orden de las
filas. La primera solucin que viene a la mente consiste en crear una consulta SQL con una restriccin o una
clusula ORDER BY. Pero eso es olvidar que estamos en un modo de funcionamiento desconectado y que es
deseablelimitarlosaccesosalabasededatosoinclusopuedeserquelabasenoestdisponible.Porlotanto
solodebemosutilizarlosdatosdisponibles,teniendocuidadodenoperderlos.LaclaseelDataViewnosvaaser

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
muy til para solucionar nuestros problemas, ya que nos va a servir para modificar la visin de los datos en el
DataTable sin riesgo para los propios datos. Puede haber varios DataView para un mismo DataTable, que
correspondenapuntosdevistadiferentesdelDataTable.Prcticamentetodaslasoperacionesrealizablesenun
DataTablesepuedenefectuaratravsdeun DataView.

HaydossolucionesdisponiblesparaobtenerunaDataView:

l Crearunainstanciagraciasaunodelosconstructores.

l UtilizarlainstanciapordefectofacilitadaporlapropiedadDefaultView.

El primer constructor utilizable espera como parmetro el DataTable a partir del cual se genera el DataView. En
estecaso,nohayningnfiltronitampocoordenacinefectuadaenlosdatosvisiblesporelDataView.Seobtiene
unresultadoequivalentealutilizarlapropiedadDefaultViewdeunDataTable.

EL segundo constructor permite especificar un filtro, un orden de ordenacin y la versin de las filas afectadas.
Paraservisiblesenel DataView,lasfilasdeberncumplirtodosestoscriterios.Tambinsepuedenmodificarlos
diferentescriterioscontrespropiedades.

RowFilter

Estapropiedadaceptaunacadenadecaracteresquerepresentalacondicinquesedebecumplirparaqueuna
fila sea visible. Esta condicin tiene una sintaxis muy parecida a las condiciones de una clusula WHERE. Los
operadoresAndyOrpuedenutilizarseparaasociarvariascondiciones.

ElsiguienteejemplovisualizaelnombredelosclientescomercialesodirectoresdeventasenEspaa:

Imports System.Data.SqlClient
Module TestDataView
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRowView
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers"
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
tabla.DefaultView.RowFilter = "Country=Espaa and
(contactTitle=Sales Agent or contactTitle=Sales Manager)"
For Each fila In tabla.DefaultView
Console.WriteLine("nombre: {0}", fila("ContactName"))
Next
End Sub

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
End Module

SepuedecancelarunfiltroasignandounacadenavacaalapropiedadRowFilter.

Sort

Estapropiedadaceptatambinunacadenadecaracteresquerepresentaelcriteriooloscriteriosutilizadospara
laordenacin.LasintaxisesequivalentealadelaclusulaORDER BY.

Elsiguienteejemplomuestralosclientesordenadosporpasy,dentrodelmismopas,pornombre:

anulamos el filtro anterior


tabla.DefaultView.RowFilter = ""
todas las filas son ahora visibles
se aade un criterio de ordenacin
tabla.DefaultView.Sort = "Country ASC,ContactName ASC"
For Each fila In tabla.DefaultView
Console.WriteLine("Pas: {0}" & vbTab & vbTab & " nombre : {1}",
fila("Country"), fila("ContactName"))
Next

RowStateFilter

Esta propiedad determina el estado de las filas y qu versin de la fila es visible en el DataView. Existen ocho
posibilidades:

CurrentRows

PresentalaversinCurrentdetodaslasfilasaadidas,modificadasono.

Added

PresentalaversinCurrentdetodaslasfilasaadidas.

Deleted

PresentalaversinOriginaldetodaslasfilasborradas.

ModifiedCurrent

PresentalaversinCurrentdetodaslasfilasmodificadas.

ModifiedOriginal

PresentalaversinOriginaldetodaslasfilasmodificadas.

None

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Ningunafila.

OriginalRows

PresentalaversinOriginaldetodaslasfilasmodificadas,eliminadasonomodificadas.

Unchanged

PresentalaversinCurrentdetodaslasfilasnomodificadas.

Elsiguienteejemploeliminadosfilasylasmuestraatravsdeunfiltro:

se eliminan dos filas


table.Rows(2).Delete()
table.Rows(5).Delete()
se anula el filtro
tabla.DefaultView.RowFilter = ""
se muestra la versin original de las filas eliminadas
tabla.DefaultView.RowStateFilter = DataViewRowState.Deleted
For Each fila In tabla.DefaultView
Console.WriteLine("Pas: {0}" & vbTab & vbTab & " nombre : {1}",
fila("Country"), fila("ContactName"))
Next

k.Buscardatos

La bsqueda se puede realizar con los dos mtodosFind y FindRows. Para que funcionen, es obligatorio haber
ordenadolosdatosconlapropiedadSort.

Find

Este mtodo devuelve el ndice de la primera fila correspondiente al criterio de bsqueda. Si no se encuentra
ningunafila,estemtododevuelve1.Recibecomoparmetroelvalorbuscado.Estevalorsebuscaenelcampo
utilizado como criterio de ordenacin. Si el criterio de ordenacin est compuesto por muchos campos, es
necesariopasaralmtodoFindunamatrizdeobjetosquecontengalosvaloresbuscadosparacadacampodel
criteriodeordenacinenelordendeaparicinenlapropiedadSort.

Estemtodoseusaamenudoparabuscarunafilaapartirdelaclaveprimaria.

Imports System.Data.SqlClient
Module TestFind
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRowView
Dim codCliente As String
Dim indice As Integer

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog= Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers"
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
Console.Write("escoger el cdigo de cliente: ")
codCliente = Console.ReadLine()
tabla.DefaultView.Sort = "CustomerID ASC"
indice = tabla.DefaultView.Find(codigoCliente)
If indice = -1 Then
Console.WriteLine("no existen clientes con este cdigo")
Else
Console.WriteLine("el cdigo {0} corresponde al cliente {1}",
codCliente, tabla.DefaultView(indice)("ContactName"))
End If
Console.ReadLine()
End Sub
End Module

FindRows

Este mtodo busca todas las filas que cumplen el criterio de bsqueda y las devuelve en forma de tabla de
DataRowView.

Elsiguientecdigobuscatodoslosclientesdeunpasydeunaciudaddeterminados:

Imports System.Data.SqlClient
Module TestFindRows
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRowView
Dim pais, ciudad As String
Dim filasEncontradas() As DataRowView
Dim criterios() As Object

Public Sub main()


ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers"

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Clientes")
tabla = ds.Tables("Clientes")
Console.Write("escoger el pas: ")
pais = Console.ReadLine()
Console.Write("escoger la ciudad: ")
ciudad = Console.ReadLine()
tabla.DefaultView.Sort = "Country ASC,City ASC"
criterios = (New Object() {pais, ciudad})
filasEncontradas = tabla.DefaultView.FindRows(criterios)
If filasEncontradas.Length = 0 Then
Console.WriteLine("no existen clientes que cumplan
los criterios")
Else
Console.WriteLine("los siguientes clientes cumplen
los criterios")
For Each fila In filasEncontradas
Console.WriteLine("Nombre:{0}", fila("ContactName"))
Next
End If
Console.ReadLine()
End Sub
End Module

4.Actualizarlabasededatos

Todo el trabajo realizado en los datos con los mtodos vistos hasta ahora se pierde inevitablemente cuando se
cierralaaplicacin,sinolosguardamos.

En la mayora de los casos, los datos vienen de una base de datos, por lo que hay que actualizarla con las
modificacionescontenidasenunDataSet,unDataTableounDataRowElDataAdaptersehautilizadopararellenarel
DataSet.Selevolverallamarparaactualizarlabasededatos.

ComoelmtodoFill,elmtodoUpdateutilizarinstruccionesSQLparaeldilogoconlabasededatos.Enfuncin
delasnecesidades,utilizarlainstruccincontenidaenelcomandoInsertCommand,UpdateCommandoDeleteCommand.
Si el mtodo Update necesita un comando y este no est disponible, se genera una excepcin. El mtodo Fill
navegaporlasfilasdelDataTablequedebeactualizary,enfuncindelestadodelafila(Added,Deleted,Modified),
llamaacomandoInsertCommand,DeleteCommandoUpdateCommand.Elordenenqueserealizanlasactualizacionesen
la base de datos puede ser importante. Para controlar el orden de ejecucin de las inserciones, modificaciones y
eliminaciones, puede pasar por tres fases, proponindole al mtodo Update solo una serie limitada de filas para
actualizar. Por ejemplo, puede seleccionar solo las filas borradas y pedir la actualizacin de la base con este
conjuntodefilas,paraluegoprocederdelamismamaneraconlasfilasmodificadasylasaadidas.

Elmtodo SelectpermiteobtenerunatabladeDataRowcorrespondienteauncriterioespecfico.Esestatablade
DataRowlaquesepasacomoparmetroalmtodoUpdate.

Elsiguienteejemplorealizalaseliminacionesylasmodificaciones,ydespuslasinsercionesenlabasededatos.

Dim filas() As DataRow


recupera las filas eliminadas y solicita la actualizacin
de la base de datos

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
filas = table.Select(Nothing, Nothing, DataViewRowState.Deleted)
da.Update(tabla)
recupera las filas modificadas y solicita la actualizacin
de la base de datos
filas = table.Select(Nothing, Nothing, DataViewRowState.
ModifiedCurrent)
da.Update(tabla)
recupera las filas aadidas y solicita la actualizacin
de la base de datos
filas = table.Select(Nothing, Nothing, DataViewRowState.Added)
da.Update(tabla)

Este ejemplo da por supuesto que los comandos InsertCommand, DeleteCommand, UpdateCommand se han
definidoanteriormente.

a.Generacinautomticadecomandos

Los comandos que se ocupan de la actualizacin de la base pueden generarse automticamente con un objeto
SqlCommandBuilder.Paraquefuncionecorrectamente,elSqlCommandBuildernecesitaque:

l Lapropiedad SelectCommandseadefinidaporelDataAdapter,porqueapartirdeestainstruccinSQLgenerarlas
instruccionesINSERT,UPDATE,DELETE.

l LaclaveprimariaestdisponibleenelDataTable.

l Losdatosnovengandeunafusindemuchastablas.

Sinoserespetanunaomsdeestascondiciones,seproducelaactivacindeunaexcepcincuandosegeneran
loscomandos.

Loscomandossegeneranrespetandolossiguientescriterios:

InsertCommand

InsertaunafilaenlabasededatosparatodaslasfilascuyoestadoesAdded.Todosloscampos,entreellosel
campoidentidad,expresinoTimeStamp,seactualizan.

UpdateCommand

ActualizaenlabasededatostodaslasfilascuyoestadoesModified.Todosloscamposseactualizan,exceptolos
camposidentidad,expresinoTimeStamp.Lafilaquesedebeactualizarsebuscaenlabaseconlaclaveprimaria,
peroesnecesarioquelosvaloresdelosotroscamposenlabasededatossecorrespondanalaversinOriginal
delcampoenelDataRow.

DeleteCommand

Borradelabasededatostodaslasfilascuyoestadoes Deleted.Esnecesarioquelosvalorespresentesenla
basededatoscorrespondanalaversinOriginaldeloscamposenelDataRow.Loscomandosgeneradosestn
disponiblesatravsdelosmtodosGetInsertCommand,GetUpdateCommand,GetDeleteCommand.

El siguiente ejemplo muestra las instrucciones SQL de los tres comandos generados automticamente para la

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 19 -
tablaCustomers:

Imports System.Data.SqlClient
Module TestOrdenPADBase
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRowView
Dim codCliente As String
Dim indice As Integer
Dim bldr As SqlCommandBuilder
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=true"
ctn.Open()
cmd = New SqlCommand
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers"
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Customers")
tabla = ds.Tables("Customers")
bldr = New SqlCommandBuilder(da)
Console.WriteLine("Instruccin SQL de UpdateCommand: {0}",
bldr.GetUpdateCommand.CommandText)
Console.WriteLine("Instruccin SQL de InsertCommand: {0}",
bldr.GetInsertCommand.CommandText)
Console.WriteLine("Instruccin SQL de DeleteCommand: {0}",
bldr.GetDeleteCommand.CommandText)
End Sub
End Module

Estecdigomuestralasiguienteinformacin:

Instruccin SQL de UpdateCommand : UPDATE [Customers] SET [CustomerID] =


@p1, [CompanyName] = @p2, [ContactName] = @p3, [Contact- Title] =
@p4, [Address] = @p5, [City] = @p6, [Region] = @p7, [PostalCode] = @p8,
[Country] = @p9, [Phone]= @p10, [Fax] = @p11 WHERE (([CustomerID] =
@p12) AND ([CompanyName] = @p13) AND ((@p14 = 1 AND [ContactName] IS
NULL) OR ([ContactName] = @p15)) AND ((@p16= 1 AND [ContactTitle] IS
NULL) OR ([ContactTitle] = @p17)) AND ((@p18 = 1 AND [Address] IS NULL)
OR ([Address] = @p19)) AND ((@p20 = 1 AND [City] IS NULL) OR
([City] = @p21)) AND ((@p22 = 1 AND [Region] IS NULL) OR ([Region] =
@p23)) AND ((@p24 = 1 AND [PostalCode] IS NULL) OR ([PostalCode] =
@p25)) AND ((@p26 = 1 AND [Country] IS NULL) OR ([Country] = @p27))
AND ((@p28 = 1 AND [Phone] IS NULL) OR([Phone] = @p29)) AND ((@p30 =
1 AND [Fax] IS NULL) OR ([Fax] = @p31)))
Instruccin SQL de InsertCommand : INSERT INTO [Customers]
([CustomerID], [CompanyName], [ContactName], [ContactTitle], [Address],

- 20 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
[City], [Region], [PostalCode], [Country], [Phone], [Fax]) VALUES
(@p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10, @p11)
Instruction SQL de DeleteCommand : DELETE FROM [Customers] WHERE
(([CustomerID] = @p1) AND ([CompanyName] = @p2) AND ((@p3 = 1 AND
[ContactName] IS NULL) OR ([ContactName] = @p4)) AND ((@p5 = 1 AND
[Contact- Title] IS NULL) OR ([ContactTitle] = @p6)) AND ((@p7 = 1 AND
[Address] IS NULL) OR ([Address] = @p8))AND ((@p9 = 1 AND [City] IS
NULL) OR ([City] = @p10)) AND ((@p11 = 1 AND [Region] IS NULL) OR
([Region] = @p12)) AND ((@p13 = 1 AND [PostalCode] IS NULL)OR
([PostalCode] = @p14)) AND ((@p15 = 1 AND [Country] IS NULL)
OR ([Country] = @p16)) AND ((@p17 = 1 AND [Phone] IS NULL)OR ([Phone]
= @p18)) AND ((@p19 = 1 AND [Fax] IS NULL) OR ([Fax] = @p20)))

Laverdadesquenodicemucho...

Enelprrafodedicadoalosaccesosconcurrentesvamosaaclararlapresenciadeesosinnumerablesparmetros
en estas tres instrucciones de SQL. Lo importante, por el momento, es que esas instrucciones realicen
correctamentelaactualizacindelabasededatos.

Lo verificaremos realizando una insercin, una modificacin o una eliminacin en la tabla Customers de clientes
franceses.Veamoselestadodelatablaantesderealizarnuestrasmodificaciones.

Ejecutamosdespuselcdigosiguiente:

Imports System.Data.SqlClient
Module TestOrdenPADBase
Dim cmd As SqlCommand
Dim ctn As SqlConnection
Dim ds As DataSet
Dim da As SqlDataAdapter
Dim tabla As DataTable
Dim fila As DataRow
Dim bldr As SqlCommandBuilder
Public Sub main()
ctn = New SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
ctn.Open()
cmd = New SqlCommand

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 21 -
cmd.Connection = ctn
cmd.CommandText = " SELECT * from Customers where country=France"
ds = New DataSet
da = New SqlDataAdapter(cmd)
da.Fill(ds, "Custmers")
tabla = ds.Tables("Customers")
borra Frdrique Citeaux
tabla.Rows(7).Delete()
cambia direccin Carine Schmitt
tabla.Rows(4)("Address") = "9 rue Benjamin Franklin"
aade un nuevo cliente
fila = tabla.NewRow
fila("CustomerID") = "ENIEC"
fila("CompanyName") = "Eni Ecole Informatique"
fila("ContactName") = "Marcel Dupond"
fila("ContactTitle") = "Manager"
fila("Address") = "24 rue Crbilon"
fila("Country") = "France"
fila("City")="Nantes"
tabla.Rows.Add(fila)
bldr = New SqlCommandBuilder(da)
da.Update(table)
End Sub
End Module

ComparemosahoraelcontenidoactualdelatablaCustomersconelanterior,paraverificarquelasmodificaciones
sehanrealizadocorrectamente.

b.Utilizacindecomandospersonalizados

Lautilizacindecomandospersonalizadospermiteelegireltipodeaccinrealizadadurantelaactualizacindela
basededatos.Porejemplo,lacancelacindeunafilasepuedetraducirenlaasignacindeunvalorespecialaun
campodelregistro.Enesecaso,lainstruccinSQLejecutadaenlaDeleteCommandserunainstruccinUPDATE,y
nounainstruccinDELETE.

Porejemplo,elsiguientecdigocreauncomandopersonalizadoparalaeliminacin:

delCmd = New SqlCommand


delCmd.Connection = ctn

- 22 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
delCmd.CommandText = " UPDATE Customers set Archive=1 where CustomerID=@num"
codCliente = New SqlParameter("@num", SqlDbType.NChar, 5,
ParameterDirection.
Input, False, Nothing, Nothing, "CustomerID", DataRowVersion.Current,
Nothing)
delCmd.Parameters.Add(codCliente)
da.DeleteCommand = delCmd
bldr = New SqlCommandBuilder(da)

Los comandos personalizados son compatibles con los comandos generados automticamente por el
SqlCommandBuilder, ya que este solo genera un comando si la propiedad InsertCommand, DeleteCommand o
UpdateCommand es igual a nothing en el DataAdapter. Si existe un comando, no se sustituye con el
SqlCommandBuilder.

c.Gestindeaccesosconcurrentes

Enunentornomultiusuario,existendostcnicasparalagestindelasactualizaciones:laproteccinoptimistayla
proteccinpesimista.

La proteccin pesimista es la ms apremiante para los usuarios, porque, para evitar los conflictos durante las
modificacionesdelabase,cuandounusuariodecidemodificarunregistro,esteseprotegeenlabasededatos.En
tantonoseacabelamodificacindelregistro,laproteccinsemantieneactiva,bloqueandoaselaccesodelos
otrosusuarios.Lafinalidaddeestasolucinesevitarlaaparicindeconflictos.

La proteccin optimista no es una verdadera proteccin, porque los registros estn prcticamente siempre
disponibles. Durante la actualizacin se realiza un test para verificar si los datos presentes en la base son
idnticosalosdatosutilizadospararellenar elDataSet.Silosdatossondiferentes,significaqueotrousuariolos
ha modificado entre el rellenado del DataSet y la solicitud de actualizacin de la base de datos. Conviene, por
tanto,tomarunadecisinacercadelasactualizaciones.

Haytressoluciones:

l Seabandonanlasactualizaciones.

l Sesuprimelaversinexistente.

l Selepidealusuarioquesloqueprefiere.

Estasolucinpuedeaplicarsemediantedostcnicas.

LaprimeraesutilizarenlatablauncampodeltipoTimeStamp.Laparticularidaddeestetipodecampoesque
tiene un valor que cambia automticamente con cada modificacin realizada en el registro. As que es suficiente
compararelvalorpresenteenlabaseconelvalorpresenteenelDataSet.Sihaydiferencias,esquelabaseha
sidomodificadadesdequesehacargadoelDataSet.

Paraqueestasolucinseaviable,labasededatosdebesercapazdegestionarestetipodecampo.Estasolucin
aumenta tambin el volumen de datos, ya que, por ejemplo, para SQL Server este tipo de campo utiliza ocho
bytes.

Lasegundasolucinconsisteengestionartodoestoaniveldelaaplicacin,manteniendolosdatosoriginalesy
comparndolosconlosdatospresentesenlabaseenelmomentodelaactualizacin.Estaeslasolucinutilizada
enloscomandosgeneradosautomticamenteporelobjetoSqlCommandBuilder.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 23 -
Vamosaanalizarelcdigodeunaconsultademodificacingeneradaporesteobjeto.

UPDATE [Customers] SET [CustomerID] = @p1, [CompanyName] = @p2,


[ContactName] = @p3, [ContactTitle] = @p4, [Address] = @p5, [City] = @p6,
[Region] = @p7, [PostalCode] = @p8, [Country] = @p9, [Phone] = @p10,
[Fax] = @p11 WHERE (([CustomerID] = @p12) AND ([CompanyName] = @p13) AND
((@p14 = 1 AND [ContactName] IS NULL) OR ([ContactName] = @p15))AND
((@p16 = 1 AND [ContactTitle] IS NULL) OR ([ContactTitle] = @p17)) AND
((@p18 = 1 AND [Address] IS NULL) OR ([Address] = @p19)) AND ((@p20 = 1
AND [City] IS NULL) OR ([City] = @p21)) AND ((@p22 = 1 AND [Region] IS NULL)
OR ([Region] = @p23)) AND ((@p24 = 1 AND [PostalCode] IS NULL) OR
([PostalCode] = @p25)) AND((@p26 = 1 AND [Country] IS NULL) OR ([Country] =
@p27)) AND ((@p28 = 1 AND [Phone] IS NULL) OR ([Phone] = @p29)) AND
((@p30 = 1 AND [Fax] IS NULL) OR ([Fax] = @p31)))

Estecomandoutilizaunnmeroenormedeparmetros:exactamentetreintayuno.Vamosaintentarexplicarel
roldecadaunodeellos.

Losparmetrosde@p1a@p11seutilizanparaespecificarlosnuevosvaloresdelregistro.

Elparmetro@p12seutilizaparaidentificarelregistroquesequiereactualizarrealizandounmapeoenlaclave
primaria.

Losdemsparmetrossolosirvenparalagestindelaproteccinoptimista.Paracadacampo,severificaquelos
datospresentesenlabaseseanidnticosalosdatosdelDataSet.Paraloscamposquenoautorizanlosvalores
nulos,laverificacinesmuysencilla.EselcasodelcampoCompanyName,quesecomparaconelparmetro@p13.

Para los campos que autorizan los valores nulos, hay que utilizar un pequeo truco. Efectivamente, es posible
verificarsiuncampoesnuloonoloesenlabasededatos,peronopuedecompararseconelvalor Null.Para
paliar esta limitacin, se utilizan los parmetros @p14, @p16, @p18, @p20, @p22, @p24, @p26, @p28 y @p30
pararepresentarelvalorNullparauncampoenelDataSet.Sisuvaloresiguala1,significaqueelcampoesigual
aNullenelDataSet.EltestdelvalordeestosparmetrossecombinaconeloperadorAndparaverificarlanulidad
simultneadelcampocorrespondienteenlabasededatos.Durantelaejecucindelcomando,losparmetrosse
sustituyenconlosvalorespresentesenelDataSet.Enfuncindelparmetro,seutilizanversionesdistintasdela
fila.

Paralosparmetros@p1a@p11,seutilizanlasversionesCurrent.Setratadelosdatosquesequierentransferir
alabasededatos.Paralosotrosparmetros,seutilizanlasversionesOriginaldelosparmetros.

Laversindelafilaquesevaautilizarsedeterminaenelmomentodelacreacindelparmetro,antesdequese
aadaalacoleccinParameters.Parahacerlo,seutilizaelsiguienteconstructor:

Public Sub New (parameterName As String, dbType As SqlDbType, ,size As


Integer, direction As ParameterDirection, isNullable As Boolean,
precision
As Byte, scaleAs Byte, sourceColumn As String, sourceVersion As
DataRowVersion, value As Object )

Permite asociar automticamente una versin de un campo especfico a un parmetro. Es el papel de los
parmetrossourceColumnysourceVersion.Laejecucindelcomandodevuelveelnmeroderegistrosrealmente
actualizados. Si el comando no puede actualizar los campos, el valor devuelto por la ejecucin del comando es

- 24 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
igualacero.Enestecaso,seactivaunaexcepcin:

Unasolucinmenosradicalpermitecontrolarlasactualizacionesamedidaquesevanejecutandolasinstrucciones
SQL. Para ello hay que gestionar el eventoRowUpdated delDataAdapterqueseactivadespusdelallamadade
cadaInsertCommand,DeleteCommand,UpdateCommand.ElparmetrodeltipoRowUpdatedEvent Argspermitesaberpor
lapropiedadRecordsAffectedcuntosregistrossehanactualizado.

Sinosehaactualizadoninguno,puedeelegirlaaccinqueesprecisoemprendermodificandolapropiedadStatus
conunodelosvaloresdelaenumeracinUpdateStatus:

Continue

Laactualizacinsiguecomosinohubierapasadonada.

ErrorsOccurred

Sevaaactivarunaexcepcin.

SkipAllRemainingRows

Interrupcindelaactualizacindelasfilasrestantes.

SkipCurrentRow

Interrupcindelaactualizacindelafilaactual.Laactualizacincontinaconlasfilasrestantes.

Enprincipio,eltipodeaccinqueesprecisoemprenderdebeelegirlaelusuario,comoenelsiguienteejemplo:

Private Sub da_RowUpdated(ByVal sender As Object, ByVal e As System.Data.


SqlClient.SqlRowUpdatedEventArgs) Handles da.RowUpdated
Dim respuesta As Integer
If e.RecordsAffected = 0 Then
Console.WriteLine("Se ha producido un error durante la
actualizacin de la base de datos")
Console.WriteLine("seleccione una opcin:")

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 25 -
Console.WriteLine("1 - continuar con las actualizaciones")
Console.WriteLine("2 - anular las actualizaciones")
Console.WriteLine("3 - anular la actualizacin de esta fila pero
continuar con las otras filas")
respuesta = Console.ReadLine()
Select Case respuesta
Case 1
e.Status = UpdateStatus.Continue
Case 2
e.Status = UpdateStatus.SkipAllRemainingRows
Case 3
e.Status = UpdateStatus.SkipCurrentRow
End Select
End If
End Sub

5.Lastransacciones

LastransaccionespermitenrecogerenunaentidadunconjuntodecomandosSQL.Esteconjuntogarantizarque,
siunadelasinstruccionescontenidasenlatransaccinfalla,labasededatospodrvolveraencontrarsuestado
inicial. El tpico ejemplo es la transferencia desde una cuenta bancaria a otra. Imagine que tiene en su base de
datosunatablaparalascuentasdeparticularesyunatablaparalascuentasdeempresas.

Latransferenciadeunacuentadeempresahaciaunacuentaparticular(elpagodesunmina)sepodrrealizar
conlassiguientesinstrucciones:

Imports System.Data.SqlClient
Module TestTransaction
Dim cmdPart, cmdEmp As SqlCommand
Dim ctn As SqlConnection
Dim numParticular, numEmpresa, cantidadPart, cantidadEmp As SqlParameter
Public Sub main()
ctn = New SqlClient.SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind; Integrated Security=true"
ctn.Open()
cmdEmp = New SqlClient.SqlCommand
cmdEmp.Connection = ctn
cmdEmp.CommandText = "Update CuentasEmpresa set saldo=
saldo-@cantidad where numCuenta=@numCuenta"
numEmpresa = New SqlParameter("@numCuenta", SqlDbType.Int)
numEmpresa.Value = 1234
cmdEmpr.Parameters.Add(numEmpresa)
cantidadEmp = New SqlParameter("@cantidad", SqlDbType.Decimal)
cantidadEmp.Value = 3000
cmdEmp.Parameters.Add(cantidadEmp)
cmdEmp.ExecuteNonQuery()
cmdPar = New SqlClient.SqlCommand
cmdPar.Connection = ctn
cmdPar.CommandText = "Update CuentasParticulares set saldo=
saldo+@cantidad where numCuenta=@numCuenta"
numParticular = New SqlParameter("@numCuenta", SqlDbType.Int)

- 26 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
numParticular.Value = 5678
cmdPart.Parameters.Add(numParticular)
cantidadPart = New SqlParameter("@cantidad", SqlDbType.Decimal)
cantidadPart.Value = 3000
cmdPart.Parameters.Add(cantidadPart)
cmdPart.ExecuteNonQuery()
ctn.Close()
End Sub

End Module

Qupasarasidurantelaejecucindeesecdigoelservidordebasededatosnoestuvieradisponibledebido,por
ejemplo,aunproblemadered?Laoperacindedbitopuedehaberserealizado,mientrasqueladecrditopuede
quenosehayarealizadocorrectamente.Existeporlotantoelriesgodequeseproduzcaungranproblemaenel
funcionamientodelaaplicacin(yparaelpagodesunmina).Lastransaccionespermitirnresolveresteproblema,
recogiendolaejecucindeinstruccionesSQLparagarantizarqueseejecutentodasoquenoseejecuteninguna.

Lastransaccionessegestionananiveldelaconexin,queeslaquenospermitirponerenmarchalatransaccin.
El mtodo BeginTransaction nos devuelve una instancia de la clase SqlTransaction. Para cada ejecucin de
comando,podemosindicarsilaejecucindeberealizarseenelcontextodelatransaccinofueradel.Alfinaldel
tratamiento, podemos validar todas las instrucciones de la transaccin o, al revs, anularlas todas. El mtodo
Commitvalidalatransaccin,mientrasqueelmtodoRollBacklaanula.

Paraasegurarelcdigoanterior,podramosutilizarlasiguienteversin:

Imports System.Data.SqlClient
Module TestTransaction
Dim cmdPart, cmdEmp As SqlCommand
Dim ctn As SqlConnection
Dim numParticular, numEmpresa, cantidadPart, cantidadEmp As SqlParameter
Dim trans As SqlTransaction
Public Sub main()
ctn = New SqlClient.SqlConnection()
ctn.ConnectionString = "Data Source=localhost;Initial
Catalog=Northwind;Integrated Security=true"
ctn.Open()
trans = ctn.BeginTransaction
Try
cmdEmp = New SqlClient.SqlCommand
cmdEmp.Connection = ctn
cmdEmp.CommandText = "Update CuentasEmpresa set saldo=saldo-
@cantidad where numCuenta=@numCuenta"
numEmpresa = New SqlParameter("@numCuenta", SqlDbType.Int)
numEmpresa.Value = 1234
cmdEmp.Parameters.Add(numEmpresa)
cantidadEmp = New SqlParameter("@cantidad", SqlDbType.Decimal)
cantidadEmp.Value = 3000
cmdEmp.Parameters.Add(cantidadEmpr)
ponemos la ejecucin del comando dentro de una transaccin
cmdEmp.Transaction = trans
cmdEmp.ExecuteNonQuery()
cmdPart = New SqlClient.SqlCommand
cmdPart.Connection = ctn

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 27 -
cmdPart.CommandText = "Update CuentasParticulares set saldo=saldo+
@cantidad where numCuenta=@numCuenta"
numParticular = New SqlParameter("@numCuenta", SqlDbType.Int)
numParticular.Value = 5678
cmdPart.Parameters.Add(numParticular)
cantidadPart = New SqlParameter("@cantidad", SqlDbType.Decimal)
cantidadPart.Value = 3000
cmdPart.Parameters.Add(cantidadPart)
cmdPart.Transaction = trans
cmdPart.ExecuteNonQuery()
trans.Commit()
Catch ex As Exception
trans.Rollback()
Console.WriteLine("todas las operaciones han sido anuladas")
End Try
ctn.Close()
End Sub
End Module

Si se interrumpe la conexin, la instruccin RollBack o Commit no podr encaminarse hacia el servidor. En este
caso,elservidortomalainiciativadeejecutarunRollBackentodaslastransaccionesencurso.

- 28 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Introduccin

Despusdemuchosaosdeevolucin,loslenguajesorientadosaobjetossehanhechoineludibleseneldesarrollo
informtico. De manera paralela, los sistemas de almacenamiento tambin han evolucionado sobre dos ejes: las
bases de datos y los archivos XML. La cohabitacin entre los objetos y los datos ha sido ms o menos mejorada
aadiendoaloslenguajesorientadosaobjetoslacapacidadparadialogarconlosdatos.Sinembargo,estasolucin
noesdeltodosatisfactoria,yaquepresentalasdesventajassiguientes:

l Ellenguajeutilizadoparamanipularlosdatossuelesermuyespecficodeuntipodefuentededatos.

l Las palabras claves de este lenguaje son desconocidas para el lenguaje de programacin, que las considera como
simplescadenasdecaracteresportanto,nohayunaverificacinsintcticaantesdelaejecucin.

l Elcambiodetipodefuentededatosconllevaimportantesmodificacionesdelcdigoyunnuevoperiododeaprendizaje
paraeldesarrollador.

l Los tipos de datos a veces son incompatibles entre el lenguaje de programacin y la fuente de datos. En este caso,
hacerlasconversionesamenudoexigetiempoy,aveces,setornanpeligrosas.

ConLINQtodoestoseconvierteenmalosrecuerdos.Peroquseescondedetrsdeestascuatroletras: Language
Integrated Query o lenguaje de consulta integrado? Se trata de un lenguaje de consulta que permite interrogar
fuentesdedatos,peroquemsofrececonrespectoalbuenodeSQL?Laclavedelmisteriosesitaeneltrmino
integrado. En efecto, a diferencia de otros mtodos utilizados para interrogar fuentes de datos (SQL, XPATH),
LINQformapartedellenguajeenelquesedesarrollala aplicacin (VB,C#).Otropuntomuyimportanterelativoa
LINQresideenlapropiasintaxisdellenguaje.Estaserlamisma,independientementedeltipodefuentededatos
consultado:tabla,coleccin,basededatos,archivoXML,dataset...Elltimopuntoimportantedeestapresentacin
deLINQserefierealosdatosmanipulados.Laaplicacinestdesarrolladaconunlenguajeorientadoaobjetos,y
resulta que LINQ tambin manipula objetos. As, no es necesario realizar manualmente las operaciones de
conversin.Sisonnecesarias,LINQlasrealizarautomticamente.Despusdeestebrevevistazo,veamosahorala
sintaxisdeLINQ.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
SintaxisdellenguajeLINQ

Antes de detallar la sintaxis de LINQ, vamos a estudiar un primer ejemplo muy sencillo. En los ejemplos de este
captulo, utilizaremos como fuente de datos dos listas, completadas con instancias de las clases del siguiente
diagrama.

Los datos utilizados para crear estas instancias de clase son extrados de la base de datos Northwind. Estn
ubicadosenunarchivodetextoqueelcdigoleeparacrearlasinstanciasdeclaseenmemoria.Acontinuacinest
elextractodecdigoquepermiterealizarestasoperaciones.

Dim listaPedidos As List(Of Pedido)


Dim listaClientes As List(Of Cliente)
Sub Main()
listaPedidos = New List(Of Pedido)
listaClientes = New List(Of Cliente)
Dim co As Pedido
Dim cl As Cliente
Dim f As IO.StreamReader
Dim fila As String
Dim col As String()
Dim nombre As String = ""
f = New IO.StreamReader("c:\data.txt", IO.FileMode.Open)
Do
fila = f.ReadLine
If Not IsNothing(fila) Then

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
col = fila.Split(New Char() {vbTab})
If nombre <> col(0) Then
nombre = col(0)
cl = New Cliente(With {.nombre = col(0),
.direccionFacturacion = New Direccion With {.calle = col(1),ciudad =
col(2),.codigoPostal = col (3)}, .telefono = col(4)
listaClientes.Add(cl)
End If
co = New Pedido() With {.codigoPedido = col(5), .fechaPedido =
col(6), .envio = col(7), .direccionDeEntrega = New Direccion With
{.calle = col(8), .ciudad = col(0), .codigoPostal = col(10)}}
listaPedidos.Add(co)
co.Cliente = cl
cl.Pedidos.Add(co)
End If
Loop Until fila Is Nothing
f.Close()
End Sub

En los siguientes ejemplos, supondremos que esta porcin de cdigo ya ha sido ejecutada para rellenar las dos
listas.Estebocetodeproyectoestdisponibleparasudescargaenelsitiodeleditor.

1.PrimerasconsultasLINQ

Sonnecesariastresetapasparamanipularunaconsulta:

l Laobtencindelosdatos.

l Lacreacindelapropiaconsulta.

l Laejecucindelaconsulta.

Elprimerpasoesmuysencillo:unaclasedebeimplementarlainterfazgenricaIEnumerable(T)paraserutilizada
como una fuente de datos. Es el caso de muchas clases del Framework .NET que son directamente utilizables en
consultasLINQ.

Para las fuentes de datos que no implementan esta interfaz, como por ejemplo un documento XML, hay clases
auxiliaresquepermitenhacerlascompatiblesconLINQ.

Lamayorpartedeltrabajoestconstituidoporlasegundaetapa:lacreacindelapropiaconsulta.

En la consulta, vamos a indicar qu datos deseamos obtener de la fuente de datos, cmo sern ordenados,
agrupadosoestructurados.

Laconsultacontienetresclusulas:

l From:indicaelorigendelosdatos.

l Where:especificalascondicionesquegarantizanquelosdatosseincluyenenlosvaloresderetorno.

l Select:indicalainformacinquesedevuelvedelafuentededatos.

As,presentamosacontinuacinnuestraprimeraconsultaLINQ.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim consulta = From unCliente In listaClientes _
Where unCliente.apellido Like "A*" _
Select unCliente

SesuelealmacenarunaconsultaLINQenunavariableyposteriormenteseejecuta.Esimportanterecordarquela
variablequecontienelaconsultanoejecutaningunaaccinynodevuelveningndato.Simplementealmacenala
definicin de la consulta. La ejecucin de la consulta solo tiene lugar cuando uno se interesa por los datos que
devuelve.EnelsiguienteejemplosemuestracmonavegarporlosresultadosdeunbucleFor Each.

For Each un cliente In consulta


Console.WriteLine(uncliente.apellido)
Next

Este mecanismo permite ejecutar varias veces la misma consulta sin tener que volver a definirla para cada
ejecucin.

Sinembargo,enalgunoscasos,lavariablecontieneelresultadodelaconsulta,ynolapropiaconsulta.Eselcaso,
porejemplo,cuandohayunclculodeagregadoenla consulta.Enelsiguienteejemplo,buscamoscuntosclientes
tenemoscuyoapellidoempiezaconlaletraA.Enestecaso,elresultadodelaconsultaesunsimpleenteroquese
calculaapartirdeladefinicindelaconsulta.

Dim numClientes = (From unCliente In listaClientes _


Where unCliente.apellido Like "A*" _
Select unCliente).Count
Console.WriteLine(numClientes)

Tambin puede acceder a mltiples fuentes de datos utilizando la clusula From. Para ello, la palabra clave Join
permitecombinarlosdatosdediferentesfuentes.Elsiguienteejemplobuscalosclientescuyoapellidoempiezapor
unaAyrecuperalafechadetodoslospedidosdecadaunodeellos.

Dim consulta3 = From unCliente In listaClientes _


Join unPedido In listaPedidos _
On unCliente.apellido Equals unPedido.Cliente.apellido _
Where unCliente.apellido Like "A*" _
Select apellidoCli = unCliente.apellido, _
fechaPdo = unPedido.fechaPedido

For Each r In consulta3


Console.WriteLine(r.apellidoCli & " " & r.fechaPdo)
Next

EstecdigomereceuncomentarioacercadelaclusulaSelect.Deseamosobtenerelapellidodelclienteylafecha
de los pedidos, o sea una cadena de caracteres y una fecha. No es necesario utilizar una instancia de la clase
Cliente y una instancia de la clasePedido solo para estos dos datos. El compilador genera, por tanto, una clase
annimaparaestosdosdatosconunapropiedadapellidoCliyunapropiedadfechaPdo.Eltipodelavariabler,
utilizada en el bucle For Each para recorrer el resultado de la consulta, ser determinado implcitamente para
corresponderseconel tipoannimocreadoporelcompilador.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
2.Losoperadoresdeconsulta

LosoperadoresquepermitenlacreacindeconsultasLINQsepuedenclasificarenochocategoras:

l Ordenardatos.

l Operacionessobreconjuntosdedatos.

l Filtrardatos.

l Proyeccin.

l Particiones.

l Unin,agrupacindedatos.

l Cuantificadores.

l Agregacin.

Para escribir consultas LINQ eficaces, conviene conocer correctamente estos operadores. Por lo tanto, vamos a
verlosendetalleconmuchosejemplos.

a.Ordenardatos

Esmuyfcilobtenerlosresultadosdeunaconsultaordenadossegnunoovarioscriterios.Graciasaloperador
Order By, podemos indicar la propiedad por la que vamos a ordenar. La siguiente consulta ordena los clientes
segnsunmerodepedidos.

Dim ConsultaOrdenada1 = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count _
Select unCliente
For Each unCliente In ConsultaOrdenada1
Console.WriteLine(unCliente.apellido & "numero de pedidos:"
& unCliente.Pedidos.Count)
Next

Pordefecto,elordenseaplicademaneraascendente.Paraobtenerlosmejoresclientesalprincipiodelalista,es
preferibleutilizarlapalabraclaveDescendingdespusdelcriteriodeordenacin.

Dim ConsultaOrdenada2 = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count Descending _
Select unCliente
For Each unCliente In ConsultaOrdenada2
Console.WriteLine(unCliente.apellido & "num pedidos:"
& unCliente.Pedidos.Count)
Next

Sepuedenindicarvarioscriteriosdeordenacinparaeliminarlasambigedadescuandodospropiedadestienenel
mismo valor. Se deben separar con comas los criterios de ordenacin en la consulta. La consulta ordena los
clientes segn el nmero de pedidos en orden descendente y luego segn el apellido del cliente en orden
ascendente,encasodequeelnmerodepedidosseaelmismo.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Dim ConsultaOrdenada3 = From unCliente In listaClientes _
Order By unCliente.Pedidos.Count Descending,
unCliente.apellido Ascending _
Select unCliente
For Each unCliente In ConsultaOrdenada3
Console.WriteLine(unCliente.apellido & "num pedidos:"
& unCliente.Pedidos.Count)
Next

b.Operacionesenconjuntosdedatos

Existeunoperadordisponibleenestacategoraquepermitelaeliminacindelosduplicadosdurantelabsqueda
de informacin. La palabra clave Distinct ubicada al final de la clusula Select indica que los duplicados sern
eliminados. El conjunto de los elementos de la clusula Select se tiene en cuenta para la eliminacin de
duplicados. La siguiente consulta determina las diferentes ciudades donde tenemos clientes. Si tenemos varios
clientesenlamismaciudad,estasoloselistarunavez.

Dim consultaJuntos = From unCliente In listaClientes _


Order By unCliente.direccionFacturacion.ciudad _
Select unCliente.direccionFacturacion.ciudad Distinct
For Each ciudad In consultaJuntos
Console.WriteLine(ciudad)
Next

c.Filtrardatos

Elfiltradoconsisteenreducirelnmerodeelementosdevueltosporlaconsulta.ConlaayudadelaclusulaWhere,
se agregan a la consulta una o ms expresiones, que deben facilitar un booleano durante la evaluacin de la
consulta.SepuedenutilizarlosoperadoresdecomparacinestndardeVisualBasicparaconstruirlaexpresin.El
usodeunacadenadecaracteresenunaclusulaWhererequiereunapequeaprecisin.Sibienpodemosutilizar
el operador = como criterio de filtrado para comparar una cadena de caracteres, el mtodo Equals ofrece ms
funcionalidades.Enefecto,coneloperador=debehaberunaigualdadestrictacondistincinentremaysculasy
minsculas durante el test. El mtodo Equals es ms flexible, ya que permite indicar cmo se debe hacer la
comparacinyeventualmenteignorarladistincinentreminsculasymaysculas,comoenelsiguienteejemplo.

Dim consultaFiltro = From unCliente In listaClientes _


Where unCliente.direccionFacturacion.ciudad.Equals("barcelona",
StringComparison.OrdinalIgnoreCase) _
Select unCliente
For Each unCliente In consultaFiltro
Console.WriteLine(unCliente.apellido)
Next

d.Proyeccin

Unaoperacindeproyeccincorrespondealatransformacindeunobjetoenunanuevaforma.Estanuevaforma
estconstituidaporlaunindepropiedadesdeobjetosespecificadaenlaclusulaSelect.Alutilizarlaproyeccin,
se puede crear automticamente un nuevo tipo construido a partir de cada proyecto. Usted puede proyectar
directamenteunapropiedad,obienejecutarunafuncinquetomacomoparmetrolapropiedad.Enestecaso,se

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
utiliza el resultado de la funcin como valor para la propiedad del objeto creado. Tambin puede proyectar el
objetooriginalsinmodificarlo.

Dim consultaProyeccion = From unCliente In listaClientes _


Select apellidoCli = unCliente.apellido.ToUpper, ciudadCli =
unCliente.direccionFacturacion.ciudad.ToLower

For Each r In consultaProyeccion


Console.WriteLine(r.apellidoCli & " " & r.ciudadCli)
Next

Las proyecciones tambin pueden realizarse indicando varias clusulas From en la consulta. En este caso, el
resultadodelaconsultahacequecadaobjetodecadaunadelasfuentesdedatossecorrespondacontodoslos
objetosdelasotrasfuentes.

Dim consultaProyeccion1 = From unCliente In listaClientes _


From unPedido In listaPedidos _
Select cli = unCliente, cmd = unPedido
For Each r In consultaProyeccion1
Console.WriteLine(r.cli.apellido & " " & r.cmd.fechaPedido)
Next

Estetipodeoperacinconducerpidamenteaunaexplosincombinatoria.Enefecto,elnmerodeobjetosenel
resultadodelaconsultaesigualalproductodelacantidaddeobjetosencadaunadelasfuentesdedatos.Un
filtrado que permita restringir el nmero de objetos en el resultado suele ser una buena idea con este tipo de
proyeccin.

Dim consultaProyeccion2 = From unCliente In listaClientes _


From unPedido In listaPedidos _
Where unCliente.Equals(unPedido.Cliente) _
Select cli = unCliente, cmd = unPedido

For Each r In consultaProyeccion2


Console.WriteLine(r.cli.apellido & " " & r.cmd.fechaPedido)
Next

e.Particiones

Laparticinconsisteendividirendospartesunconjuntodedatosyendevolverunadelasdospartes.Ellmite
delaparticinpuedeserabsoluto,yenestecasoexpresarlacantidaddeobjetos,ocondicional.Seutilizandos
clusulasparalaparticin:

l Skip indica que se desea obtener la segunda parte de la lista (en realidad se salta los objetos ubicados al
principio)

l Takeindicaquesedeseaobtenerelprincipiodelalistasintenerencuentalosregistrosdelfinaldelista.

Veamoscmoutilizarestosdosoperadoresconlasintaxisabsolutaylasintaxiscondicional.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lasiguienteconsultapermiteobtenerlalistadelosdiezpeoresclientes(basndoseenelnmerodepedidos).

Dim consultaParticion = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count _
Skip listaClientes.Count - 10 _
Select unCliente
For Each unCliente In consultaParticion
Console.WriteLine(unCliente.apellido)
Next

Parailustrarlasintaxiscondicional,buscamosahoratodoslosclientesquetienenunnmerodepedidosinferioro
iguala5.

Dim consultaParticion1 = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count Descending _
Skip While unCliente.Pedidos.Count > 5 _
Select unCliente
For Each unCliente In consultaParticion1
Console.WriteLine(unCliente.apellido & " " &
unCliente.Pedidos.Count)
Next

Pararecompensaranuestrosclientesfieles,buscamosahoralosdiezmejoresentreellos.

Dim consultaParticion2 = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count Descending _
Take 10 _
Select unCliente
For Each unCliente In consultaParticion2
Console.WriteLine(unCliente.apellido)
Next

Paraterminar,buscamoslosclientesquehanpasadoalmenosdiezpedidos.

Dim consultaParticion3 = From unCliente In listaClientes _


Order By unCliente.Pedidos.Count Descending _
Take While unCliente.Pedidos.Count >= 10 _
Select unCliente
For Each unCliente In consultaParticion3
Console.WriteLine(unCliente.apellido & " " &
unCliente.Pedidos.Count)
Next

f.Unin,agrupacindedatos

Launindedosfuentesdedatoscorrespondealaasociacindeunadelasfuentesdedatosconlosobjetosde
laotrafuentededatosconlaquetienenunapropiedadcomn.Enprogramacinorientadaaobjetos,lasuniones
permitenreemplazarasociacionesincompletas.Enelejemploqueutilizamosdesdeelprincipiodeestecaptulo,la

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
claseClientecontieneunapropiedadquepermiteobtenerlalistadelospedidosdeuncliente(Pedidos)ylaclase
Pedidocontieneunatributoquepermitereferenciarelclientequehapasadoelpedido(Cliente).Ennuestrocaso,
laasociacinesbidireccional.SiporomisinlapropiedadPedidosdelaclaseClientenoexiste,debemosrecorrer
la lista de pedidos y evaluar cada uno de ellos para obtener todos los pedidos de un cliente especfico. Le
correspondealauninrealizarestetrabajo.Lasiguienteconsultaobtienelospedidosdecadacliente.

Dim consultaJoin = From unCliente In listaClientes _


Join unPedido In listaPedidos On unCliente Equals unPedido.Cliente _
Select unCliente, unPedido
For Each r In consultaJoin
Console.WriteLine(r.unCliente.apellido & " " &
r.unPedido.fechaPedido)
Next

Paracadapedidoserepitenlosdatosrelativosalcliente.Unasolucinmseficazconsisteenejecutarlaconsulta
paraqueaadaacadaclientelalistadesuspedidos.LaclusulaGroup Joinpermiterealizarestaagrupacin.En
estecaso,estambinnecesarioespecificarconlaclusulaIntoelnombredelapropiedadutilizadaparaacceder
al reagrupamiento, en nuestro caso la lista de pedidos del cliente. Cabe observar que para nosotros esta
propiedadseduplicar(conlaqueyatenamosprevistaennuestraclaseCliente).

Dim consultaGroupJoin = From unCliente In listaClientes _


Group Join unPedido In listaPedidos On unCliente Equals unPedido.Cliente _
Into PedidosCliente = Group _
Select unCliente, PedidosCliente
For Each r In consultaGroupJoin
Console.WriteLine(r.unCliente.apellido)
For Each c In r.PedidosCliente
Console.WriteLine(vbTab & c.fechaPedido)
Next
Next

Tambin se puede llevar a cabo una agrupacin sin realizar la unin entre dos fuentes de datos. Por ejemplo,
podemosbuscarparacadaciudadlalistadelosclientesyresidentes.Paraello,laclusulaGroup By Intoesideal.
Solo es necesario indicar que deseamos agrupar los clientes con su ciudad de residencia, como clave de
agrupacin,eindicarelnombredelapropiedadquesegenerarparacontenerlaagrupacin.Laconsultagenera
entonces,durantesuejecucin,unalistadeinstanciasdeclasesquecontienedospropiedades:

l Elnombredelaciudad.

l Lalistadelosclientesgraciasalapropiedadindicadaenlaconsulta.

Dim consultaGroup = From unCliente In listaClientes _


Group unCliente By unCliente.direccionFacturacion.ciudad _
Into ClientesPorCiudad = Group _
Select ciudad, ClientesPorCiudad
For Each r In consultaGroup
Console.WriteLine(r.ciudad)
For Each c In r.ClientesPorCiudad
Console.WriteLine(vbTab & c.apellido)
Next
Next

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
g.Cuantificadores

Loscuantificadoresseutilizanparacontrolarsienunalistaalmenosunelementocumpleunacondicin,ositodos
loselementoslacumplen.Proporcionanelresultadodelcontrolenformadeunbooleanoqueengeneralseutiliza
enlaclusulaWhere.Comoejemplo,buscaremostodoslosclientescuyospedidoshansidorealizadosen 2007.

Dim consultaCuantificar = From unCliente In listaClientes _


Where (Aggregate cmd In unCliente.Pedidos Into All
(cmd.fechaPedido.Year = 2007)) _
Select unCliente
For Each unCliente In consultaCuantificar
Console.WriteLine(unCliente.apellido)
For Each c In unCliente.Pedidos
Console.WriteLine(vbTab & c.fechaPedido)
Next
Next

Lasegundaversinpermitelabsquedadeclientesquehayanhechoalmenosunpedidodurante2008.

Dim consultaCuantificar1 = From unCliente In listaClientes _


Where (Aggregate cmd In unCliente.Pedidos Into Any
(cmd.fechaPedido.Year = 2008)) _
Select unCliente

For Each unCliente In consultaCuantificar1


Console.WriteLine(unCliente.apellido)
For Each c In unCliente.Pedidos
Console.WriteLine(vbTab & c.fechaPedido)
Next
Next

h.Agregacin

Seutilizanlasoperacionesdeagregacinparaelclculodeunvalornicodesdevalorescontenidosenunalista
deelementos.Lasoperacionesmscorrientesson:

l Elclculodelpromedio.

l Labsquedadeunmximo.

l Labsquedadeunmnimo.

l Elclculodeuntotal.

Elsiguienteejemploaplicaestoscuatrooperadoressobrelosgastosdeenvodetodoslospedidos.

Dim promedioEnvio = Aggregate unPedido In listaPedidos Into


Average(unPedido.envio)
Console.WriteLine("promedio de envo: " & promedioEnvio)

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Dim maxiEnvio = Aggregate unPedido In listaPedidos Into
Max(unPedido.envio)
Console.WriteLine("envo mximo: " & maxiEnvio)
Dim miniEnvio = Aggregate unPedido In listaPedidos Into
Min(unPedido.envio)
Console.WriteLine("envo mnimo: " & miniEnvio)
Dim totalEnvio = Aggregate unPedido In listaPedidos Into
Sum(unPedido.envio)
Console.WriteLine("total envo: " & totalEnvio)

Estecdigotambinesunbuenejemplodeconsultadeejecucininmediata,yaqueparaobtenerelresultadose
deberecorrerobligatoriamentelalistadesdeelprimerohastaelltimoelemento.

Despus de haber estudiado la sintaxis del lenguaje, vamos a ver ahora cmo utilizarlo en asociacin con una
basededatos.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LINQhaciaSQL
Como hemos visto en los prrafos anteriores, el dominio preferido por LINQ es el mundo de los objetos. Permite
manipularperfectamentelaslistas,losobjetosysuspropiedades.Sinembargo,estoselementospresentanungrave
obstculo:desaparecerndemanerainexorableencuantoterminelaaplicacin.Lasolucinmsutilizadaparapaliar
esteproblemaconsisteenconfiaraunabasededatoseltrabajodeasegurarlapersistenciadelosdatosdespus
de cerrar la aplicacin. Para el dilogo con una base de datos, se utiliza a menudo el lenguaje SQL. Aunque las
principalespalabrasclaves deestosdoslenguajessonsimilares,sussintaxisnosoncompatibles.LasconsultasLINQ
setransformanautomticamenteensushomlogasSQLpararealizarlostratamientos.Perosedebetenerencuenta
otro problema. Hasta ahora hemos manipulado, por medio de consultas LINQ, objetos y solo objetos. El concepto
objetoestotalmenteextraoparaunabasededatos.Porlotanto,hayqueencontrarunasolucinparaqueLINQ
pueda acceder a los datos. La clave del enigma consiste simplemente en crear clases para representar, en la
aplicacin,losdatospresentesenlabasededatos.Estatcnicasellamamapeodeobjetorelacional,yeslaprimera
etapaenlautilizacindeLINQconunabasededatos.Porlotanto,vamosavercmocrearestasclases.

1.Elmapeodeobjetorelacional

Existentressolucionesparagenerarlasclasesquerepresentanlosdatosalmacenadosenlabasededatos:

l Crear las clases manualmente como si se tratase de cualquier otra clase de su aplicacin, utilizando un editor de
cdigo.Estasolucinesmuyfastidiosaysesueleutilizarparalasmodificacionesmnimasdeclasesexistentes.

l UtilizarlaherramientaenlneadecomandoSQLMetal.

l UtilizareldiseadorObjeto/Relacionalenmodogrfico.

a.SQLMetal

Esta herramienta est disponible desde una ventana de comando del entorno Visual Studio. Las opciones
indicadasenlalneadecomandopermitenconfigurarelfuncionamiento.Lasopcionesdisponiblestratande:

l Lageneracindelcdigofuentedelasclasesydelosatributosdemapeoapartirdeunabasededatos.

l Lageneracindeunarchivointermediodemapeo(.dbml)apartirdeunabasededatos.

l Lageneracindelasclasesydelosatributosdemapeoapartirdeunarchivodemapeo.

Cada opcin debe venir precedida por un carcter / y seguida por el carcter : y el valor de la opcin si es
necesario.

Lasopcionesdeconexin:

/server:<nombredelservidor>

IndicaelnombreoladireccinIPdelservidordebasededatos.

/database:<nombredelabasededatos>

Indicaelnombredelabasededatosapartirdelaqueseefectuarlageneracin.

/user:<usuariodeconexin>

Indicalacuentadeusuarioconlaqueseabrirlaconexinhacialabasededatos.Sinose
especificaestaopcin,seutilizarlaautenticacindeWindows.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
/password:<contrasea>

Indicalacontraseaasociadaalacuentautilizadaparaestablecerlaconexin.

/conn:<cadenadeconexin>

Sepuedeutilizarenlugardelascuatroopcionesanteriores,parafacilitarlosdatosrelativosala
conexinhaciaelservidordebasededatos.

timeout:<segundos>

IndicaladuracinmximadurantelacualSQLMetalintentaestablecerlaconexinhacialabasede
datos.Unvalorigualaceroindicaunaduracinilimitada.

Lasopcionesdesalida:

/dbml :<nombredelarchivo>

Generaunarchivodemapeo.

/codigo:<nombredelarchivo>

Generaelcdigofuentedelasclasesenelarchivoindicado.

Lasopcionesdegeneracin:

/lenguaje:<vbocsharp>

Indicaellenguajeenelquesegenerarelcdigo.LasdosopcionesvlidassonvbparaVisualBasic
ycsharpparaC#.

/namespace:<nombre>

Indicaelespaciodenombresenelquesegenerarnlasclases.Pordefecto,nohayunespaciode
nombres.

/context:<nombre>

Especificaelnombredeldatacontextgenerado.Pordefecto,sededuceestenombredelnombredela
basededatos.

/entitybase:<nombre>

Especificalaclasebasedelasclasesgeneradas.Pordefecto,lasclasesgeneradasnotienenclase
base.

Paraterminar,laltimainformacinquesedebefacilitarcorrespondealnombredelarchivodemapeoapartirdel
cual se realizar la generacin de las clases. Esta informacin es intil si la generacin se ejecuta directamente
desdelabasededatos.

Lepresentamosacontinuacinlosusosmscorrientesdeestaherramienta.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
GeneracindeclasesenVisualBasicdelabaseNorthwindsituadaenelequipolocal:

SqlMetal /server:localhost /database:northwind /dbml :nw.dbml

Como el cdigo generado es demasiado voluminoso para listarlo aqu (unas 3.500 lneas), veamos el diagrama
siguientedelasclasesgeneradas.

Tenemos la clase Northwind, que hereda de la clase DataContext y que rpidamente nos va a servir para que
LINQpuedadialogarconlabasededatos.Tambintenemosunaclasegeneradaparacadaunadelasmatrices
delabasededatos.Trabajaremosconlasinstanciasdeestasclasesennuestraaplicacin.

GeneracindelarchivodemapeodelabaseNorthwindsituadaenelordenadorlocal:

SqlMetal /server:localhost /database:northwind /dbml:nw.dbml

EstecomandogeneraunarchivoXMLdelquevemosunextracto:

<Table Name="dbo.Customers" Member="Customers">


<Type Name="Customers">
<Column Name="CustomerID" Type="System.String"
DbType="NChar(5) NOT NULL"
IsPrimaryKey="true" CanBeNull="false" />
<Column Name="CompanyName" Type="System.String" DbType="NVarChar(40)
NOT NULL" CanBeNull="false" />
<Column Name="ContactName" Type="System.String" DbType="NVarChar(30)"
CanBeNull="true" />
<Column Name="ContactTitle" Type="System.String" DbType="NVarChar(30)"
CanBeNull="true" />
<Column Name="Address" Type="System.String" DbType="NVarChar(60)"
CanBeNull="true" />
<Column Name="City" Type="System.String" DbType="NVarChar(15)"
CanBeNull="true" />
<Column Name="Region" Type="System.String" DbType="NVarChar(15)"
CanBeNull="true" />

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
<Column Name="PostalCode" Type="System.String" DbType="NVarChar(10)"
CanBeNull="true" />
<Column Name="Country" Type="System.String" DbType="NVarChar(15)"
CanBeNull="true" />
<Column Name="Phone" Type="System.String" DbType="NVarChar(24)"
CanBeNull="true" />
<Column Name="Fax" Type="System.String" DbType="NVarChar(24)"
CanBeNull="true" />
<Association Name="FK_CustomerCustomerDemo_Customers" Member=
"CustomerCustomerDemo" OtherKey="CustomerID" Type="CustomerCustomerDemo"
DeleteRule="NO ACTION" />
<Association Name="FK_Orders_Customers" Member="Orders" OtherKey=
"CustomerID" Type="Orders" DeleteRule="NO ACTION" />
</Type>
</Table>

Se puede modificar este archivo para, por ejemplo, cambiar el nombre de las clases y de las propiedades
asociadasalosdatosqueprocedendelabasededatos.Enelsiguienteejemplo,hemostraducidolosnombres.

<Table Name="dbo.Cliente" Member="Cliente">


<Type Name="Cliente">
<Column Name="CustomerID" Member="CdigoCliente" Storage="CustomerID"
Type="System.String" DbType="NChar(5) NOT NULL" IsPrimaryKey="true"
CanBeNull="false" />
<Column Name="CompanyName" Member="NombreEmpresa" Storage="CompanyName"
Type="System.String" DbType="NVarChar(40) NOT NULL" CanBeNull="false" />
<Column Name="ContactName" Member="NombreContacto" Storage="ContactName"
Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
<Column Name="ContactTitle" Member="Funcion" Storage="ContactTitle"
Type="System.String" DbType="NVarChar(30)" CanBeNull="true" />
<Column Name="Address" Member=Direccion" Storage="Address"
Type="System.String" DbType="NVarChar(60)" CanBeNull="true" />
<Column Name="City" Member="Ciudad" Storage="City"Type="System.String"
DbType="NVarChar(15)" CanBeNull="true" />
<Column Name="Region" Type="System.String" DbType="NVarChar(15)"
CanBeNull="true" />
<Column Name="PostalCode" Member="CdigoPostal" Storage="PostalCode"
Type="System.String" DbType="NVarChar(10)" CanBeNull="true" />
<Column Name="Country" Member="Pais" Storage="Country"
Type="System.String" DbType="NVarChar(15)" CanBeNull="true" />
<Column Name="Phone" Member="Telefono" Storage="_Phone"
Type="System.String"
DbType="NVarChar(24)" CanBeNull="true" />
<Column Name="Fax" Type="System.String" DbType="NVarChar(24)"
CanBeNull="true" />
<Association Name="Cliente_CustomerCustomersDemo" Member=
"CustomerCustomerDemo" ThisKey="CodigoCliente" OtherKey="CustomerID"
Type="CustomerCustomerDemo" />
<Association Name="Cliente_Orders" Member="Orders"
ThisKey="CodigoCliente"
OtherKey= "CustomerID" Type="Orders" />
</Type>
</Table>

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Enesteejemplo,conobjetodepoderutilizarnombresdepropiedadesdiferentesdelosnombresdecolumnasen
la base de datos, hemos aadido el atributo Member a cada etiqueta <Column> para especificar el nombre de la
propiedad y el atributo storage para indicar el nombre de la variable interna de la clase que contendr la
informacin.

Ahorapodemosgenerarelcdigoapartirdelarchivodemapeomodificadoconelsiguientecomando:

SqlMetal /code:nw.vb /language:vb nw.dbml

Veamoslaclasegeneradaparacomprobarquenuestrasmodificacionessehantenidoencuenta.

Estaherramientaesmuyfcildeutilizar,peropresentaelpequeoinconvenientedepodergenerarlasclasessolo
para la totalidad de una base de datos. Adems, las modificaciones se deben hacer manualmente, sea en el
cdigofuentegeneradooenelarchivodemapeointermedio.Paralageneracinylapersonalizacindealgunas
clases,espreferibleutilizareldiseadorObjeto/RelacionalintegradoenVisualStudio.

b.DiseadorObjeto/Relacional

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
EldiseadorObjeto/Relacionalofreceunasolucinmuyprcticaparacrearelmodeloobjetodeunaaplicacinque
representa los datos disponibles en una base de datos. Tambin permite la creacin de procedimientos y
funciones que autorizan la utilizacin de los procedimientos almacenados y funciones presentes en la base de
datos.Sinembargo,comportaalgunaslimitaciones:

l Solo las bases de datos SQL Server 2000, SQL Server 2005, SQL Server Express y SQL Server 2008 son
compatibles.

l El mapeo solo es posible entre una clase y una tabla, lo que significa que no se puede crear una clase para
representarelresultadodeunauninentrevariastablas.

l El diseador funciona en sentido nico, ya que en el cdigo generado solo se plasman las modificaciones
efectuadasenl.Sisemodificaelcdigomanualmente,eldiseadornotieneencuentalasmodificaciones.Yloque
es peor, si se introducen cambios en el diseador despus de haber hecho cambios manuales en el cdigo, estos
cambios se pierden al en el momento de guardar el diseador, ya que, en ese caso, el cdigo se regenera
automticamente. La solucin consiste en crear una clase parcial en un archivo independiente del que utiliza el
diseador.

El diseador Objeto/Relacional se abre automticamente cuando se agrega un elemento de tipo LINQ to SQL
Classes.Estaherramientatambinseabrecuandoseagregaunarchivo.dbmlaunproyecto.Cuandoseabre,la
superficie del diseador se separa en dos partes. La zona de la izquierda contiene las clases asociadas a las
tablas, mientras que la zona de la derecha contiene los procedimientos y las funciones asociadas a los
procedimientosalmacenados.

ElconjuntorepresentaelDataContextgenerado.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Agregarclases

Puedecrearlasclasesquerepresentanlasmatricesdeunabasededatosarrastrandoysoltandounaovarias
matricesdesdeelexploradordeservidoreshacialaparteizquierdadeldiseador.Elprimerelementoagregadoal
diseador Objeto/Relacional se usa para configurar las propiedades de la conexin del DataContext. Cuando se
aade otro elemento procedente de otra base de datos, un cuadro de dilogo le pregunta si desea sustituir la
conexin existente. Si acepta la modificacin, las clases ya presentes en el diseador no se podrn utilizar. La
adicin de una matriz genera el cdigo necesario para que el DataContext inicialice las propiedades de una
instanciadelaclaseapartirdelainformacinpresenteenunafiladelabasededatos.Tambinaadeelcdigo
necesarioparaquelasmodificacionesaportadasalaspropiedadesdelainstanciasepuedanvolcarenlabasede
datos.Eldiseadorsebasaenlaestructuradelatablayenlaclaveprimariaparaefectuarlasactualizaciones.

Si lo desea, tambin puede indicar cmo deben efectuarse las actualizaciones. Para ello, cada clase posee tres
propiedades:Insert,Update,Delete.PordefectoseinicializanestaspropiedadesconelvalorUtilizarelruntime
para indicar que el cdigo encargado de las actualizaciones se genera automticamente. Para modificar este
comportamiento,puedeasignaraestaspropiedadesprocedimientosalmacenados.Uncuadrodedilogopermite
laconfiguracindeestaspropiedades.

Despusdeseleccionarelprocedimientoalmacenado,debersealarcmoseindicanlosparmetrosesperados
enentradaporelprocedimientoalmacenado.Losvaloresdisponiblescorrespondenalasdiferentespropiedades
delaclase.Paracadapropiedad,estdisponiblelaversinactualodeorigen.

Agregarasociaciones

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Despusdehaberarrastradovariastablasaldiseador,esposiblecrearasociacionesentrealgunasdeellas.Las
asociacionessonmuysimilaresalasrelacionesentretablasenunabasededatos.Dehecho,siexisteenlabase
dedatosunarelacindeclaveexteriorentredostablas,secrearautomticamenteunaasociacincuandoestas
dostablasseagreguenaldiseador.

Paraagregarmanualmenteunaasociacin,debeutilizarelmencontextualdeldiseadorObjeto/Relacional.

Uncuadrodedilogoleproponeentoncesconfigurarlarelacin.Deberelegirlaclasepadreylaclasehijodela
relacin.Laclasepadreeslaclasequeseencuentraenelextremounodeunarelacinunoavarios,mientras
que la clase hijo representa el extremo varios de la relacin. Por ejemplo, en la asociacin entre las clases
ProductyCategory,laclaseCategoryrepresentaelladounodelarelacinylaclaseProductelladovarios.En
efecto,unproductoperteneceaunacategorayunacategoracontienevariosproductos.Acontinuacin,deber
indicarparacadaunadelasclaseslapropiedadolaspropiedadesquevanaparticiparenlarelacin.Conviene
comprobar que las propiedades que participan en la asociacin sean del mismo tipo en cada extremo de la
asociacin. Despus de la creacin de la asociacin, puede configurar algunas propiedades que no estn
disponiblesenelmomentodelacreacin.

l Cardinality:determinasilaasociacinesdetipounoavarios(onetomany)odetipounoauno(onetoone).

l Child Property: indica si una propiedad debe ser creada en la clase padre para referenciar la informacin de la
clasehijo.Eltipodeestapropiedadvienedeterminadoporeltipodelaclasehijoylacardinalidad.Silacardinalidad
es uno a uno, la propiedad es una simple referencia hacia una instancia de la clase correspondiente. Si la
cardinalidadesunoavarios,lapropiedadesunacoleccindeinstanciasdelaclasecorrespondiente.

l LaspropiedadesNamepermitenidentificarlaspropiedadescreadaspararealizarlaasociacin.

Agregarmtodos

Los procedimientos almacenados y las funciones pueden agregarse al diseador Objeto/Relacional para ser
transformados en mtodos del DataContext. La llamada de estos mtodos provocar la ejecucin del
procedimiento almacenado, o de la funcin, por el servidor de base de datos. Si el procedimiento almacenado
esperaparmetrosdeentrada,sedebernsuministraralmtododurantelaejecucin.Esmuysencilloagregarun
mtodo al DataContext, arrastrndolo y soltando entre el explorador de servidores y el diseador
Objeto/Relacional.Sinembargo,hayquetenercuidadoalagregarunprocedimientoalmacenadoounafuncin,ya
quelaubicacindondetendrlugareldesplazamientodeterminaeltipoderetornodelmtodogenerado.Sise
desplaza el elemento hacia la zona de la derecha del diseador, el tipo de retorno ser generado
automticamente.

Encambio,sisedesplazaelelementohaciaunaclaseexistentedeldiseador,eltipoderetornocorrespondera
estaclasesiemprequelainformacindevueltaporelprocedimientoalmacenadoseacompatibleconestaclase.
Vamos a hacer unas manipulaciones con el procedimiento almacenado [Ten Most Expensive Products], cuyo
cdigoeselsiguiente:

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

CREATE procedure [dbo].[Ten Most Expensive Products] AS


SET ROWCOUNT 10
SELECT Products.ProductName AS
TenMostExpensiveProducts,Products.UnitPrice
FROM Products
ORDER BY Products.UnitPrice DESC

Este procedimiento devuelve el nombre y el precio de los diez productos ms caros. Si intentamos aadir este
procedimiento al DataContext arrastrndolo y soltando hasta la superficie de la clase Product, obtenemos el
siguientemensaje.

En efecto, los elementos devueltos por el procedimiento almacenado no son productos, sino simplemente el
nombreyelpreciodelproducto.

Por el contrario, si arrastramos y movemos hacia la zona derecha del diseador, la operacin se realiza sin
problema.LasiguientefuncinseaadealDataContext.

Public Function Ten_Most_Expensive_Products() As ISingleResult


(Of Ten_Most_Expensive_ProductsResult)

Dim result As IExecuteResult = Me.ExecuteMethodCall(Me, CType(MethodInfo. GetCurrentMethod,MethodInfo))

Return CType(result.ReturnValue,ISingleResult(Of Ten_Most_Expensive_


ProductsResult))
End Function

Esta funcin no devuelve una lista de productos, sino una lista de Ten_Most_Expensive_ProductsResult, que
corresponde a una clase generada automticamente en funcin de la informacin devuelta por el procedimiento
almacenado.

Veamoslaestructura.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Para que la clase Product pueda utilizarse como tipo de retorno para la funcin, estamos obligados a modificar
ligeramenteelprocedimientoalmacenadoparaquedevuelvaproductos,ynosolamenteelnombreyelpreciodel
producto.

set ANSI_NULLS ON
set QUOTED_IDENTIFIER ON
go

ALTER procedure [dbo].[Ten Most Expensive Products] AS


SET ROWCOUNT 10
SELECT *
FROM Products
ORDER BY Products.UnitPrice DESC

Ahorapodemosvolverahacerlamismaoperacinyobtenerlasiguientefuncin,que,estavez,devuelveunalista
deproductos.

Public Function Ten_Most_Expensive_Products() As ISingleResult(Of Product)


Dim result As IExecuteResult = Me.ExecuteMethodCall(Me, CType(MethodInfo.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
GetCurrentMethod,MethodInfo))
Return CType(result.ReturnValue,ISingleResult(Of Product))
End Function

Herenciadeclases

Comocualquierclase,lasclasesgeneradasporelDiseadorObjeto/Relacionalpuedenutilizarlaherencia.Porel
contrario,paralasbasesdedatos,esunanocindesconocida.Hayquerecurriraalgunostrucosparasimularesta
tcnicaenunabasededatos.Lasolucinquesesueleutilizarconsisteencrearunatablanicaquecontendra
lavezlosdatosdelosobjetosdelaclasebsicaylosdelasubclase.Seaadeunacolumnaadicionalalatablaa
mododediscriminador.Enfuncindelvalordeestacolumna,esfcildeterminarsisedeberepresentarlafilacon
unainstanciadelaclasedebaseounainstanciadeladerivada.VamosamodificarlatablaProductsparapoder
aplicarestatcnica.AadimosalatablaunacolumnallamadaPerecederadetipoentero.Estacolumnanosvaa
servirdediscriminador.Sielvalorquecontieneesiguala1,setratadeunproductonoperecedero.Sielvalores
igual a 2, se trata de un producto perecedero. En este caso, la segunda columna, llamada DLC, de tipo fecha,
contienelafechalmitedeconsumodelproducto.Paralosproductosnoperecederos,estacolumnanocontiene
ningn valor (null). Modifique los datos de algunos productos para que se conviertan en productos perecederos
(CamenbertPierrot,CaracolesdeBorgoa,MascarponeFabioli).

Ahoraquelabasededatosestlista,podemosaadirlasclasesalDataContext.Laprimeraetapaconsisteen
aadirlatablaqueconstituyelaclasedebase.Luegoagregamosunsegundoejemplardeesatablaycambiamos
el nombre de la clase correspondiente, que se convertir en la clase derivada. A continuacin agregamos,
utilizandolacajadeherramientas,unarelacindeherenciaentrelasdosclasesquedibujamosdesdelaclasehija
hacialaclasepadre.Encadaunadelasclaseseliminamoslaspropiedadesintiles,manteniendo,porejemplo,la
propiedadDLCenlaclasederivadayeliminndolaenlaclasebase.Unavezseleccionadalarelacindeherencia
eneldiagrama,debemosmodificarsuspropiedades.

l Indique, mediante la propiedad Discriminator Property, la propiedad necesaria para distinguir entre una
instanciadelaclasebaseyunainstanciadelaclasesubclase.

l Configure las propiedades Base Class Discriminator Value y Derived Class Discriminator Value con los
valoresdelapropiedadconfiguradaanteriormentequerepresentaunainstanciadelaclasebaseyunainstanciade
lasubclase,respectivamente.

l La propiedad Inheritance Default especifica qu clase se utilizar si el discriminador contiene un valor


desconocido.

Obtenemoslassiguientesclases:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Ahoraquenuestrasclasesestndisponibles,veamoscmoutilizarlasmedianteconsultasLINQ.

c.UtilizacindeconsultasLINQaSQL

LasconsultasLINQaSQLutilizandemanerarigurosalamismasintaxisquelasquehemosestudiadoenlaseccin
SintaxisdellenguajeLINQ.Lanicapequeadiferenciaradicaenquelosdatossonextrados,enestecaso,dela
basededatosytransformadoseninstanciasdeclasesapartirdelosdatosdemapeo.Eldilogoconlabasede
datosestenteramenteacargodelDataContext.Porlotanto,tenemosquecrearunainstanciadelDataContext
porque es por su intermediacin que tendremos los datos disponibles para la ejecucin de la consulta LINQ. A
continuacinpresentamosnuestraprimeraconsultaLINQhacialabasededatos.

Dim dc As NorthWind
dc = New NorthWind
Dim consulta = From unCliente In dc.Customers _
Where unCliente.ContactName Like "A*" _
Select unCliente

For Each Cliente In consulta


Console.WriteLine(Cliente.ContactName)
Next

En este cdigo, la clase NorthWind corresponde al DataContext, que es el puente para que los datos estn
disponiblesparalaconsultaLINQ.Perocmoseseleccionanlosdatos?

En realidad, el mtodo ms natural para obtener datos procedentes de una base de datos consiste en pedir a
estaqueejecuteunaconsultaSQL.Efectivamente,estasolucineslautilizadaporLINQ.Paraverificarlo,podemos
pedirle al DataContext (NorthWind en nuestro caso) que muestre en la consola el cdigo SQL que genera
automticamente. Para ello, simplemente inicialicemos la propiedad Log del DataContext con la salida de la
consola,antesdelacreacindelaconsultaLINQ.

Dim dc As NorthWind
dc = New NorthWind
dc.Log = Console.Out
Dim consulta = From unCliente In dc.Customers _
Where unCliente.ContactName Like A* _
Select unCliente

For Each Cliente In consulta


Console.WriteLine(Cliente.ContactName)
Next

Durantelaejecucin,obtenemoslavisualizacinsiguiente:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName],


[t0].[ContactTitle], [t0].[Address], [t0].[City], [t0].[Region],
[t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax]
FROM [dbo].[Customers] AS [t0]
WHERE [t0].[ContactName] LIKE @p0
-- @p0: Input NVarChar (Size = 2; Prec = 0; Scale = 0) [A%]

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build:
3.5.21022.8

Ana Trujillo
Antonio Moreno
Ann Devon
Aria Cruz
Andr Fonseca
Annette Roulet
Alexander Feuer
Alejandra Camino
Art Braunschweiger
Anabela Domingues

Efectivamente, contamos con una consulta SQL con parmetros, que ha sido creada automticamente por el
DataContext. Esta consulta no es muy complicada y se hubiese podido escribir de forma fcil utilizando
directamenteADO.NET.Intentemosejecutarotraconsultaquenospermitaobtenerlasfechasdepedidosdecada
unodelosclientes.

Dim consultaGroupJoin = From unCliente In dc.Customers _


Group Join unPedido In dc.Orders On unCliente Equals unPedido.Customer _
Into PedidosCliente = Group _
Select unCliente, PedidosCliente
For Each r In consultaGroupJoin
Console.WriteLine(r.unCliente.ContactName)
For Each c In r.PedidosCliente
Console.WriteLine(vbTab & c.OrderDate)
Next
Next

EsteeselcdigoSQLgeneradoparalaejecucindeestaconsulta:

SELECT [t0].[CustomerID], [t0].[CompanyName], [t0].[ContactName],


[t0].[Contact Title], [t0].[Address], [t0].[City], [t0].[Region],
[t0].[PostalCode], [t0].[Country], [t0].[Phone], [t0].[Fax],
[t1].[OrderID], [t1].[CustomerID] AS [CustomerID 2],
[t1].[EmployeeID], [t1].[OrderDate], [t1].[RequiredDate],
[t1].[ShippedDate], [t1].[ShipVia], [t1].[Freight], [t1].[ShipName],
[t1].[ShipAddress], [t1].[ShipCity], [t1].[ShipRegion],
[t1].[ShipPostalCode], [t1].[ShipCountry], (
SELECT COUNT(*)
FROM [dbo].[Orders] AS [t2]
WHERE [t0].[CustomerID] = [t2].[CustomerID]
) AS [value]
FROM [dbo].[Customers] AS [t0]
LEFT OUTER JOIN [dbo].[Orders] AS [t1] ON [t0].[CustomerID] = [t1].[CustomerID]
ORDER BY [t0].[CustomerID], [t1].[OrderID]

Esto empieza a complicarse de manera seria. Escribir directamente en SQL una consulta como esta requerira
ciertamente el dominio de este lenguaje, mientras que, en cambio, la sintaxis LINQ resulta muy sencilla. Aqu,
justamente,esdondepuedeencontrarselapotenciadeLINQaSQL.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -
Estafacilidadnoselimitaalaextraccindedatosdesdelabasededatos,yaqueLINQaSQLtambinescapaz
degestionarlasactualizacionesdelosdatoshacialabasededatos.

d.Actualizacindedatos

Laactualizacindelabasededatosserealizatambindemaneramuysencilla,manipulandoobjetosysinescribir
lamenorlneadeSQL.

Modificacindedatosexistentes

La primera etapa consiste en obtener los datos que se desea modificar ejecutando una consulta de seleccin
ordinaria. Una vez que los datos estn disponibles en forma de instancias de clases, podemos simplemente
modificarlaspropiedadesdeestasinstancias.Paratransferirlasmodificacioneshacialabasededatos,bastacon
pedirle al DataContext que las propague hacia la base de datos. Vamos a probar esta tcnica desplazando
nuestrosclientesbarcelonesesaValencia.

Dim clientesBarceloneses = From unCliente In dc.Customers _


Where unCliente.City = "Barcelona" _
Select unCliente

For Each unCliente In clientesBarceloneses


unCliente.City = "Valencia"
unCliente.PostalCode = "46000"
Next
dc.SubmitChanges()

En este cdigo, es la instruccin SubmitChanges del DataContext la que provoca la actualizacin de la base de
datosejecutandoautomticamentelasiguienteconsultaSQLUpdateparacadaobjetoquehasidomodificado.

UPDATE [dbo].[Customers]
SET [City] = @p10, [PostalCode] = @p11
WHERE ([CustomerID] = @p0) AND ([CompanyName] = @p1) AND ([ContactName] = @p2)
AND ([ContactTitle] = @p3) AND ([Address] = @p4) AND ([City] = @p5)
AND ([Region]IS NULL) AND ([PostalCode] = @p6) AND ([Country] = @p7)
AND ([Phone] = @p8) AND ([Fax] = @p9)
-- @p0: Input NChar (Size = 5; Prec = 0; Scale = 0) [FRANR]
-- @p1: Input NVarChar (Size = 19; Prec = 0; Scale = 0) [Espaa restauracin]
-- @p2: Input NVarChar (Size = 14; Prec = 0; Scale = 0) [Carine Schmitt]
-- @p3: Input NVarChar (Size = 17; Prec = 0; Scale = 0) [Marketing Manager]
-- @p4: Input NVarChar (Size = 13; Prec = 0; Scale = 0) [calle real 54]
-- @p5: Input NVarChar (Size = 9; Prec = 0; Scale = 0) [Barcelona]
-- @p6: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [08000]
-- @p7: Input NVarChar (Size = 6; Prec = 0; Scale = 0) [Espaa]
-- @p8: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [40.32.21.21]
-- @p9: Input NVarChar (Size = 11; Prec = 0; Scale = 0) [40.32.21.20]
-- @p10: Input NVarChar (Size = 8; Prec = 0; Scale = 0) [Valencia]
-- @p11: Input NVarChar (Size = 5; Prec = 0; Scale = 0) [46000]
-- Context: SqlProvider(Sql2005) Model: AttributedMetaModel Build: 3.5.21022.8

Eliminacindedatos

- 14 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Comoparalamodificacin,debemosobtenerpreviamenteloselementosquedeseamoseliminarejecutandouna
consulta de seleccin, y luego indicar cules de ellos deseamos suprimir. Para ello, llamamos al mtodo
DeleteOnSubmitdelatablaalaqueperteneceelelemento,pasndolecomoparmetroelobjetoquedeseamos
eliminar. Para confirmar las eliminaciones, debemos invocar el mtodo SubmitChanges del DataContext. Vamos a
probarestatcnicaeliminandolosclientesbrasileosdelabasededatos.

Dim borrarCliente = From unCliente In dc.Customers _


Where unCliente.Country = "Brasil" _
Select unCliente
For Each unCliente In borrarCliente
dc.Customers.DeleteOnSubmit(unCliente)
Next
dc.SubmitChanges()

Alejecutanestecdigo,obtenemosestamagnificaExcepcin.

Ennuestraprecipitacin,hemosolvidadounpequeodetalle.Enlabasededatos,lasmatricesCustomer,Ordery
OrderDetail estn vinculadas por restricciones de clave externa. Por lo tanto, es imposible eliminar un cliente si
todavaposeepedidos,ydelamismamaneraesimposibleeliminarunpedidosicontienetodavafilasdepedido.
El problema viene del hecho de que LINQ no es capaz de gestionar las eliminaciones en cascada. Para resolver
nuestroproblema,tenemosdossoluciones:

l ActivarlareglaONDELETECASCADEenlasrestriccionesdeclaveextranjera.

l Gestionarnosotrosmismoslaeliminacindelosobjetosantesdelaeliminacindelosobjetospadres.

Estasolucineslaquevamosautilizar.Yaquenuestromodeloobjetoestdiseadocorrectamente,estasolucin
esmuyfcildeponerenmarcha.Enefecto,enlaclaseCustomers,tenemoslacoleccinOrders,querepresenta
los pedidos del cliente. Del mismo modo en la clase Orders, tenemos la coleccin Order_Details, que representa
todas las filas de un pedido. Solo hace falta ejecutar tres bucles anidados que van a suprimir las filas de cada
pedido,lospedidosdecadaclienteyfinalmentelospropiosclientes.

Dim borrarCliente = From unCliente In dc.Customers _


Where unCliente.Country = "Brasil" _

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 15 -
Select unCliente
For Each unCliente In borrarCliente
For Each unPedido In unCliente.Orders
For Each unaLinea In unPedido.Order_Details
dc.Order_Details.DeleteOnSubmit(unaFila)
Next
dc.Orders.DeleteOnSubmit(unPedido)
Next
dc.Customers.DeleteOnSubmit(unCliente)
Next
dc.SubmitChanges()

Conestasolucin,yanohayproblemasynuestrosclientesbrasileosestnborradoscorrectamentedelabase
dedatos.

Agregardatos

La inclusin de datos se realiza en tres etapas. Primero es necesario crear una instancia de la clase que
representa los datos que deseamos insertar en la base de datos. Luego se inicializan las propiedades de esta
instanciaconlosvaloresquequeremosagregarenlabasededatos.Elobjetoconfiguradodebeinsertarseenla
tabladelDataContext.Finalmentelasmodificacionessontransferidashacialabasededatos.Parailustrarestas
etapas,vamosaaadirunnuevoclientealabasededatos.

Dim nuevoCliente As Customer


nuevoCliente = New Customer
With nuevoCliente
.CustomerID = "MGARCI"
.ContactName = "Miguel Garca"
.CompanyName = "ENI"
.ContactTitle = "Formador"
.Country = "Espaa"
.City = "Salamanca"
.Address = "Calle Lido 3"
.Fax = "937.15.22.14"
.Phone = "937.25.88.91"
.PostalCode = "37001"
End With
dc.Customers.InsertOnSubmit(nuevoCliente)
dc.SubmitChanges()

e.Conflictosdelasactualizaciones

Ocurreamenudoquevariosusuariostrabajansimultneamenteconlamismabasededatos.Sepuedenproducir
conflictoscuandolosmismosregistrosdelabasededatossonactualizadosporvariosusuarios.LINQproponeun
mecanismoquepermitetrataresteproblema.Estemecanismosedescomponeencuatroetapas:

l Configurarenqudatosdelabasededatosdebencontrolarselosconflictos.

l Detectarlaaparicindeunconflicto.

l Obtenerinformacinrelativaalconflicto.

l Resolverelconflicto.

- 16 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Configuracindelasclasesparaladeteccindeconflictos

Durante la creacin de las clases con el diseador Objeto/Relacional, podemos indicar, para cada propiedad, si
debe ser incluida en el mecanismo de deteccin de conflictos. Cada miembro de la clase generada posee una
propiedadUpdate Checkalaquepodemosasignartresvaloresdiferentes:

l Siempre:ladeteccindeconflictosestsiempreactivaparaesteelemento.

l WhenChanged:activaladeteccinnicamentesielvalorhasidomodificado.

l Nunca:notenerencuentaesteelementoparaladeteccindeconflictos.

Pordefecto,todaslaspropiedadesseutilizanparaladeteccindeconflictos.

Deteccindeconflictos

Losconflictossurgenduranteeltrasladodelainformacinhacialabasededatos.Porlotanto,debemosintervenir
a este nivel. Para ello, durante la invocacin del mtodo SubmitChanges del DataContext, indicamos con un
parmetrocmodebecomportarseelmecanismodedeteccindeconflictos.Dossolucionessonposibles:

l FailOnFirstConflict:sealaelproblematanprontocomoseproduceelprimerconflicto.

l ContinueOnConflict:tratadehacertodaslasactualizacioneseindicaalfinalsiestteniendolugarunconflicto.

Si un conflicto es detectado, se activa una excepcin tipo ChangeConflictException. La invocacin del mtodo
SubmitChangesdebeestardentrodeunbloqueTry Catchparaatraparlaexcepcin.

Obtenerlainformacinrelativaalosconflictos

EnelbloqueCatchpodemosobtenerinformacinsobrelosconflictosrecorriendolacoleccinChangeConflictsdel
DataContext.EstacoleccincontieneunoomsobjetosdeltipoObjectChangeConflict.LapropiedadObjectnos
permiteobtenerunareferenciadelelementoqueoriginelproblema.LapropiedadMemberConflicts facilita, por
suparte,lalistadetodoslosmiembrosdeesteobjetoquehanoriginadoelproblema.

Tenemosanuestradisposicinelvalororiginaldecadaunoellosenelmomentodelacreacindelainstanciade
laclaseapartirdelainformacindelabasededatos,elvaloractualdelainstanciadelaclaseyelvaloractualen
labasededatos.

Resolverlosconflictos

Pararesolverlosconflictossobrevenidosdurantelaactualizacindelabasededatos,sepuedenconsiderartres
hiptesis.

l Reemplazarlosvaloresdelaspropiedadesenconflictoconlainformacinpresenteenlabasededatos.Paraesto,
se debe llamar al mtodo Resolve del objeto ObjectChangeConflict pasndole la constante Overwrite
CurrentValues.

l Reemplazarlosvaloresdelabasededatosporlainformacincontenidaenlaspropiedadesdelobjeto.Delamisma
manera que en la solucin anterior, debemos llamar al mtodo Resolve del objeto ObjectChangeConflict
pasndoleestavezlaconstanteKeepCurrentValues.

l Fusionarlaspropiedadesdelobjetoconlainformacindelabasededatos.Semodificalainformacindelabasede
datos solo si la propiedad correspondiente al objeto ha sido modificada. En este caso, se debe llamar al mtodo
ResolveconlaconstanteKeepChanges.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 17 -
Elsiguientecdigolepermiteprobarestasdiferentessolucionesreemplazandosimplementelaconstantedurante
lallamadadelmtodoResolve.

Dim cl As Customer
Dim rqt = From unCliente In dc.Customers _
Where unCliente.CustomerID = "BOLID" _
Select unCliente

For Each cl In rqt


cl.City = "Barcelona"
Next
Console.WriteLine("modificar el cdigo postal del cliente BOLID en
la base y luego presionar una tecla")
Console.ReadLine()
Try
dc.SubmitChanges(ConflictMode.FailOnFirstConflict)
Catch ex As ChangeConflictException
For Each o As ObjectChangeConflict In dc.ChangeConflicts
o.Resolve(RefreshMode.KeepChanges)
o.Resolve(RefreshMode.KeepCurrentValues)
o.Resolve(RefreshMode.OverwriteCurrentValues)
Next
End Try
Console.WriteLine("el objeto cliente:")
Console.WriteLine("city:" & cl.City)
Console.WriteLine("postalCode:" & cl.PostalCode)
For Each cli In rqt
Console.WriteLine("el cliente en la base:")
Console.WriteLine("city:" & cli.City)
Console.WriteLine("postalCode:" & cli.PostalCode)
Next

- 18 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Presentacin

EllenguajeXML(eXtensible Markup Language)esunlenguajequesirvepararepresentardatos.Permiteencapsular


cualquier tipo de datos representndolos en forma de rbol. Los datos se escriben en etiquetas o en forma de
atributos.Esteformatopermiteescribirdatos,peronodarlesformatonimanipularlos.Seutilizaprincipalmentepara
hacer posible el intercambio de datos entre aplicaciones e incluso entre sistemas diferentes. Tambin se utiliza a
menudo como formato de almacenamiento para los parmetros de configuracin de una aplicacin. Visual Studio y
Windows lo utilizan habitualmente con este fin. Este lenguaje ha sido diseado por W3C (World Wide Web
Consortium).Porlotanto,esenelsitio http://www.w3.org/XMLdondepodrobtenereldetalledelasespecificaciones
deestelenguaje.

EllenguajeXMLseconfundeamenudoconellenguajeHTML.Aunquepresentansimilitudes,estosdoslenguajesno
tienenlamismafinalidad.AcontinuacinpresentamoslospuntoscomunesentreloslenguajesXMLyHTML:

l Losdoslenguajessepresentancomosolotexto.

l Serepresentaelcontenidodelosdocumentosatravsdeetiquetas.

l Estasetiquetaspuedenteneratributos.

l Sepuedenanidarlasetiquetaslasunasenlasotras.

l Amboslenguajesprovienendeunamismabase:elSGML(StandardGeneralizedMarkupLanguage).

EllenguajeXMLsediferenciadellenguajeHTMLenlospuntossiguientes:

l EllenguajeXMLpermitelacreacindesuspropiasetiquetas.

l Lasherramientasencargadasdeltratamientogestionanlasintaxisdemaneramsrigurosa.

l HTML es un lenguaje diseado para la presentacin de los datos. En cambio, XML se utiliza para la descripcin de los
datos.

Parapodersermanipuladosfcilmente,losdatosXMLsedebenconfiaraunprocesadorXML.

UnprocesadorXMLesunmdulodesoftwareespecialmenteescritoparamanipularXML.Lautilizacindeunmdulo
externo para el tratamiento XML se explica por la complejidad que representa el desarrollo de un procesador XML,
totalmente funcional. Efectivamente: para que un procesador XML sea considerado totalmente funcional, su
funcionamiento debe seguir las evoluciones del lenguaje definidas por el W3C. Por lo tanto, es importante visitar
regularmenteelsitiodeMicrosoftparaverificarsiexisteunaversinmsrecientedelprocesadorXMLquelaqueest
instaladaensumquina.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
EstructuradeundocumentoXML

AntesdemanipulardocumentosXMLapartirdeVisualBasic,esimportanteentenderbienlaestructuradeestetipo
dedocumentos.Lossiguientesprrafospresentanlasnocioneselementalesquesedebenconocerantesdelanzarse
alautilizacindedocumentosXML.

1.ComponentesdeundocumentoXML

UndocumentoXMLsepuedeformarapartirdelossiguienteselementos:

Instruccindetratamiento

LasinstruccionesdetratamientopermitenincorporarenundocumentoXMLlainformacindestinadaalprocesador
XML o a otras aplicaciones que deban manipular el documento. Se utilizan estas instrucciones para facilitar una
instruccinespecialaunaaplicacinquetrabajaeneldocumento.

Seinsertalainstruccindetratamientoeneldocumentoconlasiguientesintaxis:

< ?nombreAplicacion instruccion ?>

Laprimeraparteeselnombredelaaplicacinalaquesedestinaestainstruccin.Lasegundaparteeseltextode
lainstruccin.

UndocumentoXMLcontieneengeneralunainstruccindetratamientoespecialparadefinirlaversindeXMLque
correspondealdocumentoylacodificacindeloscaracteresqueesteutiliza.

<?xml version="1.0" encoding="utf-8" ?>

Comentarios

Loscomentariossirvenparaincluireneldocumentoinformacindestinadaalosusuariosdeeste.ElprocesadorXML
olasaplicacionesqueutilizaneldocumentolosignoran.Nosedebenincorporaraunaetiqueta.

Lasiguientesintaxissedebeutilizarparaubicaruncomentarioeneldocumento.

<!--esto es un comentario-->

Enelinteriordelcomentario,lautilizacindeloscaracteresestprohibida:

Caracteresreservados

AlgunoscaracteresestnreservadosparaellenguajeXML,comoporejemploelcarcter&delsiguienteejemplo:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
ParapoderutilizarestoscaracteresenundocumentoXML,debesustituirlosporlasiguientesintaxis:

Carcter Utilizarenlugarde

& &amp

< &lt

> &gt

&apos

" &quot

Porlotanto,lasintaxiscorrectaes:

<menu>queso &amp; postre</menu>

SepuedenincorporarsecuenciasdecaracteresmslargasutilizandounaseccinCDATA. Lasintaxiseslasiguiente:

<![CDATA[{ Select * from postres where precio < 10} and caloras > 500]]>

Conestasintaxiscualquiercarctersepuedeutilizarsinprecaucinparticular.

ElementosXML

Un elemento XML es un contenedor que incluye datos y otros elementos. Est compuesto por una etiqueta de
principioyotradefin.LasintaxisdeunelementoXMLeslasiguiente:

<NombreElemento>contenido</NombreElemento>

Loselementosdebenrespetaralgunasreglasrelativasasuforma:

l Losnombresdeloselementosnopuedencontenerespacios.

l Nopuedenempezarporunnmeroounsignodepuntuacin.

l Nopuedenempezarconxml(tantosilaletraesmaysculacomominscula).

l Debenempezarjustodespusdelsigno>,sinespacios.

l Lasetiquetasdeprincipioyfindebentenerlamismacaja(maysculas/minsculas).

l UndocumentoXMLdebeconteneralmenosunelemento:elelementoraz.

l Todosloselementosquesiguenalelementorazdebenquedaranidadoseneste.

l Siunelementonotienecontenido,puedeestarconstituidonicamenteporunaetiquetadefin.

l Soloelelementorazdebetenerunaetiquetadeprincipioyotradefin,inclusosinotienecontenido.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Ejemplo

<?xml version="1.0" encoding="utf-8" ?>


<restaurante>
<menu>
<entrantes>
<nombre>rbanos</nombre>
<nombre>pasta</nombre>
<nombre>salchichn</nombre>
</entrantes>
<platos>
<nombre>paella</nombre>
<nombre>fideu</nombre>
<nombre>cuscs</nombre>
</platos>
<quesos>
<nombre>manchego</nombre>
<nombre>tetilla</nombre>
<nombre>cabrales</nombre>
</quesos>
<postres>
<nombre>helado</nombre>
<nombre>tarta</nombre>
<nombre>crema catalana</nombre>
</postres>
</menu>
</restaurante>

Atributosdeelementos

Seutilizanlosatributosdeelementosparacalificarunelemento.Seubicanenlaetiquetadeprincipiodelelemento.
Comoloselementos,debenseguirciertasreglas:

l Unatributoestcompuestoporunnombreyunaasignacindevalor.

l Unelementopuedecontenerunnmerocualquieradeatributos.

l Losnombresdeatributosestnseparadosporespacios.

l Unnombredeatributosolopuedeaparecerunavezenunelemento.

l Unnombredeatributopuedeaparecerenvarioselementos.

l Unnombredeatributonopuedecontenerespacios.

l Laasignacindeunvaloraunatributosehaceconelsignoigual,seguidoporelvalorentrecomillasdobles.

Ejemplo

<?xml version="1.0" encoding="utf-8" ?>


<restaurante>
<menu type="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">fideu</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="chocolate">helado</nmero>
<nmero caloras="250" frutas="manzanas">tarta</nmero>
<nmero caloras="400">crema catalana</nmero>
</postres>
</menu>
</restaurante>

Espaciosdenombres

Unespaciodenombresesunconjuntodenombresdeelementosidentificadosporunanicareferencia.Permiten
evitarlasconfusionescuandounosdatosXMLsefusionanapartirdediferentesfuentes.

Veamoselsiguienteejemplo,quepodraserunarchivodeconfiguracindeunaaplicacin:

<?xml version="1.0" encoding="utf-8" ?>


<aplicacion>
<menu nombre="archivo">
<entrantes>nuevo</entrantes>
<entrantes>abrir</entrantes>
<entrantes>cerrar</entrantes>
</menu>
<menu nombre="edicion">
<entrantes>copiar</entrantes>
<entrantes>cortar</entrantes>
<entrantes>pegar</entrantes>
</menu>
</aplicacion>

Enestearchivo,tenemoselementosyadefinidosenotroarchivo.Esobvioqueloselementosmenuyentrantesno
tienen el mismo significado que en el archivo utilizado anteriormente. Para evitar cualquier ambigedad, hay que
agregaracadaarchivounadefinicindeespaciodenombresquehagaquecadaelementoseanico.Ladefinicin
deunespaciodenombresseefectaconelatributoxmlnsseguidoporunprefijoyporelidentificadordelespacio
denombres.

Lasintaxiseslasiguienteparacadaunodenuestrosdosarchivos:

<restaurante xmlns:rest="http://www.eni-escuela.es/restaurante">

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
<application xmlns:appli="http://www.eni-escuela.es/configappli">

Esmuyimportantequelosidentificadoresdeespaciodenombresseannicossideseaintercambiardatosconotras
personas.Poreso,escorrienteutilizarelnombredeldominiodelaempresaenelidentificador(sesuponequeeste
esnico).Conestamodificacin,podemosutilizarenelmismoarchivoelementosdemenuyentrantesagregando
anteelprefijoelespaciodenombresenelquetienenunsignificado.

<fusion xmlns:appli="http://www.eni-escuela.es/configappli" xmlns:resto=


"http://www.eni-escuela.es/restaurante">
<appli:menu nombre="archivo">
<appli:entrantes>registrar</appli:entrantes>
</appli:menu>
<resto:menu nombre="economico">
<resto:entrantes>aguacate</resto:entrantes>
</resto:menu>
</fusion>

2.Documentobienformadoydocumentovlido

Gracias al lenguaje XML, tenemos la posibilidad de crear fcilmente documentos estructurados y comprensibles.
TambinexistendosnocionesquepermitenverificarlacalidaddeundocumentoXML:undocumentopuedeestar
bienformadoyundocumentopuedeservlido.

a.Documentobienformado

Un documento est bien formado si obedece a las reglas sintcticas del lenguaje XML. Estas reglas son mucho
menos estrictas que las reglas de validez. Gestionan las atribuciones de nombres, las creaciones y los
anidamientos de elementos. Para poder ser tratado por un procesador XML, un documento debe estar bien
formado.Sielprocesadordetectaunerror,detieneinmediatamenteeltratamientodeldocumento.

b.Documentovlido

UndocumentovlidoesundocumentoXMLalcualsevinculaunaDTD,ounesquemaXSD,(definicindeltipode
documento)yquerespetatodaslasreglasdeconstruccindefinidasenestaltima.CuandounprocesadorXML
analizaeldocumento,buscaenlaDTD,oenelesquemaXSD,unadefinicinparacualquierelemento,atributoy
entidaddeestedocumento.Encuantoencuentraunerror,detieneeltratamiento.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
ManipulacindeundocumentoXML

El tratamiento de un documento XML en una aplicacin VB.NET se hace utilizando DOM (Document Object Model). El
DOMlepermiteleer,manipularymodificarundocumentoXMLconunprograma.Esteltimorigelarepresentacinen
memoria de los datos XML, aunque los verdaderos datos XML estn almacenados de manera lineal cuando se
encuentranenunarchivooprocedendeotroobjeto.

Porejemplo,elsiguientedocumento:

<?xml version="1.0"?>
<restaurante>
<menu precio="10">
<entrantes>rbanos</entrantes>
<plato>fideu</plato>
<postre>helado</postre>
</menu>
<vinos>
<tinto>rioja</tinto>
<blanco>moscatel</blanco>
</vinos>
</restaurante>

estrepresentadoenestaformaenlamemoriadeunaaplicacin:

EnlaestructuradeundocumentoXML,cadacrculodeestailustracinrepresentaunnodo,llamadoobjetoXmlNode,
que es el objeto bsico del rbol DOM. La clase XmlDocument se encarga de los mtodos destinados a ejecutar
operacioneseneldocumentoensuconjunto,porejemploparacargarloenmemoriaograbarloenformadearchivo.
Los objetos XmlNode comportan un conjunto de mtodos y de propiedades, as como caractersticas bsicas bien
definidas.Acontinuacin,presentamosalgunasdeestascaractersticas:

l Unnodosolopuedeposeerunnodopadre,queeselnodosituadojustoencimadel.

l El nico nodo que no tiene padre es la raz del documento, ya que se trata del nodo de primer nivel que contiene el
propiodocumentoylosfragmentosdedocumento.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
l Lamayoradelosnodospuedencomportarvariosnodoshijosquesonlosnodossituadosdirectamentedebajodeellos.

l Losnodossituadosenelmismonivel,representadoseneldiagramaporlosnodosmenyvinos,sonnodoshermanos.

UnadelascaractersticasdelDOMessumaneradegestionarlosatributos.Losatributosnosonnodosqueforman
partedelasrelacionespadrehijoyhermano.Seconsiderancomounapropiedaddelnodoyestnconstituidospor
unpar,compuestoporunnombreyunvalor.

Ennuestroejemplo,precio="10"asociadoalelementomen,lapalabrapreciocorrespondealnombreyelvalordel
atributoprecioes10.Paraextraerelatributoprecio="10"delnodomen,sellamaalmtodoGetAttributecuandoel
cursorseencuentraenelnodomen.

Paralosejemplossiguientes,utilizaremosestedocumentoXML:

<?xml version="1.0" encoding="utf-8" ?>


<restaurante>
<menu tipo="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="170" sabor="chocolate">helado</nmero>
<nmero caloras="125" frutas="manzanas">tarta</nmero>
<nmero caloras="200">crema catalana</nmero>
</postres>
</menu>
<menu type="economico">
<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>
</restaurante>

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
1.UtilizacindeDOM

La primera etapa durante la utilizacin de DOM consiste en cargar el documento XML en un rbol de nodos DOM.
Para ello, usted debe declarar un objetoXmlDocument y luego utilizar el mtodo Load para rellenar este objeto a
partirdeunarchivoXML.

dim doc as XmlDocument


doc = New Xml.XmlDocument()
doc.Load("restaurante.xml")

TambinesposiblecargardatosXMLapartirdeunacadenadecaracteres.Enestecaso,debeutilizarelmtodo
LoadXMLfacilitndolelacadenadecaracteresquecontienelosdatosXML.

Una vez cargados los datos XML en el rbol, puede localizar nodos especiales con el fin de manipularlos o
modificarlos. El mtodo GetElementsByTagName permite obtener un objeto XmlNodeList, que contiene los nodos
respectivos. Entonces puede obtener los atributos del nodo utilizando la propiedad Attributes o comprobar si
poseen nodos hijos con la propiedad HasChildNodes. Si es el caso, tiene acceso a estos nodos gracias a la
propiedadChildNodesenformadeunobjetoXmlNodeList.

Elsiguienteejemplobuscalosnodosmenenelrbolymuestraelatributotipo.

menus = doc.GetElementsByTagName("menu")
For Each unMenu In menus
Console.WriteLine(unMenu.Attributes("tipo").Value)
Next

Tambin se pueden modificar las caractersticas de los nodos aadindoles un atributo. Los nodos pueden, por
ejemplo,recibirunatributoprecio.

menus = doc.GetElementsByTagName("menu")
Dim att As XmlAttribute
For Each unMenu In menus
If unMenu.Attributes("tipo").Value = "gastronomico" Then
att = doc.CreateAttribute("precio")
att.Value = "50 euros"
unMenu.Attributes.Append(att)
End If
If unMenu.Attributes("tipo").Value = "economico" Then
att = doc.CreateAttribute("precio")
att.Value = "15 euros"
unMenu.Attributes.Append(att)
End If
Next

Tambin es posible aadir nodos hijos a nodos que existen en el rbol, creando instancias de la claseXmlNode y
unindolosasunodopadre.Elsiguienteejemploaadeundigestivoalmengastronomico.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
menus = doc.GetElementsByTagName("menu")
Dim att As XmlAttribute
For Each unMenu In menus
If unMenu.Attributes("tipo").Value = "gastronomico" Then
Dim n1, n2, n3 As XmlNode
n1 = doc.CreateNode(XmlNodeType.Element, "digestivo", "")
n2 = doc.CreateNode(XmlNodeType.Element, "nombre", "")
n3 = doc.CreateNode(XmlNodeType.Text, "", "")
n3.Value = "Cognac"
n2.AppendChild(n3)
n1.AppendChild(n2)
unMenu.AppendChild(n1)
End If
Next

Despusdelaejecucindelosdosejemplosanteriores,eldocumentoXMLdebetenerlasiguienteforma:

<?xml version="1.0" encoding="Windows-1252"?>


<restaurante>
<menu tipo="gastronomico" precio="50 ">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">fideu</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="chocolate">helado</nmero>
<nmero caloras="250" frutas="manzanas">tarta</nmero>
<nmero caloras="400">crema catalana</nmero>
</postres>
<digestivo>
<nmero>Cognac</nmero>
</digestivo>
</menu>
<menu tipo="economico" precio="15 ">
<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>
</restaurante>

En realidad, solo se modifica la representacin en memoria del documento XML. Si desea conservar las
modificaciones,hayqueguardareldocumentoenunarchivoparaasegurarlapersistenciadelosdatos.Paraello,
debeutilizarelmtodoSavedelaclaseXmlDocument,ydarleelnombredelarchivoenelquedeseaefectuarlacopia
deseguridad.

doc.Save("rest2.xml")

2.UtilizacindeXPath

La principal finalidad de XPath consiste en definir la manera de buscar partes de un documento XML. El nombre
XPathvienedelautilizacindeunaescrituradetipopath,comoenlosshellsDOSyUNIX.Elobjetivoconsisteen
desplazarseenelinteriordelaestructurajerrquicadeundocumentoXMLcomoenunrboldedirectorios.Para
tenerunaideadelintersdeXPath,podramosdecirqueeselequivalenteallenguajeSQLparaundocumentoXML.
Perolacomparacinseacabaaqui,porquelasintaxisnotienenadaquever!

a.BsquedaenundocumentoXML

Para buscar un elemento en un documento XML, la primera etapa consiste en crear una instancia de la clase
XPathNavigator. Esta instancia de clase debe conocer el documento en el que deber hacer las bsquedas. Por
esoeselpropiodocumentoelque,medianteelmtodoCreateNavigator,vaafacilitarestainstanciadeclase.

Dim navegador As XPathNavigator = document.CreateNavigator()

Apartirdeestainstancia,vamosapoderlanzarbsquedaseneldocumentoconlaayudadelmtodoSelect.Este
mtodoutilizacomoparmetrounacadenadecaracteresquecontienelarutaXPathdebsqueda.Despusdela
ejecucin,obtenemosunobjetoXPathNodeIterator,quepermiterecorrerlalistadelosnodosencontrados.

Elsiguienteejemplobuscaeneldocumentorest.xmllosentrantesdisponiblesenlosdiferentesmens:

Dim documento As XmlDocument = New XmlDocument ()


documento.Load("rest.xml")

Dim navegador As XPathNavigator = documento.CreateNavigator()


Dim nodos As XPathNodeIterator = navegador.Select("/restaurante/
menu/ entrantes")
While nodos.MoveNext()
Console.WriteLine(nodos.Current.OuterXml)
Console.WriteLine()
End While

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Obtenemoselsiguienteresultado:

<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>

<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>

TambinesposibleaadiralaconsultaXPathunoscriteriosdeseleccinsobreelvalordeciertosatributos.

Elsiguienteejemplobuscalospostresdelmengastronomicoconmenosde350caloras.

Dim documento As XmlDocument = New XmlDocument ()


documento.Load("rest.xml")
Dim navegador As XPathNavigator = documento.CreateNavigator()
Dim nodos As XPathNodeIterator = navegador.Select("/restaurante/menu[@tipo=
gastronomico]/postres/nmero @caloras <350 ]")
While nodos.MoveNext()
Console.WriteLine(nodos.Current.Value)
Console.WriteLine()
End While

b.ModificacindelosdatosdeundocumentoXML

Despus de haber encontrado un elemento en el rbol de un documento, por supuesto es posible modificar su
valor.

Elsiguienteejemplodisminuyeun50 %lascalorasdecadapostredelmengastronomico.

Dim documento As XmlDocument = New XmlDocument()


documento.Load("rest.xml")
Dim navegador As XPathNavigator = documento.CreateNavigator()
Dim nodos As XPathNodeIterator =
navegador.Select("/restaurante/menu
[ @tipo=gastronomico]/postres/nombre")

While nodos.MoveNext()
nodos.Current.MoveToAttribute("caloras", "")
nodos.Current.SetValue(nodos.Current.Value * 0.5)
End While
documento.Save("rest.xml")

Acontinuacinpresentamoselcontenidodelarchivodespusdelaejecucindelcdigoanterior.

<?xml version="1.0" encoding="utf-8" ?>

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
<restaurante>
<menu tipo="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="170" sabor="chocolatee">helado</nmero>
<nmero caloras="125" frutas="manzanas">tarta</nmero>
<nmero caloras="200">crema catalana</nmero>
</postres>
</menu>
<menu tipo="economico">
<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>
</restaurante>

c.AgregarunnodoaundocumentoXML

Despusdelabsquedadeunnodoenundocumento,esposibleaadirlenodoshijosynodoshermanos.Los
mtodos InsertAfter e InsertBefore aaden un nodo hermano despus o antes del nodo actual. El mtodo
AppendChildagregaunnodo hijoalnodoactual.

Elsiguienteejemploagregaunnuevopostrealmengastronomico.

Dim documento As XmlDocument = New XmlDocument()


documento.Load("rest.xml")
Dim navegador As XPathNavigator = documento.CreateNavigator()
Dim nodos As XPathNodeIterator = navegador.Select("/restaurante/menu[@tipo=
gastronomico]/postres") nodos.MoveNext()

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
nodos.Current.AppendChild("<nmero caloras=800>crepes</nmero>")
documento.Save("rest.xml")

Despusdelaejecucindeestecdigo,eldocumentoseconvierteen:

<?xml version="1.0" encoding="utf-8" ?>


<restaurante>
<menu tipo="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="chocolate">helado</nmero>
<nmero caloras="250" frutas="manzanas">tarta</nmero>
<nmero caloras="400">crema catalana</nmero>
<nmero caloras="800">crepes</nmero>
</postres>
</menu>
<menu tipo="economico">
<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>
</restaurante>

3.UsodeLINQtoXML

El uso de LINQ puede ser una alternativa a DOM y XPath para manejar documentos XML. El principio de
funcionamiento es prcticamente igual al de DOM, ya que, para poder trabajar con un documento XML, en primer
lugar es necesario cargarlo en memoria como una arborescencia de objetos. Las clases necesarias para esta

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
representacinestndisponiblesenlabibliotecaSystem.Xml.Linq.Portanto,esimprescindibleaadirasuproyecto
unareferenciaaestabiblioteca.

El documento XML que se va a tratar se carga en memoria a travs de una llamada al mtodo Load de la clase
XDocument:

Dim doc As Xdocument


doc = XDocument.Load("c:\restaurante.xml")

Ahora el contenido del archivo est disponible en memoria en forma de instancias de las clases XElement y
XAttribute,relacionadasconlainstanciadelaclaseXDocument quesehacreado.

AlasinstanciassepuedeaccederconlapropiedadElementsdelobjetoXDocument.

Elsiguienteejemplocargaelarchivorestaurante.xmlymuestraloselementosextradosdelarchivo.

Dim doc As Xdocument


doc = XDocument.Load("c:\restaurante.xml")
Dim el As Xelement
For Each el In doc.Elements
Console.WriteLine(el)
Next

Obtenemoselsiguienteresultado,quecorrespondealcontenidodenuestroarchivo:

<restaurante>
<menu tipo="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="chocolate">helado</nmero>
<nmero caloras="250" frutas="manzanas">tarta</nmero>
<nmero caloras="400">crema catalana</nmero>
</postres>
</menu>
<menu tipo="economico">
<entrantes>
<nmero caloras="50">pan</nmero>

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>
</restaurante>

Larazdeldocumentoformapartedeloselementosqueseextraendelarchivo.

Tambinesposibleextraerdirectamenteelelementorazenformadeunobjeto XElementutilizandoelmtodo
LoaddelaclasseXElement.

Dim raiz As Xelement


raiz = XElement.Load("c:\restaurante.xml")
For Each el In raiz.Elements
Console.WriteLine(el)
Next

En este caso, obtenemos un objeto XElement, que representa al elemento raz. Su propiedad Elements
contieneloselementoshijodelcontenidodelarchivoXML(sinelementoraz).

<menu tipo="gastronomico">
<entrantes>
<nmero caloras="50">rbanos</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<platos>
<nmero caloras="1000">paella</nmero>
<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
<nmero caloras="300">tetilla</nmero>
<nmero caloras="120">cabrales</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="chocolate">helado</nmero>
<nmero caloras="250" frutas="manzanas">tarta</nmero>
<nmero caloras="400">crema catalana</nmero>
</postres>
</menu>
<menu tipo="economico">
<entrantes>

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
<nmero caloras="50">pan</nmero>
</entrantes>
<platos>
<nmero caloras="1700">jamn</nmero>
</platos>
<quesos>
<nmero caloras="240">manchego</nmero>
</quesos>
<postres>
<nmero caloras="340" sabor="sorbete">helado</nmero>
</postres>
</menu>

ElobjetivodeLINQerahacerconsultasyextraercontenidodeundocumentoXML.Porestemotivo,vamosaver
cmoescribirunaconsultaLINQenundocumentoXML.Paraempezar,vamosabuscarlasentrantesdisponiblesen
losdiferentesmens.

DespusdecargarelarchivoenunobjetoXDocument,vamosautilizarunaconsultaLINQparabuscarlalistadelos
elementoscuyonmeroesentrantes.

Dim doc As Xdocument


doc = XDocument.Load("c:\restaurante.xml")

Dim listaEntrantes As IEnumerable(Of Xelement)


listaEntrantes = From ent In doc.Root.Descendants("entrantes")
Select ent

Dim s As Xelement
For Each s In listaEntrantes
Console.WriteLine(s)
Next

Acontinuacinsemuestraelresultadodelaejecucin,quecorrespondealoqueesperbamos.

<entrantes>
<nmero caloras="50">rbano</nmero>
<nmero caloras="300">pasta</nmero>
<nmero caloras="350">salchichn</nmero>
</entrantes>
<entrantes>
<nmero caloras="50">pan</nmero>
</entrantes>

Enelsegundoejemplo,vamosabuscarlosalimentosconunnmerodecalorassuperiora1.000.

Comoenelejemploanterior,vamosabuscarloselementospornombreyluegoaplicaremosunarestriccinsobreel
atributocaloras.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Dim alimentos As IEnumerable(Of XElement) =
From al In doc.Root.Descendants("nmero")
Where al.@caloras > 1000
Select al

For Each s In alimentos


Console.WriteLine(s)
Next

Obtenemoslasiguientelista,quecorrespondealosalimentosmsenergticos.

<nmero caloras="2000">cocido</nmero>
<nmero caloras="1700">cuscs</nmero>
<nmero caloras="1700">jamn</nmero>

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Introduccin

Ahoraquesuaplicacinestterminada,probada,depuraday,porlotanto,funcionasinproblemas,eselmomentode
pensarenlamaneradeponerlaadisposicindelosusuarios.Haydossolucionesposibles:

l LatecnologadeimplementacinWindowsInstaller.Laaplicacinesempaquetadaenunoovariosarchivosqueluego
sedistribuyenalosusuarios.EstosejecutanelarchivoSetup.exeparainstalarlaaplicacin.

l La implementacin ClickOnce. Con esta solucin, la publicacin de los archivos de la aplicacin se hace de forma
centralizadayelusuarioinstalaoejecutalaaplicacinapartirdeestaubicacin.

Acontinuacinvamosadetallarcadaunadeestastcnicasdeimplementacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
ImplementacinconWindowsInstaller

Microsoft Windows Installer es un servicio de instalacin y configuracin de aplicaciones disponible en todos los
sistemasoperativosdeMicrosoft.ElprincipiobsicodelfuncionamientodeWindowsInstallerresideenlaagrupacin
en un nico elemento de todos los datos e instrucciones necesarios para la implementacin de una aplicacin.
Representa una evolucin importante respecto a los procedimientos de instalacin clsicos, que consistan
principalmenteenfacilitarelconjuntodelosarchivosnecesariosparaelfuncionamientocorrectodelaaplicacinyun
scriptencargadodecopiaresosarchivoseneldiscodurodelamquina.

Con Windows Installer, el sistema conserva un rastro de todas las operaciones efectuadas durante la instalacin:
directorios creados, archivos copiados, entradas del registro modificadas, etc. Estos datos se utilizan durante la
desinstalacindelaaplicacin,momentoenqueWindowsInstallerefectalasoperacionesinversas.Sinembargo,se
realiza un control para garantizar que ninguna otra aplicacin necesite un archivo, una clave de registro o un
componente que est a punto de ser eliminado. Esta verificacin permite asegurar que la eliminacin de una
aplicacinnoconllevaproblemasdefuncionamientoenotraaplicacin.

Windows Installer tambin gestiona la reparacin de una aplicacin al reinstalar automticamente los archivos que
faltanquehubieranpodidosereliminados,porerror,amanosdelusuario.

El procedimiento de instalacin se efecta en el interior de una transaccin garantizando que la aplicacin ser
instaladacompletamenteoque,encasodefallodurantelainstalacin,elsistemavolversuestadoinicial.

En realidad, los procedimientos de instalacin son verdaderas aplicaciones. De hecho, son gestionados por Visual
Studiocomoproyectosnormales.

Laversin2012deVisualStudioyanointegralaherramientaquepermitacrearunproyectodeinstalacin.Estose
tienequehaceratravsdeunaherramientaexternaquesepuedaincluirdentrodeVisualBasic.Porlotanto,antes
decrearunproyectodeinstalacin,vamosavercmoobtenerestaherramientaeintegrarlaenVisualStudio.

1.InstalacindeInstallShieldLimitedEdition

Laprimeraetapaconsisteendescargarelprogramadeinstalacindelproducto.Estadescargaserealizaratravs
deunenlacealapginawebqueestdisponibleenlaopcindemenArchivoNuevoproyectoyactivandola
regla Instalado Plantillas Otros tipos de proyectos Instalacin e implementacin Habilitar InstallShield
LimitedEdition.

Aparecerlasiguientepgina.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
El enlace Vaya al sitio web de descarga le permite acceder al sitio web de la empresa FLEXERA Software, que
garantiza la distribucin del software. Debe rellenar el formulario de inscripcin antes de poder descargar el
producto. Hay que proporcionar una direccin de correo electrnico vlida porque se enviar un cdigo a esta
direccin para activar el producto antes de usarlo por primera vez. Puede ejecutar la instalacin directamente a
partirdelsitiodedescargaocopiarlocalmenteelarchivoydespusejecutarlainstalacinapartirdelacopialocal.
Esta ltima opcin es mejor porque facilita la vuelta atrs en caso de producirse un incidente, sin tener que
descargardenuevoelarchivo.EspreferiblequeVisualStudioestcerradoduranteelprocedimientodeinstalacin.
En caso contrario, ser necesario un reinicio. Lo primero que hace el programa de instalacin es actualizar su
sistemaparaintegrarloscomponentesquenecesitaInstallShield.

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
DespusdebeaceptarelcontratodelicenciayseleccionareldirectoriodeinstalacinparaInstallShield,antesde
copiarlosarchivos.Cuandoterminalacopiadearchivos,lasiguientepantallaleinformadelxitodelainstalacin.

La instalacin todava no ha terminado completamente, ya que falta la etapa de activacindel producto, que se
realizar durante la creacin del primer proyecto InstallShield Limited Edition. Se le pedir introducir su cdigo de
activacinocontinuarconunaversindeevaluacin,limitadaeneltiempo.

Si elige la opcin de activacin, la siguiente pantalla le permite introducir la clave de producto que se le ha
comunicadoaladireccindecorreoelectrnico,cuandoseinscribiparaladescargadelproducto.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
EstaoperacindeactivacinnecesitaunaconexinaInternetactiva.LainstalacindeInstallShieldLimitedEdition
haterminadoysolofaltadescubrirsuusodurantelacreacindeunproyectodedesarrollo.

2.Creacindeunproyectodeinstalacin

Elmtododecreacindeunproyectodeinstalacinesidnticoalutilizadoporcualquierotrotipodeproyectode
Visual Studio. En el men Archivo, seleccione Agregar, y luego Nuevo proyecto. En el cuadro de dilogo de
Agregar un proyecto, seleccione Otros tipos de proyecto y despus InstallShield Limited Edition Project. El
proyectoseaadeentoncesalasolucinactual.Elproyectoparaelquedeseacrearunprogramadeinstalaciny
elproyectoInstallShielddebenformarpartedelamismasolucinVisualStudio.

Unasistentelepermitecubrirlasdiferentesetapasdelaconfiguracindelproyectodeinstalacin.

Cada etapa cubre un aspecto concreto del funcionamiento del programa de instalacin. Con esta versin Limited

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Edition de InstallShield, algunas funcionalidades u opciones estn bloqueadas. Estas se identifican con el icono

.

a.Informacingeneral

Laprimeraetapadelasistenterecogelainformacingeneraldelaaplicacin.

Enestapantalladebeproporcionarlasiguienteinformacin

l Elnombredesuempresa.

l Elnombredelaaplicacin.

l Elnmerodeversindelaaplicacin.

l Elsitiowebdondeestdisponiblelainformacinadicionaldelaaplicacin.

l Eliconoasociadoalaaplicacin.

Esta informacin se utiliza durante la instalacin de la aplicacin. Tambin la utiliza la funcionalidad


correspondientealaopcinDesinstalarocambiarunprograma,delpaneldecontroldeWindows.

b.Requisitosprevios

Lasiguienteetapavaapermitirespecificarlosrequerimientosdelaaplicacinenrelacinconlaconfiguracindel
puestoenelquesevaainstalar.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
PuedeespecificarlasdiferentesversionesdeWindowsquepermitenlainstalacindelaaplicacin.Sidurantela
instalacin de la aplicacin no se detecta en la mquina ninguno de los sistemas operativos permitidos, se
muestraelsiguientecuadrodedilogoysedetienelainstalacin.

Si se respeta la primera condicin respecto a la presencia de una versin particular, se realiza una segunda
comprobacinparacontrolarlapresenciadeunaovariasaplicacionesenelpuesto.Comosucedeconlaprimera
verificacin,sifaltaalgunodeloselementosnecesarios,semuestrauncuadrodedilogoylainstalacintermina
justodespusdelcierredeestecuadrodedilogo.Enestecaso,noserealizaningunamodificacinenelpuesto
cliente.

LasiguienteetapanoesconfigurableconlaversionLimitedEditiondeInstallShield.Portanto,pasamosalaetapa
nmerocuatro,queeslamsimportantedelasistente.

c.Archivosdelaaplicacin

Estaetapaesverdaderamenteprimordialparaelcorrectofuncionamientodelaaplicacin,yaquedefinequseva
ainstalarydnde.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Estapantallasecomponededospaneles:

l Unpaneldenavegacinalaizquierda.

l Unapaneldeinformacinaladerecha.

Elpaneldenavegacincontienelalistajerrquicadelascarpetasquecorrespondenalsistemadearchivosdel
ordenador de instalacin. Los nombres de las carpetas corresponden a las carpetas de Windows estndar. Los
tres botones de la pestaa de la derecha permiten agregar diferentes elementos. En la carpeta de aplicacin,
puede agregar por ejemplo una subcarpeta, un archivo o la opcin utilizada ms a menudo: una salida del
proyecto (los archivos creados por la compilacin de un proyecto). En esta etapa, podr indicar el proyecto que
deseainstalar.Elsiguientecuadrodedilogolepermiteelegirelproyectoyelementosquequiereinstalarenlos
puestosdelosclientes.

Para que la aplicacin pueda ejecutarse en el ordenador cliente, se debe seleccionar como mnimo la opcin
Resultadoprincipal.Porelcontrario,laopcinArchivosdecdigofuenteseutilizararamente.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
d.Accesosdirectoshacialaaplicacin

Para facilitar la ejecucin de la aplicacin por parte del usuario, es deseable proporcionar accesos directos que
eviten tener que buscar el ejecutable en el rbol del sistema de archivos. Esto es lo que ofrece la siguiente
pantalladelasistente.

AlmenosesnecesariodefinirunaccesodirectohacialaaplicacinenelmenInicio.Estoserepresentamediante
elelementoLaunchdelalista.Paracadaaccesodirectonuevo,puedeelegirsuemplazamiento,bienenelmen
Inicio o en el Escritorio (o los dos). Observe que, si se aade una carpeta con archivos ejecutables durante la
etapaanterior,estosaccesosdirectossecreanautomticamentehaciaesosejecutables.Sisetratadesimples
herramientas que necesita la aplicacin, posiblemente sea mejor eliminarlos para que no se pueda acceder
directamenteaellas.

e.Informacindelregistro

Estaeslapenltimaetapaylepermiteespecificarlasmodificacionesquesedebenrealizarenelregistrodurante
lainstalacindelaaplicacin.Sinoexisteningunaclaveenelregistrodelamquinadurantelaimplementacin,
seaadedurantelainstalacin.Esposibleagregarclavesdebajodecualquierclavedenivelsuperioreneleditor
delregistro.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Paraagregarunaclaveenelregistro,previamentedebeseleccionarunnododenivelsuperior,ounasubclave,y
enelmencontextualescogerlaopcinNew Key.Sedebevolveranombrarlaclave.

Se puede eliminar una clave simplemente con la opcinDelete del men contextual. Sin embargo, hay que ser
prudente,yaquelasupresindeunaclaveconllevalasupresindetodaslassubclavesyvalorescontenidosen
ella. Se visualiza un mensaje de aviso para alertarle de esta peligrosa situacin y para pedirle que confirme su
eleccin.

Tambin es posible especificar valores para las nuevas claves o modificar los valores existentes. Podr aadir
valores de tipo cadena, binario DWORD, Multi String y expandable String. Durante la instalacin, estos valores
estn escritos en el registro. Los valores existentes son sustituidos por valores especficos en el programa de
instalacin.

Esposibleagregarclavesyvaloresderegistroaunproyectodeimplementacinimportandounarchivoderegistro
(.reg).Estolepermitircopiarunaseccincompletadeunregistroexistentedeunasolavezparaganartiempo.
Los archivos de registro pueden crearse con la ayuda de herramientas como el editor del registro de Windows
(regedit.exe). Esta solucin es muy prctica para transferir al puesto de los usuarios una porcin de registro
recuperadaenelpuestoutilizadoparaeldesarrollodelaaplicacin.Elmencontextualdisponibleenelelemento
delRegistrodelordenadordedestinoproponelaopcinImportar,quepermiterealizarestaoperacin.Solotiene
queelegirelarchivo(.reg)quecontienelosdatosquedeseaimportar.

f.Configuracindeloscuadrosdedilogo

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
Durantelainstalacindelaaplicacin,semuestraunasucesindecuadrosdedilogoconobjetoderecogerla
informacinnecesariaparalainstalacindelaaplicacin.Estaltimaetapapermiteactuarsobrelaaparienciade
estoscuadrosdedilogo.

Enalgunoscasos,sernecesarioproporcionarunarchivoexternoconlainformacinquesedebevisualizarenel
cuadrodedilogo.Porejemplo,esteeselcasoparalaopcinquecontrolalavisualizacindelcontratodelicencia
delaaplicacin,quenecesitaelarchivoconformato.rftquecontieneelcontratodelicencia.

Comoresultadodeestasdiferentesetapas,elproyectodedesplieguedebeestarcorrectamenteconfigurado.Solo
faltagenerarelproyectoconlasolucincompleta.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
ImplementacinconClickOnce

ClickOnceesunatecnologadeimplementacinquepermitecrearaplicacionesWindowscuyaactualizacinpuedeser
efectuadaautomticamente.Lainstalacindeestetipodeaplicacinseefectaconunmnimodeintervencinpor
parte del usuario. Esta tcnica simplifica la etapa de implementacin, que a veces se transforma en un verdadero
rompecabezas. A menudo nos encontramos con los siguientes problemas durante la implementacin de una
aplicacin:

Actualizacindelaaplicacin

Conunmtododedespliegueclsico,cuandoestdisponibleunanuevaversindelaaplicacin,el
usuariodebe,engeneral,reinstalarlaaplicacinparaaprovecharesaactualizacin.Latecnologa
ClickOnceescapazdefacilitarlasactualizacionesautomticamente.Enestecaso,solosedescarganlas
partesdelaaplicacinquehancambiado,yluegolaaplicacincompletayactualizadasereinstala
automticamentedesdeunanuevacarpeta.

Componentescompartidos

Lasaplicacionesdependenamenudodecomponentescompartidosdeahlaexistenciadeunriesgode
conflictodeversiones.EnelcasodeunaimplementacinconClickOnce,cadaaplicacinesautnomay
nopuedeinterferirconlasotras.

Autorizacindeseguridad

Engeneral,lainstalacindeunaaplicacinconunmtodoclsicoexigeautorizacionesadministrativas
enelpuestodetrabajodondeseefectalainstalacin.LaimplementacinconClickOnceautorizaalos
usuariosquenotienenprivilegiosadministrativosaefectuarlainstalacinysololesatribuyelas
autorizacionesdeseguridaddeaccesoalcdigonecesariasparaelbuenfuncionamientodela
aplicacin.

A veces, todas estas exigencias han conducido a los desarrolladores a elegir una tecnologa Web en lugar de
aplicaciones Windows clsicas, simplemente para beneficiarse de las facilidades de implementacin de este tipo de
aplicaciones. La contrapartida de esta eleccin se encuentra en una reactividad menor de la aplicacin y en una
interfazdeusuariomenoselaborada.LatecnologaClickOncehacequelaimplementacindeaplicacionesWindows
seatansencillacomolaimplementacindeaplicacionesWeb.CualquieraplicacindeconsolaodeWindowsFormes
sepuedepublicarconClickOnce. Haytrestcnicasdepublicacindisponibles:

l ApartirdeunapginaWeb.

l Apartirdeunacomparticindearchivosdered.

l ApartirdeunsoportecomoCDRomoDVD.

Laejecucindelaaplicacindisponededosvariantes.Sepuedeinstalarenelordenadordeunusuarioyejecutarse
inclusosinotieneconexin.Tambinsepuedeejecutarnicamenteenmodoenlneasininstalarningnelementode
manerapermanenteenelordenador.LasaplicacionesClickOnceestnaisladasunasdeotras,ylainstalacinola
ejecucindeunaaplicacinnopuedeinterrumpiraplicacionesexistentes.Pordefecto,lasaplicacionesClickOncese
ejecutanenlaszonasdeseguridaddeInternetodelaIntranet.Enfuncindelasnecesidades,laaplicacinpuede
exigirautorizacionesdeseguridadmselevadas.

Laactualizacindelaaplicacintambinpuedetenervariosmodosdefuncionamiento.Puedenserautomticosen
estecaso,laaplicacinverificaencadainiciosihayactualizacionesdisponibles,yluegolasinstalaautomticamente.
El usuario puede comprobar de forma manual la existencia de una actualizacin y decidir o no su instalacin. El
administradorpuedeconvertirenobligatorialainstalacindeunaactualizacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 1-
1.PrincipiodefuncionamientodeClickOnce

ElmecanismodeimplementacindeClickOncesebasaendosarchivosXMLllamadosmanifiestos:

l Unmanifiestodeaplicacin.

l Unmanifiestodeimplementacin.

El manifiesto de aplicacin describe la propia aplicacin, los ensamblados y los archivos que la componen, las
dependencias, las autorizaciones requeridas para la ejecucin y la ubicacin donde estn las actualizaciones
disponibles.

Elmanifiestodeimplementacindescribecmoseimplemetarlaaplicacin,incluyendolaubicacindelmanifiesto
de aplicacin y la versin de la aplicacin que deben ejecutar los clientes. Estos dos archivos son generados por
VisualStudio.

Elmanifiestodeimplementacinsecopiaenlaubicacindelaimplementacin.Estaubicacinpuedeserunservidor
Web,undirectoriocompartidoenlaredosoportesmviles,comounCDRom.Elmanifiestodeaplicacinytodoslos
archivos de la aplicacin tambin se copian en una ubicacin de implementacin especfica en el manifiesto de
implementacin.Sepuedencopiarestosarchivosenlamismaubicacinoendosubicacionesdistintas.VisualStudio
tambinseencargadelascopiasdeestosarchivos.

Despusdelaimplementacindelaaplicacinenlaubicacindelaimplementacin,losusuariospuedendescargar
e instalar la aplicacin haciendo clic en el icono que representa el archivo del manifiesto de implementacin
disponibleenunapginaWeboenunacarpeta.Elusuariosoloveruncuadrodedilogoquelepideconfirmarla
instalacin.

Despus de la validacin, la instalacin contina y se lanza la aplicacin sin otra intervencin. Si la aplicacin
requiere autorizaciones de ejecucin ms elevadas, el cuadro de dilogo pide al usuario que conceda las
autorizacionesparaquelainstalacinpuedaproseguir.

LaaplicacinseaadealmenIniciodelusuarioyalaseccinAgregaroquitarprogramasdelPaneldecontrol.A
diferencia de otras tecnologas de implementacin, no se aade nada a la carpeta Program Files, en la base de
registrooenelescritorio.Adems,noesnecesarioningnderechodeadministracinparalainstalacin.

Cuando crea una versin actualizada de la aplicacin, tambin debe generar un nuevo manifiesto de aplicacin y
copiar los archivos en la ubicacin de la implementacin, en general una carpeta similar a la carpeta de la
implementacinoriginal.Tambinsedebeactualizarelmanifiestoparaqueapuntehacialaubicacindelanueva
versindelaaplicacin.

2.Losdiferentesmtodosdeimplementacin

Para implementar una aplicacin ClickOnce, hay tres estrategias posibles. La estrategia que elija depende
principalmentedeltipodeaplicacinquevaaimplementar.Lastresestrategiassonlassiguientes:

l InstalacindesdelaWebounaredcompartida.

l InstalacindesdeunCDRom.

l ArranquedelaaplicacindesdelaWebounaredcompartida.

InstalacindesdelaWebounaredcompartida

- 2- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
EstaestrategiapermiteimplementarlaaplicacinenunservidorWebounaredcompartida.Cuandounusuariofinal
desea instalar la aplicacin, debe hacer clic en un icono de una pgina Web o doble clic en un icono de archivos
compartidos.Luegosedescarga,instalayarrancalaaplicacinenelordenadordelusuario.Algunoselementosse
aadenalmenInicioyalgrupoAgregaroquitarprogramasenelPaneldecontrol.

Puesto que esta estrategia depende de la conexin de red, funciona de manera ptima para las aplicaciones
implementadasporusuariosconaccesoaunaredlocalounaconexinrpidaaInternet.

InstalacindesdeunCDRom

Esta estrategia permite implementar la aplicacin en un soporte mvil, como un CDRom o un DVD. Como para la
opcinanterior,cuandoelusuarioeligeinstalarlaaplicacin,estaserinstalada,lanzadayalgunoselementosse
agregarnalmenInicioyalgrupoAgregaroquitarprogramasenelPaneldecontrol.

Estaestrategiafuncionamejorenelcasodeaplicacionesimplementadasenordenadoresdeusuariossinconexin
alaredocuyaconexinaInterneteslenta.Comolaaplicacinestinstaladaapartirdeunsoportemvil,noes
necesarianingunaconexinparalainstalacinsinembargo,sloesparalasactualizacionesdelaaplicacin.

ArranquedelaaplicacindesdelaWebounaredcompartida

Estaestrategiaessimilaralaprimera,exceptoporquelaaplicacinactacomounaaplicacinWeb.Laaplicacin
seejecutacuandoelusuariohaceclicenunhipervnculodeunapginaWeb(odobleclicenunrecursocompartido).
Cuando los usuarios cierran la aplicacin, esta ya no est disponible en el ordenador local. Ningn elemento se
aadealmenIniciooalgrupoAgregaroquitarprogramasenelPaneldecontrol.Tcnicamente,laaplicacinse
descargaeinstalaenuncachdelaaplicacindelordenadorlocal,delamismamaneraqueunaaplicacinWebse
descargaenelcachWeb.ComoparaelcachWeb,losarchivossoneliminadosdelcachdelaaplicacinalfinal
delautilizacin.Sinembargo,elusuariotienelaimpresindequelaaplicacinseejecutadesdelaWebolared
compartida.

Estaestrategiaespreferibleparalasaplicacionesqueseutilizanpoco.

3.Lasactualizacionesdelaaplicacin

ClickOnce puede facilitar automticamente las actualizaciones de la aplicacin. Una aplicacin ClickOnce lee
peridicamentesuarchivomanifiestodeimplementacinparacomprobarsilasactualizacionesdelaaplicacinestn
disponibles.Siestdisponible,lanuevaversindelaaplicacinsedescargayejecuta.Porrazonesdeeficacia,solo
sedescarganlosarchivosmodificados.

Haytresestrategiasbsicasposiblesparalasactualizaciones:

l Laverificacindelasactualizacionesduranteelarranquedelaaplicacin.

l La verificacin de las actualizaciones despus del arranque de la aplicacin (ejecutada en un thread de segundo
plano).

l Lapresentacindeunainterfazdeusuariodestinadaalasactualizaciones.

Tambinsepuededeterminarlafrecuenciadeverificacindelasactualizacionesquedebeefectuarlaaplicacino
configurarunaactualizacinobligatoria.Lasactualizacionesdeaplicacinexigenunaconexinalared.Enausencia
deunaconexin,laaplicacinseejecutasinverificarlasactualizaciones,seacualsealaestrategiadeactualizacin
elegida.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 3-
Verificacindelasactualizacionesdespusdelarranque

Pordefecto,laaplicacinintentalocalizaryleerelarchivomanifiestodeimplementacinensegundoplanodurante
su ejecucin. Si una actualizacin est disponible, se invitar al usuario a descargar e instalar la actualizacin
durantelaprximaejecucin.

Esta estrategia se adapta particularmente a las conexiones de banda ancha restringida o a las aplicaciones
voluminosasquepuedannecesitardescargaslargas.

Verificacindelasactualizacionesduranteelarranque

Con esta estrategia, la aplicacin intenta localizar y leer el archivo manifiesto de implementacin en cada
lanzamiento. Si una actualizacin est disponible, se descargar y ejecutar. En caso contrario, se ejecutar la
versinexistentedelaaplicacin.

Estaestrategiaseadaptabienalasconexionesdebandaancha.Elplazonecesarioparainiciarlaaplicacinpuede
serinaceptableenconexionesquenoseandebandaancha.

Actualizacionesobligatorias

Avecesesnecesarioobligaralosusuariosaejecutarunaversinactualizadadelaaplicacinsi,porejemplo,seha
modificadounrecursoquepuedaperturbarelfuncionamientodesuantiguaversin.Enestecaso,puedemarcarla
actualizacincomoobligatoriay,porlotanto,impedirlaejecucindeunaversinmsantiguadelaaplicacin.Se
debeasociarestaestrategiaconlaverificacindelasactualizacionesduranteelarranque.

Intervalosdeactualizacin

En el marco de las actualizaciones automticas, se puede especificar la frecuencia de verificacin de las


actualizaciones. Por ejemplo, puede desear una verificacin con cada ejecucin de la aplicacin, una vez a la
semanaounavezalmes.Siningunaconexinredestdisponibleenelmomentoespecificadoparalaverificacin,
estaseefectaconlaprximaejecucindelaaplicacin.

Bloqueodelasactualizaciones

Tambinesposiblehacerquesuaplicacinnoseactualicenunca.Puede,porejemplo,implementarunaaplicacin
sencillaquenonecesiteseractualizada,peroutilizarlaventajaqueofreceClickOnceparasuinstalacin.

4.PuestaenmarchadelapublicacinClickOnce

LapublicacindeunaaplicacinconlatecnologaClickOnceestfacilitadaporunasistentequepermiterecogerla
mayora de los datos necesarios para la implementacin. Este asistente est disponible en el explorador de
soluciones al elegir la opcin Publicar del men contextual del proyecto que se va a implementar. Sin embargo,
algunasopcionesdelaimplementacinnosongestionadasporesteasistenteydebenconfigurarsemanualmentea
travselcuadrodedilogodelaspropiedadesdelproyecto.

Laprimeraetapadelasistenteconsisteenconfigurarlaubicacindondesedebehacerlapublicacin.

- 4- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Estaubicacinpuedeser:

l Undirectoriodelamquina.

l Un directorio compartido en otra mquina indicando una ruta UNC de la siguiente manera \\nombre de la
mquina\nombredeldirectorio.Esnecesariotenerlaautorizacindeescribirsobrelaparticinparaquelapublicacin
sepuedarealizar.

l El servidor Web IIS de la mquina en el que previamente se habr agregado un directorio virtual para acoger los
archivos.

l UnservidorFTPcuyainformacindeconexindebefacilitarusandoelcuadrodedilogosiguiente:

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 5-
Debeindicar:

l LadireccinIPoelnombredelservidorFTP.

l Elnmerodelpuertoutilizadoparacontactarconelservidor(engeneral,21).

l Eldirectoriodelservidorenelqueseefectuarlacopiadelosarchivos.Necesitartenerlaautorizacindeescritura
enestedirectorio.

l Siseprotegeconunfirewall,asegresedeactivarlaopcinModopasivo.

l Siustedseconectademaneraannimao,encasocontrario,elnombredeusuarioylacontraseautilizadosparala
conexin.

Lasegundaetapadeterminacmovanainstalarlaaplicacinlosusuarios.

- 6- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
Lasopcionesposiblesson:

l DesdeunsitioWebcuyaURLsedebeindicar.

l Desde un recurso compartido cuya ruta de acceso UNC deber especificar. Por supuesto, los usuarios deben tener
derechodelecturaenelrecursocompartido.Elderechodeescrituranoesobligatorioeinclusomuydesaconsejado.

l Desde un CDRom o DVD que usted proporcionar. La creacin de este soporte no la realiza el asistente y se debe
efectuarconunaaplicacindegrabacinexterna.

La ltima etapa visualiza un resumen de los datos seleccionados y permite lanzar la publicacin con el botn
Finalizar.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 7-
Al final de la instalacin, se abre una pgina HTML en la ubicacin utilizada durante la publicacin que permite el
arranquedelainstalacinolaejecucindelaaplicacin.

- 8- Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LasopcionesdeimplementacinmsespecficassedebenconfigurarconlaseccinPublicardelaspropiedadesdel
proyecto.Estecuadrodedilogoreanudalaspropiedadesconfiguradasporelasistentedepublicacin.

LosbotonesArchivosdeaplicacin,Requisitosprevios,ActualizacionesyOpcionespermitendarelltimotoque
alosajustes.

Elbotn Archivosdeaplicacinmuestraelsiguientecuadrodedilogorelativoalosarchivosqueconstituyenla
aplicacin.

Elestadodelapublicacindecadaarchivosepuedeconfigurarcontresvaloresdiferentes:

l Incluir: elarchivoestardisponibleparalosusuariosenelsoportedeimplementacin.

l Excluir: elarchivonosecopiaenelsoportedeimplementacin.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 9-
l Archivo de datos: el archivo contiene datos necesarios para el correcto funcionamiento de la aplicacin y ser
incluidoenlapublicacin.

El botn Requisitos previos se utiliza para configurar los elementos necesarios para el funcionamiento de la
aplicacin.

Puede optar por crear un programa de instalacin para los componentes que requiere el funcionamiento de la
aplicacinmarcandolacasillaCrearprogramadeinstalacinparainstalarloscomponentesnecesarios.Sedebe
elegir los componentes correspondientes en la lista presentada. Tambin debe indicar desde qu ubicacin se
instalarnestoscomponentes.Haytresopcionesposibles:

l DesdeelsitioWebdelproveedordelcomponente.

l Desdelamismaubicacinquelautilizadaparainstalarlaaplicacin.

l Desdelaubicacinindicada.

La configuracin de las actualizaciones prevista durante la utilizacin del asistente puede ser modificada con el
botnActualizaciones.

- 10 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
LacasillaLaaplicacindebebuscaractualizacionesespecificaquelaaplicacindebeverificarladisponibilidadde
actualizacionesenelmomentodesuinstalacin.Siseleccionaestaopcin,lasotrasopcionesestarndisponibles.
Permitenelegirelmomentoenelquetendrlugarlaverificacindeladisponibilidaddeunaactualizacin.Laopcin
Antes de que se inicie la aplicacinindicaquelaaplicacindebeverificarladisponibilidaddelasactualizaciones
antes del arranque. Esto garantiza que los usuarios conectados a la red siempre disponen de la versin ms
reciente de la aplicacin. Esta opcin puede ralentizar el arranque de la aplicacin en el caso de que existan
actualizaciones disponibles. La opcin Despus de que se inicie la aplicacin planifica la ejecucin de la
actualizacinduranteelprximoarranquedelaaplicacin.Lafrecuenciadelasactualizacionestambinsepuede
indicar en horas, das o semanas, o bien ejecutarse cada vez que arranca la aplicacin. Tambin puede indicar la
ubicacinapartirdelacualestndisponibleslasactualizaciones,siestaesdiferentedelaubicacindeinstalacin.

Elltimobotnsirveparaconfigurarvariasopcionesdeimplementacin.

Lasopcionessiguientesestndisponibles:

Idiomadepublicacin

Especificaelidioma(ylosparmetrosregionales)enelquesepublicalaaplicacin.

Nombredeleditor

Especificaelnombredeleditordelaaplicacin.Siestazonaestvaca,seusarelvalordela
propiedadRegisteredOrganizationdelordenador.Siestevaloresnulo,seutilizaelnombredel
proyectoutilizado.

Nombredelproducto

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 11 -
Especificaelnombredeleditordelaaplicacin.Siestazonaestvaca,seutilizaelnombredel
ensamblado.

DireccinURLdesoporte

EspecificaunsitioWebquecontienedatosdesoporteparalaaplicacin.LaespecificacindeestaURL
esfacultativa.Perosiseutiliza,estaURLapareceenlaentradaAgregaroquitarprogramasdela
aplicacinenelPaneldecontroldeWindows.

ImplementacindelapginaWeb

EspecificaunnombreparalapginaWebdeimplementacin.Elnombredelarchivopordefectoes
Publish.htm.

GenerarautomticamentelapginaWebdeimplementacindespusdecadapublicacin

Siestaopcinestseleccionada,elprocesodepublicacingeneraunapginaWebdeimplementacin
encadapublicacin.EstaopcinsoloestdisponiblesiseespecificaunapginaWebde
implementacin.

AbrirlapginaWebdeimplementacindespusdepublicar

Siseseleccionaestaopcin,lapginaWebdeimplementacingeneradaautomticamenteseabre
despusdelapublicacin.

BloquearlaaplicacinparaquenoseactivemedianteunadireccinURL

Siestaopcinestdesactivada,laaplicacinseejecutaautomticamentedespusdelainstalacin.Si
estactivada,elusuariodeberarrancarlaaplicacindesdeelaccesodirectodelprogramaenel
menInicio.

Utilizarlaextensindearchivo.deploy

Siestopcinestseleccionada,elarchivodeimplementacinutilizalaextensin.deploy.Algunos
servidoresWebestnconfiguradosparabloquear,porrazonesdeseguridad,losarchivosqueno
suelenestarpresentesenunsitioWeb.Porejemplo,losarchivosquellevanlasextensiones
siguientessepuedenbloquear: .dll,.config,.mdf.LasaplicacionesWindowssuelencontenerarchivos
conalgunasdeestasextensiones.SiunusuariointentaejecutarunaaplicacinClickOncequeaccede
aunarchivobloqueadoenunservidorWeb,seproduceunerror.Envezdedesbloqueartodaslas
extensionesdelarchivo,sepublicacadaarchivodeaplicacinpordefectoconunaextensindearchivo
.deploy.Silaopcinseutiliza,elservidorWebsolodebeestarconfiguradoparadesbloquearlas
tresextensionesdearchivossiguientes:

n .application

n .manifest

n .deploy

PermitirquesepasenlosparmetrosdeladireccinURLalaaplicacin

Pordefecto,estaopcinestdesactivada.Siestaopcinestactivada,laaplicacinsercapazde
accederytratarlosdatosdelosparmetrosdelaURL.

- 12 - Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca
EnlasinstalacionesdesdeCD,elprogramadeinstalacinseiniciaautomticamentealinsertarelCD

Siestaopcinestseleccionada,seaadeunarchivoAutorun.infalarazdelsoporteparalas
aplicacionesClickOncequeseinstalandesdeunCDRomoDVDRom.

Comprobarlosarchivoscargadosenunservidorweb

Siestaopcinestactivada,elprocesodepublicacindescargacadaarchivoparaverificarque
efectivamentesepuedendescargar,yleinformardelosarchivosquenosepuedendescargar.

Usarelmanifiestodelaaplicacinparalainformacindeconfianza

Cuandoestaopcinestseleccionada,puedefirmardenuevoelmanifiestodelaaplicacinconla
ayudadeuncertificadoquecontienesuspropiosdatos.

Editions ENI Tous droits rservs Copie personnelle de henry Zacarias Ingaruca - 13 -

Potrebbero piacerti anche