Sei sulla pagina 1di 217

INDICE

1. Arreglos Bidimensionales
http://www.elguille.info/colabora/puntoNET/FernandoLuque_Arrays_Bidimensionales.
htm
2. Barras de Herramientas y Menús en Visual Basic .Net
http://www.elguille.info/colabora/NET2005/FernandoLuque_MenusBarras.htm
3. Controles en Visual Basic .Net – El control ChechedListBox
http://www.elguille.info/colabora/puntoNET/FernandoLuque_Controles.htm
4. Consumiendo XML Web Services
http://www.elguille.info/colabora/NET2005/FernandoLuque_WebServiceBD.htm
5. Controlando Eventos y Arrays
http://www.elguille.info/colabora/NET2005/FernandoLuque_Controlando_Eventos_y_
Arreglos.htm
6. El control ComboBox
http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ComboBox.ht
m
7. El Control ListBox – Opciones Principales
http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ListBox.htm
8. Maestro – Detalle. Clientes y Órdenes
http://www.elguille.info/colabora/NET2005/FernandoLuque_MaestroDetalleSimple.ht
m
9. Mantenimiento de Categorías usando Northwind
http://www.elguille.info/colabora/NET2005/FernandoLuque_MatenimietoCateg.htm
10. Usando SQLDataReaders – Entornos conectados
http://www.elguille.info/colabora/NET2005/FernandoLuque_Usando_SQLDataReader.
htm
11. El control ListView –Parte I
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
12. Formateando el control DataGrid
http://www.elguille.info/colabora/NET2005/FernandoLuque_FormateandoDataGrid.ht
m
13. El control ListView (II)
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
14. Navegando en un sitio Web
http://www.elguille.info/colabora/NET2005/FernandoLuque_ASPSinLogin.htm
15. Controles de lista en Visual Basic .Net
http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesBasicos.htm
16. Iniciando en ASP .Net
http://www.elguille.info/colabora/NET2005/FernandoLuque_IniciandoASP.htm
17. El Control ListView III
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm
18. Uso de DataBindings
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataBinding.htm
19. Ordenar y Filtrar un DataView
http://www.elguille.info/colabora/NET2005/FernandoLuque_FiltrosOrdenamientos.htm
20. Controles de Lista enlazados a Base de datos
http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm
21. DataSets Tipificados y No Tipificados I
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm
22. El Control TabControl – Manejo de los TabPages
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_TabControl.htm
23. DataSets Tipificados y no Tipìficados II
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm
24. Llenar un control DataGrid y actualizarlo
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetI.htm
25. Examinar una tabla con claves foráneas
http://www.elguille.info/colabora/NET2005/FernandoLuque_ExaminarTabla01.htm
26. Typed DataSet – Ejercicio
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetII.htm
27. Borrar el contenido de controles I
http://www.elguille.info/colabora/NET2005/FernandoLuque_BorrarContenidos.htm
28. El control ListView usando Base de datos
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewBD.htm
29. Typed DataSet – Ejercicio
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSet03.htm
30. El Control TreeView
http://www.elguille.info/colabora/NET2005/FernandoLuque_TreViewBDatos.htm
31. GDI+ Gráficos en Visual Basic: Textos Artísticos
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm
32. GDI+ Gráficos en Visual Basic: Textos con sombra
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto02.htm
33. GDI+ Gráficos en Visual Basic: Textos en contorno
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto03.htm
34. GDI+ Gráficos en Visual Basic: Textos Block, Cursiva y Reflejo
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto04.htm
35. Borrar el contenido de los controles II
http://www.elguille.info/colabora/NET2005/FernandoLuque_BorrarContenidosII.htm
36. GDI+ Crear gráficos permanentes
http://www.elguille.info/colabora/NET2005/FernandoLuque_GraficosPermanentes.htm
37. DataBindings en Visual Basic .Net
http://elguille.info/colabora/NET2005/FernandoLuque_DataBindings.htm
38. Aplicaciones en N-Capas usando Visual Basic .Net
http://elguille.info/colabora/NET2005/FernandoLuque_NCapas.htm
39. Creando un Explorador de Windows usando Clases de componente
http://www.elguille.info/colabora/NET2005/FernandoLuque_Explorador01.htm
40. Creando un Explorador usando el IDE
http://elguille.info/colabora/NET2005/FernandoLuque_Explorador02.htm
41. GDI+ Trabajando con Lápices (Pens)
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDILapices.htm
42. Herencia en Visual Basic .Net
http://elguille.info/colabora/NET2005/FernandoLuque_HerenciaNet.htm
43. Usando Hojas de Estilos en Cascada en Aplicaciones Web con ASP .Net
http://www.elguille.info/colabora/NET2005/FernandoLuque_ASPEstilos.htm
44. Controles de Validación en Aplicaciones Web ASP .Net
http://www.elguille.info/colabora/NET2005/FernandoLuque_ASPValidar.htm
45. Usando Store Procedures en Aplicaciones Web ASP .Net
http://www.elguille.info/colabora/NET2006/FernandoLuque_SP_en_ASP.htm
46. Leer y escribir archivos XML en aplicaciones Web ASP .Net
http://www.elguille.info/colabora/NET2006/FernandoLuque_ASPyXML.htm
47. Uso de XMLDataDocument en aplicaciones Web ASp .Net
http://www.elguille.info/colabora/NET2006/FernandoLuque_ASPyXML_02.htm
48. Filtrando DataViews usando Fechas
http://www.elguille.info/colabora/NET2006/FernandoLuque_DataViewFiltro.htm
49. Combos con datos relacionados
http://www.elguille.info/colabora/NET2006/FernandoLuque_CombosListViewStatusBa
r.htm

Arreglos en Visual Basic .Net


Uso de Arreglos de dos dimensiones

El presente trabajo pretende colaborar con el conocimiento de Visual Basic .Net y de las
opciones especificas de los arreglos de dos dimensiones. El ejemplo maneja dos arrays
bidimensionales que tienen relación (ya se que podría hacerse usando DataSet y
DataTables), pero la idea del ejercicio es justamente el manejo de arrays
bidimensionales.

Un poco de teoría

Los Arrays o arreglos son conjuntos de Variables Agrupadas con un nombre, que se
pueden manejar juntas o individualmente, en Visual Basic .Net se pueden tener arreglos
desde una dimensión y hasta un máximo de 32 dimensiones.

Como se definen

Para definir un arrays se utiliza Dim, Private, Friend o Public según el alcande del
mismo, por ejemplo la orden:

Dim Cursos( , ) As String

Define el array Cursos sin asignarle la cantidad de elementos de cada dimensión. El


array anterior tendrá que redefinirse a nivel de procedimiento usando la instrucción
Redim, está funciona unicamente cambiando el tamaño de la última dimensión.
Generalmente se usa una variable que va aumentando, suponer que la variable
Incluidos es la utilizada, la instrucción podría ser como la siguiente:

Redim Cursos(2,Incluidos)

y para conservar los datos actuales en el Array se utiliza la palabra Preserve:

Redim Preserve Cursos(2,Incluidos)


Algo de lo que contiene

Todos los elementos del arrays deben ser del mismo tipo.En Visual Studio .Net los
arrays derivan de la clase Arrays del NameSpace System. Esta Clase (Array)
proporciona los métodos para crear, manipular, realizar busquedas y ordenación de
arrays.

Un elemento es un valor de Array, al que se puede acceder haciendo uso del indice o
indices según las dimensiones. Por ejemplo, para acceder al elemento de la segunda fila
y la tercera columna del arrays bidimensional con nombre Cursos se debe escribir
Cursos(1,2), cabe adelantar que en Visual Basic .Net el valor inicial de cada dimensión
es CERO. El método GetLowerBound permite obtener el límite inferior de una
determinada dimensión. Para el límite superior de la dimensión especificada se utiliza el
método GetUpperBound.

La longitud de Array es el número total de elementos que puede contener. El método


GetLength permite obtener el número de elementos de un array.

El rango de Array es el número de dimensiones de Array. La Propiedad Rank permite


obtener el número de dimensiones de una array.

Ahora mi ejercicio

El sistema de control de Matriculas de un instituto es muy lento, se necesita que los


datos puedan procesarse de manera mas rápida y segura, se decide hacer un sistema por
computadora; este deberá registrar según los siguientes productos descritos en la tabla:

Cod. Producto Descripción


IES Computación e Informática
SEC Secretariado Ejecutivo
DBS Da Bussines

De acuerdo a los Productos antes registrados pueden crearse cursos o


promociones, el sistema ingresará y pedirá: Número de la promoción en el formato
9999-XX donde las 9999 será el año actual y las XX el número del curso registrado en
el año, por ejemplo; 01, 02, 03, etc., también deberá registrarse la descripción del curso,
la fecha de inicio, el número de vacantes y la cantidad de matriculados.

Una vez registrado el o los cursos, se podrá matricular alumnos, de los cuales se
pedirá el ingreso de Apellidos, Nombres, teléfono y fecha de matricula. Los datos por
cada curso deben de registrarse y aparecer en un formulario de reporte.
Los datos de la tabla siguiente :

Producto Promociones Matriculados


2004-06 Luque Villacorta, Fernando

Computacion e Informática Telf. 9458548

Fecha de Inicio: 01/11/2004 Fecha: 25/10/2004

Vacantes: 25
Pereda Geronimo, Luis
IES
2004-07 Telf. 9444567
Computación e
Informática Computación e Informática Fecha: 28/09/2004
Terranova Carrion Esmeralda
Fecha de Inicio: 05/11/2004
Telf. 9499498
Vacantes: 20
Fecha: 30/09/2004
Hinostroza Ramirez Carlos

2004-10 Telf. 9645676

Secretariado Ejecutivo Fecha: 30/09/2004


Villacorta Acosta, Carol
Fecha de Inicio: 08/11/2004
Telf. 96442567
Vacantes: 30
SEC
Fecha: 30/09/2004
Secretariado
Bolivar Saldaña, Silvia
Ejecutivo
2004-12
Telf. 96656443
Secretariado Ejecutivo
Fecha: 30/09/2004
Sanchez Campos, Julia
Fecha de Inicio: 12/11/2004
Telf. 9644444
vacantes: 25
Fecha: 01/10/2004

Nota: Bajar el empaquetado del ejercicio para ejecutarlo, fue hecho con Visual Studio
2002.

A continuación sigue parte del código en Visual Basic:

En el Módulo:
'************* MODULO *******************

'Programación: Ing. Fernando Luque Sánchez

'Noviembre 2004

Module SistMatriculas

'Definicion de las variables para Productos

Public vProducto As String

'Para saber el Número de Promociones Aperturadas

Public vNumPromos As Integer

'Para saber el Número de Alumnos Matriculados

Public vNumAlumnos As Integer

'''' ARREGLOS PARA ALMACENAR LOS DATOS

'Para Alamcenar los datos de las promociones

Public aPromos(,) As String 'CódPromo, Descrip, Fecha, Vacantes, Matriculados

'Para Alamcenar los datos de los alumnos

Public aAlumnos(,) As String ' CodAlumno, CodPromo, Descrip,

' Nombre, Telefono y Fecha Matricula

'Para el Título del Reporte

Public VTitulo As String

'Datos de un Curso Aperturado

Public vDescrip As String

Public vCodigo As String


Public Vfechainicio As Date

Public vVacantes As Integer

'Para saber si los Formularios están abiertos

Public fPromosA As Integer

End Module

En el formulario Principal

Public Class frmPrincipal

Inherits System.Windows.Forms.Form

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

*** codigo eliminado

#End Region

Private Sub Reportes(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles mnuRepPromos.Click


If sender Is mnuRepPromos Then

'REPORTE SOLAMENTE DE LAS PROMOCIONES ABIERTAS

Dim NReporte As New frmReportes()

VTitulo = "Reporte de Promociones"

NReporte.ShowDialog()

ElseIf sender Is mnuRepAlumnosPromo Then

'Reporte de los alumnos por Promocion

Dim RepAlumnos As New frmRepAlumnxPromo()

RepAlumnos.ShowDialog()

End If

End Sub

Private Sub Salir(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles mnuSalir.Click

Application.Exit()

End Sub

'MUESTRA EL FORMULARIO DE INGRESO DE PROMOCIONES.

Private Sub mnuIngPromo_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles mnuIngPromo.Click

mnuIngPromo.Enabled = False

Dim iPromos As New frmPromociones()

iPromos.MdiParent = Me

iPromos.Show()

End Sub
'Procedimientos para la Inserción de Alumnos

Private Sub mnuIngAlumnos_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles mnuIngAlumnos.Click

Dim formAlumnos As New fAlumnosMatri()

Me.mnuIngAlumnos.Enabled = False

formAlumnos.ShowDialog()

End Sub

'ACERCA DE....

Private Sub AcercaDe(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MenuItem2.Click

Dim fAcerca As New frmAcerca()

fAcerca.ShowDialog()

End Sub

'Para determinar si el número de Promociones es Mayor a Cero

Private Sub mnuMoves_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles mnuMoves.Click, mnuMoves.Select

If fPromosA = 0 Then mnuIngPromo.Enabled = True _

Else mnuIngPromo.Enabled = False

If vNumPromos = 0 Then mnuIngAlumnos.Enabled = False _

Else mnuIngAlumnos.Enabled = True

End Sub
Private Sub mnuReporte_Select(ByVal sender As Object, ByVal e As
System.EventArgs) Handles mnuReporte.Select

If vNumPromos = 0 Then mnuRepPromos.Enabled = False _

Else mnuRepPromos.Enabled = True

If vNumPromos = 0 OrElse vNumAlumnos = 0 Then


mnuRepAlumnosPromo.Enabled = False _

Else mnuRepAlumnosPromo.Enabled = True

End Sub

End Class

Barras de Herramientas y menús en VB .Net

Sres. Desarrolladores, les envío un aporte, uso de Barras de Herramientas y menús


usando Visual Basic .Net.

Notas importantes:

 Actualice las conexiones a la Base de datos en el formulario de Productos.


 Establezca también conexión para el Reporte
 Algunos botones de la barra de Herramientas solo tienen un mensaje, el objetivo
es aprender a implementar el código para la selección de cada botón.
 También he incluido algo de interesante para los que les gusta el diseño,
ejecuten Acerca de, Programador

A continuación sigue código en Visual Basic:

Imports System.Drawing
Imports System.Drawing.Brush
Imports System.Drawing.Brushes
Imports System.Drawing.Bitmap
Imports System.Drawing.Drawing2D

Public Class frmPrincipal


Inherits System.Windows.Forms.Form

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


****** el código en esta zona ha sido eliminado...
#End Region

Private Sub Clickenbarra(ByVal sender As System.Object, ByVal e As


System.Windows.Forms.ToolBarButtonClickEventArgs) Handles
ToolBar1.ButtonClick
Select Case ToolBar1.Buttons.IndexOf(e.Button)
Case 0
MessageBox.Show("Implemente la opción deseada...", "Atención...")
Case 1
MessageBox.Show("El código no está implementado...", "Atención...")
Case 2
Dim miform As New frmLlenarGrid
miform.ShowDialog()
Case 5
If e.Button.Pushed = True Then
MessageBox.Show("Boton Activado", "Hola")
Else
MessageBox.Show("El botón está desactivado", "Hola")
End If
End Select
End Sub

Private Sub MenuItem5_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MenuItem5.Click
Dim resp As Integer
resp = MsgBox("Esta Seguro De Salir", MsgBoxStyle.YesNo, "Salir")
If resp = 6 Then
End
End If
End Sub

Private Sub MenuItem8_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MenuItem8.Click
Dim obrush As New HatchBrush(HatchStyle.Wave, Color.Aqua,
Color.DarkGreen)
'crear el tipo de letra
Dim ofont As New Font(New FontFamily("Georgia"), 50)
Dim ograf As Graphics = Me.CreateGraphics
ograf.DrawString("Net Desarrollo", ofont, obrush, New RectangleF(20, 20, 500,
200))

End Sub

End Class

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias. Cualquier consulta a los correos
que están al inicio del articulo.

Controles en Visual Basic .Net

Uso de CheckedListBox - TabControl


Opciones del control ListBox de .Net
El presente trabajo pretende colaborar con el conocimiento de Visual Basic .Net y de las
opciones nuevas de los controles CheckedListBox (nuevo en Visual Basic .Net),
TabControl, que es similar a los anteriores SSTaB y TabStrip de VisualBasic 6.0 y de
las opciones de ListBox

Un poco de teoría

El Control CheckedListBox

El control CheckedListBox muestra una lista de elementos similar a un control


ListBox, pero cada elemento tienen la apariencia de una casilla de verificación o control
CheckBox. El control CheckedListBox puede enlazarse a datos por medio de la
propiedad DataSource al igual que los controles ComboBox y ListBox, debe
establecerse el nombre de una columna del origen de datos a la propiedad
DisplayMember. El código suponiendo que el CheckedListBox se llama
chklProductos de la Tabla dtProductos del DataSet dsDatos y la columna es
NombreProducto es:

chklProductos.DataSource = dsDatos.Tables("dtProductos")
chklProductos.DisplayMember = "NombreProducto"

El control CheckedListBox al igual que el control ListBox tienen la colección Items a la


que se le agrega elementos, puede ser individualmente o de manera grupal con un
arreglo o matriz. Por ejemplo:

Para agregar un elemento al control chklPromovidos se escribe lo siguiente

chklPromovidos.Items.Add("María Fernanda")

Para agregar un arreglo a chklPromovidos se utiliza AddRange: (de manera similar en


un ListBox y un ComboBox)

Dim aPromovidos(3) as String


aPromovidos(0) = "Fernando"
aPromovidos(1) = "Carolina"
aPromovidos(2) = "María Fernanda"
aPromovidos(3) = "Fernandito"

chklPromovidos.Items.AddRange(aPromovidos)

Para eliminar una opción se utiliza Remove cuando se usa el texto de la opción y
RemoveAt cuando usamos el índice que lo identifica. Para eliminar todos usamos
Clear.

Para eliminar a Carlos: chklPromovidos.Items.Remove("Carlos")

Para eliminar al
selecccionado: chklPromovidos.Items.Remove(chklPromovidos.SelectedItem)

Para eliminar al tercero: chklPromovidos.Items.RemoveAt(2)


Para eliminar a todos: chklPromovidos.Clear()

Algunas propiedades

CheckedListBox y ListBox

Propiedad Descripción
Indica si la casilla
cambia de estado con
un solo clic.
CheckOnClick Aconsejo establecerla
a True. Solo la tiene
el control
CheckedListBox
Indica el Origen de
DataSource
Datos
Indica la columna del
DisplayMember origen de datos que
se mostrará
Indica el valor que se
utilizará en caso la
ValueMember propiedad
DislpayMember no
sea el dato a utilizar.
Colección de valores
Items incluidos en el
control

El Control TabControl

Este control TabControl muestra una colección de fichas similares a las etiquetas de
una ventana de opciones (Herramientas, Opciones ... aunque sea de Internet Explorer),
cada ficha o Página puede contener otros controles y también imágenes.

Este control es similar al control SStab y el control TabStrip de Visual Basic 6.0, actúa
como un contenedor.

Algunas propiedades

TabControl

Propiedad Descripción
Contiene las fichas a
TabPages
mostrar en el control.
Las fichas cambian
HotTrack de apariencia cuando
el cursor para sobre
ellas
Relaciona el control
con un control
ImagesList ImageList para
mostrar el cada ficha
una imagen
Muestra las fichas en
Multiline varias líneas cuando
esta en True.
Especifica el menú
ContextMenu
contextual del control

Para mas información vease: Colección combinada de Visual Studio .Net

Ahora mis ejercicios

El Primero: PracOtros

El Primer Proyecto llamado PracOtros (ver empaquetado con el código) supone la


creación de una Proforma, donde seleccionaremos primero una línea de Productos y se
mostrarán sublíneas cada una definida en una array, después de seleccionar la sublínea
se mostrarán los productos en un CheckedListBox, seleccionado el producto se lo puede
incluir en la Proforma que se incluirá en una ListBox. Cada opción es utilizada en un
Page de un control Tabcontrol.

Aquí parte del código:

'PROCEDIMIENTO PARA LLENAR LAS SUBLINEAS

Private Sub LlenarSublineas(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cbolinea.SelectedIndexChanged

lstSublineas.Items.Clear()

Select Case cbolinea.SelectedItem

Case "Lacteos" 'SUBLINEAS DE Lacteos

Dim SubLacteos() As String = _

{"Enlatados", "Instantáneos", "Derivados"}

Sublineas = SubLacteos.Clone

Case "Ferreteria" 'SUBLINEAS DE Ferreteria


Dim SubFerreteria() As String = _

{"Herramientas", "Agregados", "Pegamentos"}

Sublineas = SubFerreteria.Clone

Case "Perfumería" 'SUBLINEAS DE Perfumería

Dim SubPerfumes() As String = _

{"Nacionales", "Importados", "Alternativos"}

Sublineas = SubPerfumes.Clone

Case "Hogar" 'SUBLINEAS DE Hogar

Dim Subhogar() As String = _

{"Decoración", "Sanitarios", "Cerámicas"}

Sublineas = Subhogar.Clone

End Select

lstSublineas.Items.AddRange(Sublineas)

End Sub

El segundo: PracListas

Este ejercicio complementa el uso del control ListBox, supone que debe escribir un
nombre, luego seleccionar un programa donde matricular al alumno, de acuerdo al
programa seleccionado que son: Computación e Informática, Secretariado o
Contabilidad se generan cursos que se insertan en una lista, estos cursos deben
seleccionarse, activar el CheckBox para matricularlo y luego calcular el costo de la
matrícula.

Aquí parte del código:

'PROCEDIMIENTO PARA LA SELECCION DE LOS CURSOS

Private Sub Seleccion(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdUnoSel.Click

If sender Is cmdUnoSel Then 'Seleccion de un Curso


If lstDispo.SelectedIndex = -1 Then

MessageBox.Show("No hay curso seleccionado...", "Error...")

Else

lstSelec.Items.Add(lstDispo.SelectedItem)

lstDispo.Items.Remove(lstDispo.SelectedItem)

End If

ElseIf sender Is cmdTodosSel Then 'Seleccion de todos los cursos

Dim x As Integer

For x = 0 To lstDispo.Items.Count - 1

lstSelec.Items.Add(lstDispo.Items.Item(x))

Next

lstDispo.Items.Clear()

ElseIf sender Is cmdUnoNoSel Then 'Eliminacion de un curso

If lstSelec.SelectedIndex = -1 Then

MessageBox.Show("Seleccione el curso a eliminar...", "Error...")

Else

lstDispo.Items.Add(lstSelec.SelectedItem)

lstSelec.Items.Remove(lstSelec.SelectedItem)

End If

ElseIf sender Is cmdTodosNoSel Then 'Eliminación de todos

Dim x As Integer

For x = 0 To lstSelec.Items.Count - 1

lstDispo.Items.Add(lstSelec.Items.Item(x))

Next

lstSelec.Items.Clear()
End If

End Sub

El Tercero: Practica02

Este ejercicio permite complementar el uso de los controles básicos de Windows Forms,
asi como el uso del control PictureBox para agregar una imagen o una foto dentro del
formulario.

Aquí parte del código:

Private Sub Procesar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdAgregar.Click

'PROCEDIMIENTO PARA LOS BOTONES DE COMANDO

' LOS DELEGADOS SE HAN INSERTADO EN EL CONSTRUCTOR

'con las siguientes dos lineas

'AddHandler cmdNuevo.Click, AddressOf Procesar

'AddHandler cmdSalir.Click, AddressOf Procesar

Dim TEXTOMENSAJE As String

If sender Is cmdSalir Then

End

ElseIf sender Is cmdNuevo Then

txtnombre.Clear()

txtdire.Clear()

optsoltero.Checked = True

optcasado.Checked = False

optestable.Checked = False

optcontrato.Checked = True

optotro.Checked = False

dtpFechaReg.Value = Now
Dim x As Integer

For x = 0 To chklAficiones.Items.Count - 1

'COMPROBAR SI ESTA SELECCIONADO

If chklAficiones.GetItemCheckState(x) = CheckState.Checked Then

'QUITAR LA SELECCION

chklAficiones.SetItemChecked(x, False)

End If

Next

Me.chklAficiones.ClearSelected()

Me.PictureBox1.Image = Nothing

txtnombre.Focus()

ElseIf sender Is cmdAgregar Then

MessageBox.Show("Agregar el registro...", _

"Registro Nuevo...", MessageBoxButtons.OK)

'MOSTRAR EL MENSAJE UNICAMENTE...

TEXTOMENSAJE = "Nombre: " & txtnombre.Text & ControlChars.CrLf &


_

"Dirección: " & txtdire.Text & ControlChars.CrLf & _

"Estado Civil: " & IIf(optsoltero.Checked, "Soltero", "Casado") & _

ControlChars.CrLf & _

"Condición: " & IIf(optestable.Checked, "Estable", _

IIf(optcontrato.Checked, "Contratado", "Otra")) & _

ControlChars.CrLf & _

"Fecha de Registro: " & Me.dtpFechaReg.Value & _

ControlChars.CrLf & ControlChars.CrLf & _

ControlChars.CrLf & _
"Aficiones : " & ControlChars.CrLf

Dim x As Integer 'Para explorar las opciones del CheckedListBox

For x = 0 To chklAficiones.Items.Count - 1

'COMPROBAR SI ESTA SELECCIONADO

If chklAficiones.GetItemCheckState(x) = CheckState.Checked Then

'Agregar la Afición al TextoMensaje

TEXTOMENSAJE = TEXTOMENSAJE & ControlChars.CrLf _

& chklAficiones.Items(x)

End If

Next

MessageBox.Show(TEXTOMENSAJE, "Datos del registro insertado", _

MessageBoxButtons.OK)

End If

End Sub

El Cuarto: PracVariosForms01

Este ejercicio es mas completo, incluye cajas de texto, CheckedListBox, ListBox y el


uso de mas de un formulario, insertando también un módulo haciendo uso de variables
publicas que se usarán en mas de un formulario.

Supone un sistema de Evaluacion de Personal, donde al seleccionar un departamento


aparece el personal de este, deberán seleccionarse un mínimo de 6 personas para los
exámenes, los cuales deben ser como mínimo 02 y como máximo 04. En el control
DateTimePicker utilizado se especifica como fechas límites los días del mes en curso.

Aquí parte del código:

'PROCEDIMIENTO PARA LA SELECCION DEL PERSONAL

Private Sub Seleccion(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdUnoSel.Click

cmdMostrar.Enabled = False

If sender Is cmdUnoSel Then 'Seleccion de un empleado


If lstDispo.SelectedIndex <> -1 Then

lstSelec.Items.Add(lstDispo.SelectedItem)

lstDispo.Items.Remove(lstDispo.SelectedItem)

End If

ElseIf sender Is cmdTodosSel Then 'Seleccion de todos los empleados

Dim x As Integer

For x = 0 To lstDispo.Items.Count - 1

lstSelec.Items.Add(lstDispo.Items.Item(x))

Next

lstDispo.Items.Clear()

ElseIf sender Is cmdUnoNoSel Then 'Eliminacion de un empleado

If lstSelec.SelectedIndex <> -1 Then

lstDispo.Items.Add(lstSelec.SelectedItem)

lstSelec.Items.Remove(lstSelec.SelectedItem)

End If

ElseIf sender Is cmdTodosNoSel Then 'Eliminación de todos

Dim x As Integer

For x = 0 To lstSelec.Items.Count - 1

lstDispo.Items.Add(lstSelec.Items.Item(x))

Next

lstSelec.Items.Clear()

End If

End Sub

XML Web Services


Autenticación mediante Fomularios en ASP
Uso de Controles de Usuario
Navegar entre Registros en un WebForm
Sres. Desarrolladores, siempre con mi estilo de ejemplos pequeños pero útiles les envio
una práctica que desarrollé con un grupo de alumnos. En la práctica se pueden entender
lo siguiente:

1. La autenticación mediante formularios (Forms), haciendo uso de usuarios


registrados en una base de datos y usando un Store Procedure para buscar al
usuario con el que se loguea. Este se encuentra en una base de datos llamada
EXAMEN (Campos: Usuario y Clave), el Store Procedure se encuentra en una
archivo adjunto al código en formato doc.
2. Las teclas de Navegación en ASP, en las cuales tenemos que hacer uso de los
estados del Web Form y de la propiedad ViewState.
3. El consumo de XML Web Services incluidos en el mismo Proyecto y en otro
Proyecto, para realizar cálculos sencillos, lo importante es reconocer como crear
el Proxy para el consumo del servicio.
4. El uso de Controles de Usuario .ascx, para el menú principal una vez
logueados.

Notas importantes:

 El Web Form de Calculos no tiene implementados los controles de Validación,


se asume que el usuario debe conocerlo para darle consistencia, el objetivo de
este aporte no es ese.
 Cree su Base de datos Examen, la tabla usuarios y el SP login, existe un
documento adjunto en formato Word llamado Base.doc que tiene las
indicaciones adecuadas.
 Al bajar el código fuente, actualicen sus cadenas de conexión.

Aqui parte del Código:

'Importar los NameSpace Necesarios

Imports System.Web.Security
Imports System.Data.SqlClient
Imports System.Data

Public Class login


Inherits System.Web.UI.Page

Dim cmd As SqlCommand

Dim con As New SqlConnection("workstation id=HOME;packet


size=4096;integrated security=SSPI;data source=.;persist security info=False;initial
catalog=Examen")

#Region " Código generado por el Diseñador de Web Forms "

''' el código de esta parte ha sido eliminada


#End Region

'Procedimiento para loguearse

Private Sub cmdAceptar_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles cmdAceptar.Click

'Crear el comando

cmd = New SqlCommand("Login", con)

cmd.CommandType = CommandType.StoredProcedure

'Crear el parametro del procedimiento almacenado - retorno

Dim prmDato As SqlParameter

Dim Resultado As Integer

prmDato = cmd.Parameters.Add("RETURN_VALUE", SqlDbType.Bit)

prmDato.Direction = ParameterDirection.ReturnValue

'asignar los valores a los parametros

cmd.Parameters.Add("@user", TextBox1.Text)

cmd.Parameters.Add("@clave", TextBox2.Text)

'Abrir la conexion

con.Open()

'Ejecutar el comando

cmd.ExecuteNonQuery()

'Recoger el resultado

Resultado = cmd.Parameters("RETURN_VALUE").Value

'Cerrar la conexion
con.Close()

If Resultado = 1 Then

FormsAuthentication.RedirectFromLoginPage(TextBox1.Text, False)

'Response.Redirect("defoult.aspx")

Else

lblm.Text = "Usuario no Existe o la Clave es Incorrecta"

End If

End Sub

End Class

El código completo está en el archivo adjunto, cree los directorios virtuales después de
desempaquetar los archivos fuente.

Suerte a todos, espero les sirva de ayuda, no olviden dar su opinión en mi Panoramabox,
gracias.

Controlando Eventos y Arrays


Uso de Controladores de Eventos en una Aplicación .Net
Arrays de dos dimensiones
Creación de DataSet por Código

Sres. Desarrolladores, en esta ocasión les envío un aporte interesante para comprender
el uso de Delegados en aplicaciones de Visual Studio .Net

Un poco de Teoría

Al desarrollar aplicaciones en Visual Studio 6.0, muchos de nosotros implementábamos


los arrays de controles para agrupar varios controles en procedimientos donde después
evaluábamos el índice para decidir o saber que botón fue pulsado. Al desarrollar
aplicaciones en Visual Studio .Net cambiamos esa forma de trabajo con el uso de
Controladores de Eventos (Handles).

Cuando nosotros usamos una aplicación al pulsar click en un botón de comando se


produce el evento click del control respectivo, suponiendo que el nombre de ese botón
es cmdGuardar y el evento es Click al escribir el código para esto, Visual Basic le
asigna una nomenclatura estándar y le asigna automáticamente el nombre
cmdGuardar_Click. y aparece como sigue:

Private Sub cmdGuardar_Click(Byval..... ) Handles cmdGuardar.Click


End Sub

Nos podemos dar cuenta de lo siguiente, Visual Studio le asigna al procedimiento Sub
el nombre cmdGuardar_Click, este nombre en aplicaciones de escritorio lo podemos
cambiar sin ningún problema, en aplicaciones ASP debemos cambiar el valor de la
Propiedad AutoEventWireUp a False para poder hacerlo. Lo mas importante de los
controladores se define después de la palabra Handles. Después de esto podemos
definir los controles y eventos que han sido asignados al evento.

ASIGNAR LOS CONTROLADORES

La asignación de los controladores se puede realizar de dos formas:

1. Asignando el controlador en la definición del Procedimiento, separados por


comas después de la palabra Handles, como sigue:

Private Sub Procesar(Byval..... ) Handles cmdGuardar.Click,


cmdCambiar.Click,cmdEliminar.Click

End Sub

Lo que significa que el peocedimiento Procesar se ejecuta cuando se pulsa click en los
controles cmdGuardar, cmdCambiar y cmdEliminar.

Para controlar que control fue pulsado utilizamos la variable sender de la siguiente
manera:

Private Sub Procesar(Byval..... ) Handles cmdGuardar.Click,


cmdCambiar.Click,cmdEliminar.Click

If sender Is cmdGuardar Then

'Líneas de código para guardar

ElseIf sender Is cmdCambiar Then

'Ejecuta el Procedimiento Cambiar

ElseIf sender Is cmdEliminar Then

'Ejecuta el Procedimiento para eliminar

End If

End Sub
2. Asignar el controlador utilizando la instrucción AddHandler, cuya sintaxis es como
sigue:

AddHandler <Control.Evento>, AddressOf <Nombre Procedimiento>

La asignación de estos controladores puede ser en el evento Load del Formulario o en


el contructor (evento New). Para el ejemplo que estamos siguiendo los controladores
se asignan con las siguiente líneas:

AddHandler cmdGuardar.Click, AddressOf Procesar

AddHandler cmdCambiar.Click, AddressOf Procesar

AddHandler cmdEliminar.Click, AddressOf Procesar

Personalmente recomiendo crearlos en el constructor. Tenga en cuenta que asignarlo en


los dos Procedimientos no reporta errores al ejecutar, pero si en el proceso.

Notas importantes:

 Si se ha asignado en ambas partes, en la definición del Procedimiento y en el


Constructor, al ejecutar la aplicación no reporta ningún error, pero el
procedimiento se ejecuta dos veces.
 Por orden personalmente recomiendo incluir los controladores en el constructor.

ELIMINAR LOS CONTROLADORES

Para eliminar la asignación de un controlador de evento se utiliza RemoveHandler


que tiene la siguiente sintaxis:

RemoveHandler <Control.Evento>, AddressOf <Nombre Procedimiento>

Si se quisiera eliminar el controlador para los controles anteriores las ordenes serían:

RemoveHandler cmdGuardar.Click, AddressOf Procesar

RemoveHandler cmdCambiar.Click, AddressOf Procesar

RemoveHandler cmdEliminar.Click, AddressOf Procesar

VAMOS CON NUESTRO EJEMPLO

En nuestro ejemplo se pide cinco datos y luego se almacenan estos en un arrays de dos
dimensiones, luego esos datos del array se guardan en un DataTable de un DataSet
creado por código. Espero les sirva.

Aqui parte del Código:

'Procedimiento que procesa los 4 botones de comando del formulario


'El delegado se ha especificado en el constructor

'NOTE QUE EXISTE ASINGADO DOS VECES EL CONTROLADOR AL


BOTON CERRAR
'Y NO REPORTA NINGUN ERROR...TENGA MUCHO CUIDADO CON
ESTO

Private Sub Procesar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdGuardar.Click, cmdCerrar.Click

'NOTA IMPORTANTE:
' Se utiliza la variable sender para saber que control
' se ha utilizado.

If sender Is cmdGuardar Then


'Permite guardar el elemento actual en el Array
GuardarElemento()

ElseIf sender Is cmdBorrar Then


'Ejecuta el Procedimiento BorrarTodo
BorrarTodo()

ElseIf sender Is cmdMostrar Then


MostrarTodos()

ElseIf sender Is cmdCerrar Then


End
End If

End Sub

Private Sub GuardarElemento()


'Comprobar el ingreso de datos
If Len(Trim(txtNombre.Text)) = 0 Or Len(Trim(txtDire.Text)) = 0 Then
MessageBox.Show("Datos imcompletos...", "Error")
Exit Sub

End If

If cboGrado.SelectedIndex = -1 Then

MessageBox.Show("Seleccione en grado de instrucción...", "Error")

Exit Sub

End If

'Hacer crecer el array y Guardar los datos actuales.

ReDim Preserve aRegistros(4, cRegistros)


aRegistros(0, cRegistros) = Trim(txtNombre.Text)

aRegistros(1, cRegistros) = Trim(txtDire.Text)

aRegistros(2, cRegistros) = IIf(optEstable.Checked, "Estable",


IIf(optContrato.Checked, "Contratado", "Service"))

aRegistros(3, cRegistros) = IIf(optEstable.Checked, "Soltero", "Casado")

aRegistros(4, cRegistros) = Trim(cboGrado.SelectedItem)

cRegistros += 1

End Sub

Private Sub BorrarTodo()

ReDim aRegistros(4, 0)

cRegistros = 0

dgRegistrados.DataSource = Nothing

'Borrar los datos actuales

txtNombre.Clear()

txtDire.Clear()

optEstable.Checked = True

optSoltero.Checked = True

cboGrado.SelectedItem = -1

cboGrado.Text = "Seleccionar"

txtNombre.Focus()

End Sub

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias.

El control ComboBox
Opciones principales

Sres Desarrolladores, les envio este aporte que permitirá conocer las opciones
principales del control ComboBox, en este articulo no utilizo el enlace del control a
base de datos, pero les prometo que dentro de poco preparo otro con enlaces a Base de
Datos. Suerte a todos

UN POCO DE TEORIA

Los controles de lista como ListBox, ComboBox y CheckedListBox (pueden visitar el


artículo en http://www.elguille.info/colabora/puntoNET/FernandoLuque_Controles.ht
m) permiten el manejo de varias opciones, en este artículo trato de explicar el uso del
control ComboBox.

El ComboBox es uno de los controles de lista mas utilizados en las aplicaciones tanto de
escritorio como ASP .Net, este es sumamente versastil, su propiedad DropDownStyle
nos brinda presentarlo de forma variada. en el ejemplo he tratado de mostrar estas
opciones.

El ejemplo también muestra como ingresar una fecha considerando edades entre 17 y 90
años. El botón Comprobar permite mostrar un mensaje si la fecha seleccionada es
Correcta o Incorrecta.

A continuación sigue código en Visual Basic

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


Handles MyBase.Load
'Llenar el Día
Dim i As Integer
For i = 1 To 31
cboDia.Items.Add(i)
Next

'Llenar los Nombres de los Meses

For i = 1 To 12
cboMes.Items.Add(MonthName(i, False))
Next

'Al ingresar el rango para los años existen


'diferentes posibilidades...consideremos mayores de 18 años
'hasta las 90 años

For i = Year(Now) - 90 To Year(Now) - 17


cboAnio.Items.Add(i)
Next

End Sub
Private Sub CompruebaFecha(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles cmdComprobar.Click

If cboDia.SelectedIndex = -1 Or cboMes.SelectedIndex = -1 Or
cboAnio.SelectedIndex = -1 Then
MessageBox.Show("Faltan datos...", "Fecha incompleta",
MessageBoxButtons.OK)
Exit Sub
End If

Dim vfecha As String

vfecha = Trim(cboDia.SelectedItem) & "/" & Trim(Str(cboMes.SelectedIndex +


1)) & "/" & Trim(cboAnio.SelectedItem)

If Microsoft.VisualBasic.IsDate(vfecha) = False Then


MessageBox.Show("Fecha no valida...", "Error de ingreso",
MessageBoxButtons.OK)
Else
MessageBox.Show("Fecha CORRECTA...", "Dato Válido",
MessageBoxButtons.OK)
End If

End Sub

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias.

El control ListBox

Sres Desarrolladores, les envío este aporte que permitirá conocer las opciones
principales del control ListBox, en este articulo no utilizo el enlace del control a base de
datos, pero de todas maneras espero que les sea útil. Suerte a todos.

UN POCO DE TEORÍA

Los controles de lista como ListBox, ComboBox y CheckedListBox (pueden visitar el


artículo que publiqué hace algún tiempo
en http://www.elguille.info/colabora/puntoNET/FernandoLuque_Controles.htm)
permiten el manejo de varias opciones, en este artículo trato de explicar el uso del
control ListBox.

La diferencia básica del control ListBox con respecto al ComboBox es que el control
ListBox permite la selección de múltiples opciones además lógicamente de poder
mostrarlas.

A continuación sigue código en Visual Basic


Private Sub CargaFormulario(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'Llenar los elementos del ListBox lstDisponibles

Dim aOpciones() As String = {"Net Desarrollo", "Visual Basic .Net", "ASP .Net",
_

"XML Web Service", "Application Blocks", "Ing. Fernando Luque", "COM+


Components"}

lstDisponibles.Items.AddRange(aOpciones)

'Llenar los elementos del ListBox lstMulti para

'probar el comportamiento de la Propiedad SelectionMode

'NOTE QUE EN EL ARRAY ANTERIOR SE USO AddRange

'Cuando se utiliza DataSource no se pueden eliminar

'los elementos de la lista

Dim aMultiple() As String = {"Carolina", "Maria Fernanda", "Fernando", _

"Carla", "Ingrid", "Esmeralda", "Víctor"}

lstMulti.DataSource = aMultiple

lstMulti.ClearSelected()

End Sub

Private Sub AgregarNombre(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdAgregar.Click

'Comprobar el ingreso de un dato en la caja de texto

If Len(Trim(txtnombre.Text)) = 0 Then

MessageBox.Show("No hay dato para agregar...", "Error",


MessageBoxButtons.OK)

txtnombre.Focus()

Exit Sub
End If

'Comprobar si está en la lista

Dim i As Integer, vPresente As Boolean

For i = 0 To lstNombres.Items.Count - 1

If lstNombres.Items.Item(i) = txtnombre.Text Then

vPresente = True

Exit For

End If

Next

If vPresente = False Then

lstNombres.Items.Add(txtnombre.Text)

lstNombres.Focus()

End If

End Sub

Private Sub Eliminar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdEliminar.Click

If lstNombres.SelectedIndex <> -1 Then

lstNombres.Items.Remove(lstNombres.SelectedItem)

End If

End Sub

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias.

Maestro - Detalle
Clientes - Órdenes usando Northwind

Sres. Desarrolladores, en esta oportunidad les envío un pequeño pero útil ejemplo de
como utilizar un DataView en una consulta Maestro (la tabla Customers) y obtener las
órdenes del Cliente seleccionado (de la tabla Orders), los clientes son cargados en un
ComboBox y luego de seleccionar uno de ellos se pueden visualizar sus órdenes.

A continuación sigue código en Visual Basic, nótese que la Region generada por
Windows Forms ha sido eliminada para mostrar únicamente lo que se desea:

Se ha insertado desde el IDE los objetos SQLConnection, SQLDataAdapter y se ha


generado el DataSet.

'Maestro - Detalle sencillo


'Ing. Fernando Luque Sánchez
'Trujillo - Perú

Imports System.Data
Imports System.Data.SqlClient

Public Class frmPrincipal


Inherits System.Windows.Forms.Form

'Vista para el filtrado de Datos


Dim dvOrdenes As DataView

Private Sub CargarForm(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

'Llenar los DataTables con los datos


daClientes.Fill(dsDatos, "Clientes")

daOrdenes.Fill(dsDatos, "Ordenes")

'Origen del ComboBox

cboClientes.DataSource = dsDatos.Tables("Clientes")

cboClientes.DisplayMember = dsDatos.Tables("Clientes").Columns(1).ToString

cboClientes.ValueMember = dsDatos.Tables("clientes").Columns(0).ToString

'Definir el DataView

dvOrdenes = dsDatos.Tables("Ordenes").DefaultView

End Sub

Private Sub BuscaOrdenes(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdBuscar.Click


Dim vdato As String = cboClientes.SelectedValue

dvOrdenes.RowFilter = "CustomerId = '" & vdato & "'"

With dgOrdenes

.CaptionText = "Órdenes Registradas"

.DataSource = dvOrdenes

End With

End Sub

Private Sub cboClientes_SelectedIndexChanged(ByVal sender As System.Object,


ByVal e As System.EventArgs) Handles cboClientes.SelectedIndexChanged

dgOrdenes.DataSource = Nothing

End Sub

End Class

Como se pueden dar cuenta, es una de las formas mas sencillas de obtener un Maestro -
Detalle, también es posible agregar una relación (Relation) entre las dos tablas
(DataTables) y utilizar el método GetChildRows del objeto DataRow para obtener el
detalle.

Suerte a todos, espero les sirva de ayuda.

Mantenimiento de Categorías
Usando la Base de datos Northwind

Sres. Desarrolladores, les envío en esta oportunidad el clásico mantenimiento de una


tabla de una base de datos, es algo sencillo pero a la vez sumamente importante.

El ejemplo tiene incluido desde el IDE los objetos SQLConnection, un


SQLDataAdapter y se ha generado un DataSet tipificado. Se asume que el lector conoce
todos estos términos.

También se muestra como se utiliza el control ToolTip, recuerden que en los exámenes
del Desarrollador Cinco Estrellas asi como en la Certificación MCSD .Net viene
preguntas acerca del Control ToolTip. Basta con uno solo para todos los controles que
se les pueda especificar un mensaje.

Notas importantes:
 El ejemplo incluye dos formas de manipular los registros de Categorías, la
primera es únicamente con el uso de un grid y un botón que actualice la tabla de
la base de datos con el uso del SQLDataAdapter respectivo.
 La segunda forma es incluyendo los clásicos botones de navegación entre
registros y los botones Insertar, Modificar, Actualizar y Eliminar.
 El ejemplo muestra en el mismo Form las dos opciones.
 Les envío además un archivo de Word en Versión Imprimible.

A continuación sigue código en Visual Basic:

'Importar el NameSapce para los datos con SQL Server 2000


Imports System.Data.SqlClient

Public Class Categorias


Inherits System.Windows.Forms.Form

'CREAR EL Adaptador, el DataSet y el Entero para la Posición

Private daCat As SqlDataAdapter


Private dsCatCod As DataSet
Private iPosicion As Integer

'Este DataTable es para el Mantenumiento con todos los botones.

Private CategoriasCod As DataTable

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


*** CODIGO ELIMINADO
#End Region

'CUANDO CARGA EL FORMULARIO --- LOAD

Private Sub CargarForm(ByVal sender As Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

'LLENAR EL DATATABLE CON LOS DATOS DEL DATASET

daCategorias.Fill(dsCat, "Categorias") 'ENLAZAR EL GRID CON EL


DATATABLE CREADO

grdCategorias.DataSource = dsCat.Tables("Categorias")

grdCategorias.CaptionText = "Categorias Registradas"

' **********************************************************'

'Esta seccion el para el Mantenimiento por código


'CREAR LA CONEXION
Dim cn1 As New SqlConnection()

'ESTABLECER LA CADENA DE CONEXION


cn1.ConnectionString = "data source=HOME;" & _
"initial catalog=Northwind;" & _
"integrated security=SSPI;" & _
"persist security info=False;" & _
"user id=sa;workstation id=HOME;packet size=4096"

'CREAR EL ADAPTADOR
daCat = New SqlDataAdapter("Select CategoryId,CategoryName,Description from
Categories", cn1)

'CREAR EL COMMANDBUILDER
'ESTE OBJETO PERMITE CREAR LOS COMANDOS DEL ADAPTADOR
Dim cbCat As New SqlCommandBuilder(daCat)

'Crear una nueva instancia del DataSet


Me.dsCatCod = New DataSet()

'Abrir la Conexion
cn1.Open()

'Llenar el DataSet
Me.daCat.Fill(dsCatCod, "CategoriasCod")

'Cerrar la conexion
cn1.Close()

'Indicador de registros a 0
Me.iPosicion = 0

'Cargar los datos del registro a las cajas de texto


Me.CargarDatos()

'DataSource del Grid por Código


grdCatCod.DataSource = Me.dsCatCod.Tables("CategoriasCod")

grdCatCod.CaptionText = "Categorias - Código"


grdCatCod.ReadOnly = True

End Sub

'MUESTRA LOS DATOS DEL REGISTRO ACTIVO EN LAS CAJAS DE TEXTO


Private Sub CargarDatos()

'DEFINIR UN DATAROW
Dim drFila As DataRow
'ASIGNAR LOS DATOS DEL PRIMER REGISTRO AL DATAROW
drFila = dsCatCod.Tables("CategoriasCod").Rows(Me.iPosicion)

'LLENAR LAS CAJAS DE TEXTO CON LOS DATOS DEL DATAROW

Me.txtIdCat.Text = drFila("CategoryID")

Me.txtNombreCat.Text = drFila("CategoryName")

Me.txtDescCat.Text = drFila("Description")

'ACTUALIZAR LA ETIQUETA "Registro..... de ......"

Me.lblPosicion.Text = "Registro " & CType(Me.iPosicion + 1, String) & _

" de " & Me.dsCatCod.Tables("categoriasCod").Rows.Count

End Sub

'ACTUALIZACION DESDE EL IDE

Private Sub ActualizaGrid(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles cmdActualizar.Click
daCategorias.Update(dsCat, "Categorias")
End Sub

Private Sub cmdPrimero_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles cmdPrimero.Click
'PRIMER REGISTRO DE LA TABLA
Me.iPosicion = 0
CargarDatos()
End Sub

Private Sub cmdUltimo_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles cmdUltimo.Click

'ULTIMO REGISTRO DE LA TABLA


Me.iPosicion = Me.dsCatCod.Tables("CategoriasCod").Rows.Count - 1
CargarDatos()

End Sub

Private Sub cmdAnterior_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdAnterior.Click

'REGISTRO ANTERIOR
If Me.iPosicion = 0 Then

MessageBox.Show("Primer registro...", "Atención")

Else

Me.iPosicion -= 1

CargarDatos()

End If

End Sub

Private Sub cmdSiguiente_Click(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdSiguiente.Click

'SIGUIENTE REGISTRO

If Me.iPosicion = Me.dsCatCod.Tables("CategoriasCod").Rows.Count - 1 Then

MessageBox.Show("Último registro...", "Atención")

Else

Me.iPosicion += 1

CargarDatos()

End If

End Sub

Private Sub Insertar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdInsertar.Click

'INSERTAR REGISTROS AL DATATABLE

'DEFINIR EL DATAROW

Dim FilaNueva As DataRow

FilaNueva = Me.dsCatCod.Tables("CategoriasCod").NewRow()
'ASIGNAR LOS VALORES CON LOS DE LAS CAJAS DE TEXTO

FilaNueva("CategoryID") = CType(Me.txtIdCat.Text, Integer)

FilaNueva("CategoryName") = Me.txtNombreCat.Text

FilaNueva("Description") = Me.txtDescCat.Text

'Agregar el Row

Me.dsCatCod.Tables("CategoriasCod").Rows.Add(FilaNueva)

'Deshabilitar Botones

Me.cmdInsertar.Enabled = False

Me.cmdActualCod.Enabled = True

Me.cmdModificar.Enabled = True

Me.cmdEliminar.Enabled = True

Me.PanelMover.Enabled = True 'Activar Panel

Me.cmdLimpiar.Enabled = True

DesactivarCajas()

Me.cmdActualCod.Text = "Actualizar"

Me.iPosicion = Me.dsCatCod.Tables("CategoriasCod").Rows.Count - 1

Me.lblPosicion.Text = "Registro " & CType(Me.iPosicion + 1, String) & _

" de " & Me.dsCatCod.Tables("categoriasCod").Rows.Count

End Sub

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias.

Usando SQLDataReader

Entornos Conectados

Sres Desarrolladores, en esta ocasión va mi aporte para entender un poco el uso del
objeto SQLDataReader usado en Entornos conectados usando Base de Datos.

UN POCO DE TEORIA
SQLDataReader es una clase que permite leer un conjunto de registros avanzando
unicamente hacia adelante, es una clase que no se puede heredar.

Para crear un SQLDataReader se utiliza el método ExecuteReader del


SQLCommand, lo mas importante de anotar es que este objeto mantienen la conexión
SQLConnection ocupada y abierta mientras realiza la lectura.

Algunos métodos públicos podemos encontrarlos en la siguiente tabla:

Método Público Descripción


Close Cierra el objeto SQLDataReader
Desplaza en SQLDataReader al
Read
siguiente registro
Desplaza el lector de datos al siguiente
resultado, esto es cuando en el
NextResult Procedimiento almacenado utilizado se
incluye mas de una instrucción Transact-
SQL
GetBoolean
Obtiene el valor de la columna teniendo
en cuenta el tipo de dato.
GetByte
La Lista completa de métodos la puede
GetChar
visualizar en la ayuda interactiva de
Visual Studio .Net
GetDouble

El ejemplo que comparto con todos utiliza el sigueinte Procedimiento Almacenado


(Store Procedure - SP) en la base de datos Northwind:

Create PROCEDURE dbo.GetAllProductsList

AS

SELECT * FROM PRODUCTS WHERE DISCONTINUED<>0


SELECT * FROM PRODUCTS WHERE CATEGORYID IN (1,3,5)
SELECT * FROM PRODUCTS WHERE UNITPRICE > 20

RETURN

Note que el Procedimiento Almacenadoes simple y tiene TRES instrucciones Transac-


SQL.

A continuación sigue código en Visual Basic

Private Sub ObtenerDatos(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles Button1.Click

'Crear el Comando SQL


Dim cmd As New SqlCommand("getAllProductsList", cn)
'Especificar el tipo de comando
cmd.CommandType = CommandType.StoredProcedure

'Crear el DataReader
Dim drConsulta As SqlDataReader

'Abrir la conexión
cn.Open()

'Ejecutar el DataReader
drConsulta = cmd.ExecuteReader()

'LLENAR LAS LISTAS CON LOS RESULTADOS - Borrarlas primero


ListBox1.Items.Clear()
ListBox2.Items.Clear()
ListBox3.Items.Clear()

'ARTICULOS NO DESCONTINUADOS
While drConsulta.Read
ListBox1.Items.Add(drConsulta(1))
'el número 1 indica la segunda
'columna de la consulta
End While

'SIGUIENTE RESULTADO
'PRODUCTOS DE CATEGORIAS 1, 3 Y 5
drConsulta.NextResult()

While drConsulta.Read
ListBox2.Items.Add(drConsulta(1))
End While

'SIGUIENTE RESULTADO
'PRODUCTOS CON PRECIO UNITARIO > 20

drConsulta.NextResult()
While drConsulta.Read
ListBox3.Items.Add(drConsulta(1))
End While

'Cerrar el DataReader

drConsulta.Close()
'Cerrar la conexión
cn.Close()
End Sub

El código completo está en el archivo adjunto. Suerte a todos, espero les sirva de ayuda,
no olviden dar su opinión en mi Panoramabox, gracias.
El Control ListView

Uso de Estructuras

Sres. Desarrolladores, en esta oportunidad les envie un aporte para poder comprender la
parte básica de uno de los controles mas utilizados en aplicaciones de Escritorio, el
control ListView.

UN POCO DE TEORIA

El control ListView es un control de lista que tiene mucha versatilidad, se puede utilizar
hasta en 4 vistas diferentes: LargeIcon, Details, SmallIcon y List (Iconos grandes,
Detalle, Iconos pequeños y Lista). Las mismas opciones están incluidas en el botón
Vistas del Explorador de Windows.

El control ListView se usa generalmente ligado a una o dos Listas de Imagenes


incluídas en controles ImageList, estos permiten mostrar los íconos de cada elemento
cuando se selecciona las opciones de LargeIcon y SmallIcon.

El control ListView presenta una lista de elementos que son heredados de la clase
ListViewItem, cada uno de estos elementos a su vez tiene Subelementos (SubItems),
que van relacionados con el ListViewItem respectivo.En la vista Detalle (propiedad
View en la opción Details) permite mostrar el control con los ListViewItem y los
SubItems respectivos en una cuadricula similar a un control Grid (control DataGrid). En
esta vista se muestran los encabezados de cada columna (colección Columns) donde
podemos asignar nombres a las mismas, un texto que se mostrará en cada una asi como
el ancho.

Como en todo control de Lista los elementos del control ListView se agregan a la
colección Items.

Pueden visitar los enlaces


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ComboBox.ht
m para el control ComboBox

http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ListBox.htm
para el control ListBox -

Algunas de las propiedades ligadas a la vista Details del control ListView son:

Propiedad Descripción

AllowColumnReorder Permite ordenar los Items incluidos

Cuando está en True permite


GridLines
mostrar líneas de división.
Permite seleccionar el Item con
FullRowSelect todos los SubItems que dependen
de este

Permite especificar el estilo de los


HeaderStyle
encabezados de las columnas.

NUESTRO EJEMPLO

El aporte que comparto con ustedes señores desarrolladores muestra como ingresar dos
datos: Nombre y Nota y mostrarlos en un control ListView. Estos dos datos están
incluidos en una Estructura previamente creada, luego se crea un arreglo donde cada
elemento es del tipo de la estructura. ES NECESARIO ANOTAR QUE LA
CONSISTENCIA DE LOS DATOS REPETIDOS O DEL TIPO ADECUADO (String
para el nombre y Numeric para la nota) NO ESTAN COSISTENCIADOS.

A continuación sigue código en Visual Basic

Structure alumno
Public nombre As String
Public nota As Integer
End Structure

Dim aIntegrantes() As alumno


Dim cContador As Integer

Private Sub Agregar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdAgregar.Click

If Len(Trim(txtNombre.Text)) = 0 Or Len(Trim(txtNota.Text)) = 0 Then

MessageBox.Show("Faltan datos...", "Error")

Exit Sub

End If

cmdMostrar.Enabled = True

ReDim Preserve aIntegrantes(cContador)

aIntegrantes(cContador).nombre = txtNombre.Text

aIntegrantes(cContador).nota = txtNota.Text

cContador += 1
txtNombre.Focus()

End Sub

El código completo del artículo se encuentra en el archivo adjunto al final del


artículo, no olviden de calificar en PanoramaBox. Cualquier consulta no duden en
escribir a mi correo, respondo mas rápido con el de Hotmail. Suerte a todos.

Formateando el control DataGrid

Creando y usando estilos

Sres. Desarrolladores, este aporte ayudará a muchos de ustedes a darle ese toque final a
sus proyectos, en esta oportunidad envio un ejemplo donde explico como cambiar la
forma de presentación de un Grid en una aplicción Windows.

UN POCO DE TEORIA

El control DataGrid es un control que muestra un conjunto de datos de manera tabular,


es decir ordenado con filas y columnas donde posiblemente muestre los datos de una
tabla que son el resultado de una instrucción Transact-SQL como Select. Este
contenido lo pasamos a un DataTable dentro de nuestro DataSet y luego desde el IDE o
mediante código especificamos el origen del Grid.

Este Grid o control DataGrid tiene una apariencia que en muchas ocasiones no se
adecua a nuestros requerimientos, para esto debemos cambiarle la forma de como se ve
aplicando un Estilo o lo que se conoce como CAMBIARLE EL FORMATO AL GRID.

La Clase DataGridTableStyle

La clase DataGridTableStyle es una clase que representa al control Grid dibujado,


mediante esta clase se puede controlar la forma de como se visualiza el control
DataGrid. Para cambiar el formato de un control DataGrid debemos crear una nueva
instancia de esta clase y luego cambiar sus propiedades de la forma como se desea ver el
control DataGrid.

Para crear una nueva instancia de la clase DataGridTableStyle se utiliza:

Dim dgEstiloTabla As New DataGridTableStyle

Donde dgEstiloTabla es el nombre asignado a esta instancia. Luego se especifican las


características de este nuevo formato, como por ejemplo:

With dgEstiloTabla
.AlternatingBackColor = Color.GhostWhite
.BackColor = Color.GhostWhite
.ForeColor = Color.MidnightBlue
.GridLineColor = Color.RoyalBlue
.HeaderBackColor = Color.MidnightBlue
.HeaderFont = New Font("Tahoma", 8.0!, FontStyle.Bold)
.HeaderForeColor = Color.Lavender
.SelectionBackColor = Color.Teal
.SelectionForeColor = Color.PaleGreen
' Establecer la propiedad Mapping
'para que tenga efecto el objeto DataGridTableStyle
.MappingName = vNombreTabla
.PreferredColumnWidth = 125
.PreferredRowHeight = 15
End With

Luego para asignar el estilo creado al control DataGrid debemos utilizar la propiedad
Mapping y seleccionar el nombre del DataTable que tomará el formato definido.

Fijese en la fila que contiene la instrucción .MappingName = vNombreTabla, aqui se


asigna el DataTable respectivo, previamente en el ejemplo que comparto con ustedes se
ha declarado una variable vNombreTabla con la siguiente instrucción:

Public vNombreTabla As String = "Clientes"

El estilo definido se agrega a la colección GridTableStylesCollection, en esta colección


se puede agregar todos los estilos que el usuario desee, luego para utilizarlos basta con
utilizar la propiedad Mapping para especificar que DataTable se mostrará en el control
DataGrid.

COMO MUESTRO EL FORMATO

Una vez definido el formato, especificada la propiedad Mapping debe agregarse este a
la colección TableStyles del control DataGrid, la instrucción para nuestro ejemplo es:

dgClientes.TableStyles.Add(dgEstiloTabla)

La Clase DataGridColumnStyle

Esta clase determina la apariencia, el formato del texto y la forma de comportamiento


de cada columna del control DataGrid. Las siguientes instrucciones muestran la
definición del formato de una de las columnas, note que el estilo es definido usando la
clase DataGridTextBoxColumn que es heredada de la clase DataGridColumnStyle.

Dim ColEStilo1 As New DataGridTextBoxColumn


With ColEStilo1
.HeaderText = "Id Cliente"
.MappingName = "CustomerID"
.Width = 75
.ReadOnly = True
End With

Después de crear todos los estilos de las columnas a mostrar deben agregarse estos a la
colección GridColumnStyles del control DataGrid.
VAMOS CON EL EJEMPLO

A continuación sigue código en Visual Basic

'NameSpace necesarios
Imports System.Data
Imports System.Data.SqlClient

Public Class frmFormatoGrid


Inherits System.Windows.Forms.Form

'Definición del Dataset


Dim dsDatos As New DataSet

'Guargar el estilo del Borde


Dim EstiloBordeGrid As BorderStyle

Public vNombreTabla As String = "Clientes"

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


CÓDIGO ELIMINADO
#End Region

Private Sub frmFormatoGrid_Load(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MyBase.Load
LlenarGrid()
End Sub

Public Sub LlenarGrid()


'Llenar los datos del Grid
daClientes.Fill(dsDatos, "Clientes")
dgClientes.DataSource = dsDatos.Tables("Clientes")
End Sub

'Este Procedimiento es el que maneja todo


Private Sub Estilos(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmdPorDefecto.Click, cmdEstiloTabla.Click, _
cmdEstiloColumnas.Click

'Usando Sender para saber que control se pulsó


If sender Is cmdPorDefecto Then
PorDefecto()
ElseIf sender Is cmdEstiloTabla Then
EstiloTabla()
ElseIf sender Is cmdEstiloColumnas Then
EstiloColumna()
End If
End Sub

El codigo completo está en el empaquetado al final del artículo. Suerte a todos y no se


olviden dar su opinion en PanoramaBox.

El Control ListView (II)

Uso de la Vista Details

Sres. Desarrolladores, les envio otro ejercicio de ListView, este es mas completo, que el
anterior publicado, el link del anterior es el siguiente:
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm, en
este artículo usé estructuras junto con el control LstView.

UN POCO DE TEORIA (la misma del aporte anterior)

El control ListView es un control de lista que tiene mucha versatilidad, se puede utilizar
hasta en 4 vistas diferentes: LargeIcon, Details, SmallIcon y List (Iconos grandes,
Detalle, Iconos pequeños y Lista). Las mismas opciones están incluidas en el botón
Vistas del Explorador de Windows.

El control ListView se usa generalmente ligado a una o dos Listas de Imagenes


incluídas en controles ImageList, estos permiten mostrar los íconos de cada elemento
cuando se selecciona las opciones de LargeIcon y SmallIcon.

El control ListView presenta una lista de elementos que son heredados de la clase
ListViewItem, cada uno de estos elementos a su vez tiene Subelementos (SubItems),
que van relacionados con el ListViewItem respectivo.En la vista Detalle (propiedad
View en la opción Details) permite mostrar el control con los ListViewItem y los
SubItems respectivos en una cuadricula similar a un control Grid (control DataGrid). En
esta vista se muestran los encabezados de cada columna (colección Columns) donde
podemos asignar nombres a las mismas, un texto que se mostrará en cada una asi como
el ancho.

Como en todo control de Lista los elementos del control ListView se agregan a la
colección Items.

Pueden visitar los enlaces


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ComboBox.ht
m para el control ComboBox

http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ListBox.htm
para el control ListBox .

EL EJEMPLO

Este ejemplo es muy similar al anterior, pero aqui no se manejan los datos con
estructuras, dejo a criterio de ustedes desarrolladores la elección de como implementar
su uso.
A continuación sigue código en Visual Basic

'Las consistencias para el ingreso de datos no están creadas


Private Sub Agregar(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdAgregar.Click

Dim lvItem As ListViewItem


lvItem = New ListViewItem(txtcodigo.Text)
lvItem.SubItems.Add(txtnombre.Text)
lvItem.SubItems.Add(txtdni.Text)
lvItem.SubItems.Add(txtdireccion.Text)

'Insertar el ListViewItem al control ListView


lsvDatos.Items.Add(lvItem)
End Sub

Private Sub Eliminar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdEliminar.Click
Dim i As Integer
With lsvDatos
For i = .SelectedItems.Count - 1 To 0 Step -1
.Items.Remove(.SelectedItems.Item(i))
Next
End With
End Sub

El código completo está en el archivo adjunto, voten por mi PanoramaBox para que me
den mas aliento para seguir publicando. Suerte a todos.

Navegando en un Sitio Web

Como usar la autenticación en algunas páginas

res. Desarrolladores, en esta oprtunidad quiero compartir con ustedes este pequeño Site,
que muestra como navegar en el por las páginas donde solamente algunas necesitan de
autenticación.

Algunos ejemplos los encontramos en las páginas del Desarrollador Cinco Estrellas,
donde se puede navegar a través del sitio sin loguearse, solamente cuando accedemos al
perfil o a los examenes nos piden usuario y contraseña.

Muchos de los Sitios Web que construimos nos piden esa forma de trabajo, me parece la
forma mas sencilla de desarrollar esto con el uso de variables de sesión. El ejemplo que
comparto con ustedes tiene una ZONA DE MIEMBROS, la cual se accede siempre que
el usuario se haya autenticado.

A continuación sigue código en Visual Basic


En la página principal cuando se accede al enlace de zona de miembros...

Private Sub LinkButton4_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles LinkButton4.Click
' PARA PERFIL

If Session("Nombre") Is Nothing And Session("Clave") Is Nothing Then


Session("Pagina") = "1"
Response.Redirect("ParaLogin.aspx")
Else
Response.Redirect("MiPerfil.aspx")
End If
End Sub

Private Sub LinkButton5_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles LinkButton5.Click

' PARA COMPRAS


If Session("Nombre") Is Nothing And Session("Clave") Is Nothing Then
Session("Pagina") = "2"
Response.Redirect("ParaLogin.aspx")
Else
Response.Redirect("Compras.aspx")
End If
End Sub

Luego para comprobar al cargar la página directamente (solo implementado para la


página MiPerfil.aspx), se utiliza lo siguiente:

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MyBase.Load
'Introducir aquí el código d usuario para inicializar la página
' PARA PERFIL
If Session("Nombre") Is Nothing Or Session("Clave") Is Nothing Then
Session("Pagina") = "1"
Response.Redirect("ParaLogin.aspx")
End If
End Sub

Todo el código está en el archivo adjunto. No olviden calificar, me incentiva para seguir
publicando, suerte a todos

Controles Básicos en Visual Basic .Net

CheckedListBox, ListBox y ComboBox

Sres. Desarrolladores, les envio otro aporte, este trata de despejar algunas dudas de
como utiizar los controles básicos en una aplicación Windows usando Visual Basic
.Net.
EL EJEMPLO

Los controles mas utilizados en aplicaciones Windows son las cajas de texto y los
controles de lista, en este ejemplo se ingresa los datos de un producto que se repartirá
entre los departamentos que se seleccionen de una empresa, la cantidad de
departamentos es mínimo dos.

Se usan variables y se grafica un poco como usar estas a nivel de clase y como cambiar
y manejar su valor entre los diferentes procedimientos.En este ejemplo se ingresa una
cantidad de un supuesto producto que luego según los departamentos seleccionados
tendrá que repartirse. Note ciertas consistencias en el ingreso de datos y luego en el
manejo de las variables. Suerte.

A continuación sigue código en Visual Basic .Net

Private Sub SeleccionaDepas(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdSelec.Click

'Procedimiento para seleccionar los departamentos


'Comprobar el ingreso correcto de datos
If Len(Trim(txtIDProd.Text)) = 0 Or Len(Trim(txtCanti.Text)) = 0 Or
Len(Trim(txtDescrip.Text)) = 0 Then
MessageBox.Show("Faltan datos...", "Error...", MessageBoxButtons.OK)
Exit Sub
End If

'Comprobar que la cantidad sea ingreso numérico

If Not IsNumeric(txtCanti.Text) Or Val(txtCanti.Text) <= 0 Then


MessageBox.Show("Cantidad no válida...", "Error...", MessageBoxButtons.OK)
Exit Sub
End If

'Para saber cuantos hay seleccionados


Dim c As Integer
For i = 0 To chklDepas.Items.Count - 1
If chklDepas.GetItemChecked(i) = True Then
c += 1
End If
Next

If c >= 2 Then
cboDepa.Items.Clear()
lstAsignado.Items.Clear()
cmdMostrar.Enabled = True
cmdAsignar.Enabled = False
For i = 0 To chklDepas.Items.Count - 1
If chklDepas.GetItemChecked(i) = True Then
cboDepa.Items.Add(chklDepas.Items.Item(i))
End If
Next

'Regresar los valores asignados a CERO


vAdministracion = 0 : VContabilidad = 0 : vProduccion = 0 : vVentas = 0
txtCantiAsigna.Clear()
lblRestantes.Text = txtCanti.Text
vRestante = Val(lblRestantes.Text)
lblProducto.Text = "Producto : "
Else
MessageBox.Show("Son dos departamentos como mínimo...", "Error...",
MessageBoxButtons.OK)
End If
End Sub

Private Sub SeleccionarDepa(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cboDepa.SelectedIndexChanged
cmdAsignar.Enabled = True
Select Case cboDepa.SelectedItem
Case "Administración"
txtCantiAsigna.Text = vAdministracion
Case "Contabilidad"
txtCantiAsigna.Text = VContabilidad
Case "Producción"
txtCantiAsigna.Text = vProduccion
Case "Ventas"
txtCantiAsigna.Text = vVentas
End Select
End Sub

El código completo se encuentra en el archivo adjunto, suerte a todos y no se olviden de


dar su calificación en PanoramaBox, eso me alienta a seguir publicando.

Iniciando en ASP .Net

Uso de los principales controles


Uso de los controles Button

Sres. Desarrolladores, esta oportunidad les envio un aporte en ASP .Net, en este artículo
muy simple intento explicar el uso de los principales controles en ASP y el uso de los
Controles Button.

ALGO DE TEORIA

Existe diferencias entre una aplicación Windows y una aplicación ASP .Net,
basicamente en el uso de los principales controles como:

 TextBox (cajas de texto)


 RadioButton (botones de opción)
 ListBox y ComboBox (DropDownList en aplicación ASP .Net)
 CheckBox (casilla de verificación)
 Asi como la existencia de controles nuevos en este tipo de aplicaciones como
son: RadioButtonList y CheckBoxList.

Hemos de anotar que la mayor parte de aplicaciones utilizan mucho estos controles, por
lo que este artículo está orientado a explicar lo mas importante de cada uno de ellos.

El control Web TextBox

Caja de texto, control que almacena datos alfanuméricos como nombres, emails,
direcciones, etc. El uso de este control es básico en todo tipo de aplicaciones.

Algunas propiedades importantes:

Propiedad Descripción
Obtiene o establece la tecla de
acceso rápido en combinación con
AccessKey
la tecla ALT. Solo se permite una
letra.
BorderColor, BorderStyle,
Color, Estilo y ancho del borde
BorderWidth
Obtiene o establece si la caja de
Enabled
texto está disponible
MaxLength Longitud máxima del texto
Comportamiento de la caja de
texto:
SingleLine: para una sola linea
TextMode
MultiLine: múltiples líneas
Password: para el ingreso de
contraseñas
Obtiene o establece el contenido de
la caja de texto, para borrar el
Text contenido podemos usar la
siguiente línea:
txtNombre.Text = ""

Algo mas, la definición en la vista HTML del control Web TextBox es como sigue:

<asp:TextBox
id="txtNombre"
runat="server"
accessKey="N"></asp:TextBox>

El control Web RadioButton


Este control permite la selección de una opción dentro de un grupo. Las opciones están
visibles y generalmente son pocas, si la cantidad de opciones fueran muchas podría
usarse un control de lista como ListBox o DropDownList (ComboBox).

Parte importante: EN APLICACIONES DE ESCRITORIO para agrupar botones de


opción se podía usar un Panel o el control GroupBox, con esto se consigue que dos o
mas grupos de estos controles funcionen de manera independiente. EN
APLICACIONES ASP .NET no se puede, para agrupar los botones de opción se debe
especificar a cada miembro del grupo el MISMO NOMBRE en la propiedad
GroupName.

Algunas propiedades importantes:

Propiedad Descripción
Obtiene o establece la tecla de
acceso rápido en combinación con
AccessKey
la tecla ALT. Solo se permite una
letra.
BorderColor, BorderStyle,
Color, Estilo y ancho del borde
BorderWidth
Obtiene o establece si la caja de
Enabled
texto está disponible
MaxLength Longitud máxima del texto
True: El control está seleccionado
Cheched False: El control no está
seleccionado
Obtiene o establece el texto que
Text
muestra el control

Algo mas, la definición en la vista HTML del control Web RadioButton es como sigue:

<asp:RadioButton
id="optEstable"
runat="server" Text="Estable"
Checked="True"
GroupName="condicion"></asp:RadioButton>

Los Controles Web ListBox y DropDownList (ComboBox)

Los controles ListBox y DropDownList de aplicaciones ASP .Net son muy similares, la
diferencia o la decisión de usar uno o el otro es el espacio para el diseño y el tipo de
selección. Si no hay suficiente espacio en la aplicación puede ser mejor usar un
DropDownList, si existe mejor un ListBox; el control ListBox permite la selección de
varias alternativas, sin embargo el control DropDownList no.

Algunas propiedades importantes:


Propiedad Descripción
Obtiene o establece la tecla de
acceso rápido en combinación con
AccessKey
la tecla ALT. Solo se permite una
letra.
DataSource Establece el origen de datos
Establece el DataTable cuando el
DataMember
origen de datos en un DataSet
Responde a los eventos
AutoPostBack
automáticamente
Muestra el origen de datos que
DataTextField proporciona el texto que muestra el
control.
Es el campo del orígen de datos
DataValueField que proporciona el valor del
elemento seleccionado.
Proporciona el texto de la opción
SelectedItem
seleccionada
Proporciona el índice de la opción
seleccionada.
SelectecIndex
El valor es -1 si no hay opción
seleccionada.

Algunos apuntes importantes:

 Tenga en cuenta el de la página si agrega las opciones de estos controles en el


evento Load del WebForm, para comprobar si cargo se utiliza Page.IsPostBack.
 La colección Items representa las opciones presentes del control.

LOS CONTROLES BUTTON

Los controles Button en aplicaciones ASP .Net son:

 Control Button
 Control LinkButton
 Control Hyperlink
 Control ImageButton

Control Descripción
Control de servidor Presenta un botón de comando estándar, que se representa
Web Button como un botón "Enviar" de HTML.
Control de servidor Se representa como un hipervínculo en la página. No obstante,
Web LinkButton contiene una secuencia de comandos del lado cliente que hace
que el formulario se devuelva al servidor. (Puede crear un
hipervínculo auténtico mediante el control de servidor Web
HyperLink).
Control de servidor Permite especificar un gráfico como botón. Esto es útil para
Web ImageButton representar los botones con una apariencia más rica. Los
controles ImageButton determinan con precisión el punto en
el que hizo clic el usuario, lo que permite utilizar el botón
como si fuera un mapa de imagen.

El cuadro anterior fue extraído de la ayuda de Visual Studio.

NUESTRO EJEMPLO

Basta de lectura, un ejemplo sencillo pero me parece útil.

Importante: El ingreso de datos en las cajas de texto y la selección de las opciones de


las lista no está validado, es posible que si se ejecuta el botón ¿Quién es? muestre un
error, en este código se obtienen los datos de los diferentes controles utilizados.

La ultima: NOTE que se ha implementado un bloque SCRIPT para el último botón


ImageButton, ya publicaré otro artículo con mas detalle.

Private Sub Page_Load(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles MyBase.Load
'Introducir aquí el código de usuario para inicializar la página
If Not Page.IsPostBack Then
ListBox1.Items.Add("Fernando")
ListBox1.Items.Add("Carolina")
ListBox1.Items.Add("Fernandito")
ListBox1.Items.Add("María Fernanda")
ListBox1.Items.Add("Ingrid")
ListBox1.Items.Add("Aracely")
ListBox1.Items.Add("Esmeralda")
ListBox1.Items.Add("Carlos")
End If
End Sub

Private Sub DropDownList1_SelectedIndexChanged(ByVal sender As


System.Object, ByVal e As System.EventArgs) Handles
DropDownList1.SelectedIndexChanged

Select Case DropDownList1.SelectedIndex


Case 0
txtBasico.Text = 1500
Case 1
txtBasico.Text = 1320
Case 2
txtBasico.Text = 1000
Case 3
txtBasico.Text = 1908
Case 4
txtBasico.Text = 3200
Case 5
txtBasico.Text = 2300
End Select
End Sub

El código completo está en el archivo adjunto al final del artículo, suerte a todos y no se
olviden botar en mi PanoramaBox, eso me alienta a seguir publicando. Suerte a todos.

Ing. Fernando Luque Sánchez


Trujillo - Perú

ListView Avanzado

Uso de Vistas
Manejo de los datos del Item seleccionado

Sres. Desarrolladores, este ejemplo trata de mostrar el uso del control ListView, además
de incluir un ContextMenu para permitir al usuario seleccionar la Vista que desee de
este. Lo artículos antes publicados respecto a este mismo control son:

El control ListView –Parte


I: http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm

El control ListView
(II): http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListVie
wII.htm

En una cuarta parte manejaré el control enlazado a una base de datos en SQL Server y
otro con el uso del control TreeView.

UN POCO DE TEORIA

El control ListView es un control muy versatil, permite mostrar un conjunto de datos de


manera tabular similar al control DataGrid y tambien mostrar sus elementos con las
opciones similares a las vistas del Explorador de Windows: Detalle, Iconos Grandes,
Iconos Pequeños y Lista, para conseguir esto se modifica la propiedad View.

El Control ListView se puede enlazar al control ImageList para determinar el ícono de


cada elemento, tanto para las opciones de Vista: Iconos Grandes e Iconos Pequeños, las
propiedades a cambiar son LargeImageList para Iconos Grandes y SmallImageList
para Iconos Pequeños.

Algunas propiedades importantes:

Propiedad Descripción
Indica si el usuario puede reordenar las
AllowColumnReorder
columnas
CheckBoxes Indica si se muestran casillas de
verificación
Indica si al seleccionar un Item se marcan
FullRowSelect todos los SubItems del elemento
seleccionado
GridLines Muestra las líneas en la vista Details
MultiSelect Permite la selección de Multiples Items
View Cambia la Vista
Permite que el usuario modique
LabelEdit
directamente las etiquetas de los elementos.
Columnas que se mostrarán en la vista
Columns
Detalle (Details)
Identificador de cada elementos del
Items
ListView
Conjunto de elementos que dependen del
SubItems
Item

NUESTRO EJEMPLO

En el ejemplo que comparto con ustedes les incluyo dos controles ListView, el primero
con 4 elementos incluídos con la vista Detalle por defecto, este primer ListView tiene
especificados las propiedades SmallImageList y LargeImageList y también un menú
contextual para cambiar la vista del control.

El botón Copiar copia los elementos seleccionados a un array y luego los incluye en el
segundo ListView, si bien es cierto pueden hacerlo directamente, hago esto debido a
una consulta que me hicieron por el correo, ¿COMO PUEDO COPIAR LOS DATOS
DEL LISTVIEW A OTRO FORMULARIO?, me parece que contanto con un array
definido en un módulo es sumamente sencillo conseguir esto. En otro envio trabajaré
con datos extraido de una base de datos de SQL Server.

A continuación sigue código en Visual Basic:

Private Sub Cargar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

LlenarListview()
FormatoGridCopiados()

End Sub

'Procedimiento para formatear el ListView


Sub LlenarListview()
lsvDatos.GridLines = True
lsvDatos.FullRowSelect = True
'Encabezados
lsvDatos.Columns(0).Text = "Id. Empleado"
lsvDatos.Columns(1).Text = "Nombre"
lsvDatos.Columns(2).Text = "Edad"
lsvDatos.Columns(3).Text = "Dirección"

'Ancho de cada Columna


lsvDatos.Columns(0).Width = 100
lsvDatos.Columns(1).Width = 200
lsvDatos.Columns(2).Width = 50
lsvDatos.Columns(2).TextAlign = HorizontalAlignment.Right
lsvDatos.Columns(3).Width = 280

'Llenar algunos Items en el ListView


'EN LA PARTE PRACTICA...REAL LOS SACAMOS DE UN DataTable
'Los datos de la familia....la razón de mi esfuerzo
'con esas direcciones no me encontrarán.....je,je,je...

lsvDatos.Items.Add("FL3049", 0)
lsvDatos.Items(0).SubItems.Add("Ing. Fernando Luque Sánchez")
lsvDatos.Items(0).SubItems.Add("39")
lsvDatos.Items(0).SubItems.Add("Av. Brasil 567 Lima")

lsvDatos.Items.Add("CVA049", 1)
lsvDatos.Items(1).SubItems.Add("Carolina Villacorta de Luque")
lsvDatos.Items(1).SubItems.Add("39")
lsvDatos.Items(1).SubItems.Add("Av. Angamos Oeste 466")

lsvDatos.Items.Add("FLV456", 2)
lsvDatos.Items(2).SubItems.Add("Fernando Luque Villacorta")
lsvDatos.Items(2).SubItems.Add("8")
lsvDatos.Items(2).SubItems.Add("Av. Larco 906 Miraflores")

lsvDatos.Items.Add("MFL012", 3)
lsvDatos.Items(3).SubItems.Add("María Fernanda Luque Villacorta")
lsvDatos.Items(3).SubItems.Add("4")
lsvDatos.Items(3).SubItems.Add("Canaval y Moreyra 499 La Molina")
End Sub

Sub FormatoGridCopiados()
lsvSelec.GridLines = True
lsvSelec.FullRowSelect = True

'Encabezados
lsvSelec.Columns(0).Text = "Id. Empleado"
lsvSelec.Columns(1).Text = "Nombre"
lsvSelec.Columns(2).Text = "Edad"
lsvSelec.Columns(3).Text = "Dirección"
'Ancho de cada Columna
lsvSelec.Columns(0).Width = 100
lsvSelec.Columns(1).Width = 200
lsvSelec.Columns(2).Width = 50
lsvSelec.Columns(2).TextAlign = HorizontalAlignment.Right
lsvSelec.Columns(3).Width = 280
End Sub

El código completo está en el archivo adjunto. Recuerda votar en mi PanoramaBox, los


puntos me alientan a seguir publicando, y gracias a ustedes por su preferencia. Suerte a
todos

Uso de DataBinding

Maestro - Detalle: Empleados - Órdenes

Sres. Desarrolladores, en esta ocasión mi aporte intenta orientar en el uso de


la propiedad DataBinding, la cual contiene información sobre una expresión de enlace
a datos usando tecnología RAD (Rapid Application Developer). Esta clase no se puede
heredar.

Información adicional de RAD en los siguientes enlaces:


http://www.linux.org.pe/ldd2005/ldd2005-php5_xul-clever-flores.pdf
http://www.ldc.usb.ve/~vtheok/cursos/ci3711/apuntes/99-01-14/Info/Modelo RAD.htm
http://buscador.hispavista.es/rad/

Los controles que con regularidad se utilizan en aplicaciones Windows así como en
aplicaciones Web tienen la propiedad DataBinding, es necesario configurar la propiedad
de cada control que contendrá en enlace a los datos, luego para administrar esta se debe
utilizar la propiedad BindingContext de la clase contenedora. Al usar el
BindingContext obtiene el BindingManagerBase que mantiene sincronizados todos los
controles enlazados al mismo origen de datos, se puede utilizar la propiedad Position
del BindingManagerBase para especificar el elemento actualmente seleccionado de una
lista.

Por ejemplo, para enlazar una caja de texto con el campo FirsName de la Tabla
Empleados (dtEmpleados) contenida en una DataSet previamente definido utilizo la
siguiente instrucción:

txtNombre.DataBindings.Add("Text", dtEmpleados, "FirstName")

Luego para administrar por ejemplo la posición actual o lo que es lo mismo el registro
activo se utiliza la siguiente instrucción:

Me.BindingContext(dtEmpleados).Position = 0

Note en la instrucción anterior que se utiliza ña propiedad BindingContext del


formulario, como lo dicho en líneas arriba, la propiedad Position va a mantener
sincronizados todos los controles enlazados al DataTable dtEmpleados.

NUESTRO EJEMPLO
El ejemplo muestra un formulario donde aparecen los Empleados (Tabla Employees), el
Total de sus ventas, las Órdenes Registradas (Tabla Oders) por el Empleado y el
Detalle de las mismas (Tabla Order Details). La Base de datos es Northwind.

Se ha utilizado un SQLDataAdapter, definido mediante código, para generar los


comandos SQL se ha utilizado un SQLCommandBuilder, luego al SQLDataAdapter
cambiamos el SQLCommand Select para poder llenar los DataTables.

Las órdenes Select para nuestro ejemplo son las siguientes:

1. Para poder llenar el DataTable de Órdenes:

/*ID de la Orden, Total, Id Empleado, la Fecha y el Nombre de la Compañía*/

SELECT od.OrderID, SUM(CONVERT(money, (od.UnitPrice * od.Quantity) * (1 -


od.Discount) / 100) * 100)
AS Total, o.EmployeeID, o.OrderDate, c.CompanyName
FROM [Order Details] od
INNER JOIN Orders o
ON od.OrderID = o.OrderID
INNER JOIN Customers c
ON o.CustomerID = c.CustomerID
GROUP BY od.OrderID, o.EmployeeID, o.OrderDate, c.CompanyName

2. Para llenar Total de las ventas creamos un DataTable con el Id del Empleado y el
valor total de las Órdenes.

/*ID del Empleado y el Total de sus ventas*/


SELECT e.employeeid, sum(UnitPrice * Quantity)
As SalesToDate
FROM [order details] od
INNER JOIN orders o
ON o.orderid = od.orderid
INNER JOIN employees e
ON e.employeeid = o.employeeid
GROUP BY e.employeeid

3. Para llenar el DataTable de Detalle de las órdenes:

/*Orden select para el Detalle de las órdenes Extrae:


ID de la Orden, Precio, Cantidad, Descuento, Nombre Producto
nombre de Categoía y Subtotal*/
SELECT od.OrderID, od.UnitPrice, od.Quantity, od.Discount, p.ProductName,
c.CategoryName, (od.UnitPrice * od.Quantity)
As SubTotal
FROM [order details] od
INNER JOIN Products p ON od.ProductID = p.ProductID
INNER JOIN Categories c ON c.CategoryID = p.CategoryID
ORDER BY od.OrderID
Las instrucciones Select anteriores puedes copiarlas al Query Analyzer de SQL Server
usando la base de datos Northwind para ver los resultados, es obvio que todos los
lectores conocen de la sintaxis y del uso de Transac SQL.

En el ejemplo se han incluído cuatro DataTable y tres Vistas, con las siguientes órdenes
asigno los DataTables creados a variables y especifico el origen de las Vistas creadas.

'Asignar los DataTables a las Variables definidas


dtEmpleados = dsDatos.Tables("Empleados")
dtOrdenes = dsDatos.Tables("Ordenes")
dtVentas = dsDatos.Tables("Ventas")
dtDetalle = dsDatos.Tables("Detalle")

'Especificar las Vistas


dvOrdenes = dtOrdenes.DefaultView
dvVentas = dtDetalle.DefaultView
dvDetalle = dtDetalle.DefaultView

Luego se agregan los DataBindings para los controles y conseguimos mantener


enlazados y sincronizados los controles.

A continuación sigue código en Visual Basic:

El siguiente es una porción del código, intento mostrar la zona de declaraciones para
que se den cuenta de los datos definidos:

Public Class frmPrincipal


Inherits System.Windows.Forms.Form

'Definición de los elementos a utilizar la cadena de conexión


Dim vcadenaCon As String = _
"workstation id=HOME;packet size=4096;user id=fernnado; integrated
security=SSPI;data source=(local);persist security info=False;initial
catalog=Northwind"

'El DataSet, las Tablas y las Vistas.


Dim dsDatos As DataSet
Dim dtEmpleados As DataTable
Dim dtOrdenes As DataTable
Dim dtDetalle As DataTable
Dim dtVentas As DataTable

'Las vistas
Dim dvOrdenes As DataView
Dim dvDetalle As DataView
Dim dvVentas As DataView

'El SQLDataAdapter
Dim daDatos As SqlDataAdapter
.....

Al cargar el formulario se ejecuta lo siguiente:

Private Sub CargarForm(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load
'Crear y llenar el DataSet
CrearDataSet()
'Enlazar los controles al DataSet
IniciarBinding()
LlenarGridOrdenes()
LlenarGridDetalle()
MostrarRegistro()
End Sub

El procedimiento para crear y añadir los DataBindings a los controles es como sigue:

Private Sub iniciarbinding()


'Las cajas de texto
txtNombre.DataBindings.Add("Text", dtEmpleados, "FirstName")
txtId.DataBindings.Add("Text", dtEmpleados, "EmployeeID")
txtApel.DataBindings.Add("Text", dtEmpleados, "LastName")
txtDire.DataBindings.Add("Text", dtEmpleados, "Address")
txtCiudad.DataBindings.Add("Text", dtEmpleados, "City")
txtTotal.DataBindings.Add("Text", dtVentas, "TotalVentas")

'Controlador para actualizar los grids al cambiar el registro activo


AddHandler Me.BindingContext(dtEmpleados).PositionChanged, AddressOf
CambioPosicion
End Sub

Para que puedas ejecutar el ejemplo baja el código fuente al final del artículo y actualiza
tu cadena de conexión, no te olvides de calificarme en PanoramaBox, si lo haces me das
los puntos que me incentiva seguir publicando. Suerte a todos y A SEGUIR
DESARROLLANDO....cualquier consulta por correo.

Ordenar y Filtrar un DataView

Uso de Sort y RowFilter

Sres. Desarrolladores, en esta oportunidad quiero mostrar en una aplicación sencilla el


uso de Vistas. Usando la base de datos Northwind y la tabla productos muestro opciones
para ordenar y para filtrar un DataView.

UN POCO DE TEORIA

Un DataView permite crear diferentes Vistas de los datos almacenados en una


DataTable asignandole diferentes criterios de ordenación y filtrado. El DataView
presenta una vista dinámica de los datos contenidos en un DataTable, en importante
anotar que el DataView no se puede tratar como una Tabla y no puede
proporcionar vista de tablas combinadas.

El DataView tampoco puede Excluir o Incliur columnas que no existen en la tabla


original como por ejemplo las columnas o campos calculados.

Crear un DataView

Para crear un DataView existen dos formas:

1. Crear una referencia a la propiedad DefultView de la Tabla origen, como la siguiente


orden

Dim dvProductos As DataView = dsDatos.Tables("Productos").DefaultView

2. Utilizando el Constructor del DataView, para esto debe asignarse los parámetros
necesarios como: el DataTable de Origen, la cadena de Filtrado (Propiedad RowFilter),
la cadena de Ordenamiento (Sort) y el estado de las filas o registros que muestre
(RowState). En nuestro ejemplo utilizamos la siguente instrucción:

dvProductos = New DataView(dsDatos.Tables("Productos"), "ProductName like


'%'", "ProductName ASC", DataViewRowState.OriginalRows)

Donde:

 dsDatos.Tables.("Productos") ==> es el DataTable origen


 "ProductName Like '%'" ==> es la cadena de Filtrado (Todos)
 "ProductName ASC" ==> es el criterio de Ordenamiento
 DataViewRowState ==> el estado de las filas a mostrar.

Ordenar y Filtrar un control DataView

La propiedad Sort permite establecer criterios simple y múltiples de ordenación de


columnas, donde se puede incluir los parametros ASC para orden ascendente y DESC
para orden descendente. Se puede utilizar la propiedad ApplyDefaultSort para crear un
criterio de ordenación por defecto de acuerdo a la clave principal del DataTable, este
ordenamiento aplica cuando la propiedad Sort es una cadena vacia.

Para nuestro ejemplo la cadena de conexión la armamos con las opciones seleccionadas
previamente:

'Armar la cadena de Orden


Dim vCadenaDos As String = "UnitsInStock " & IIf(optAscStock.Checked, "ASC",
"DESC")
vCadenaDos &= ", UnitsOnOrder " & IIf(optAscOrden.Checked, "ASC", "DESC")
'Ordenar la Vista
dvProductos.Sort = vCadenaDos

Las opciones de ordenación de la porción de código anterior se extraen teniendo en


cuenta el estado de los botones de opción optAscStock y optASCOrden.
También podemos utilizar los métodos Find o FindRows para filtrar los datos de un
DataView, consiguiendo un máximo rendimiento de nuestra aplicación.

Las opciones del estado de los registros DataViewRowState en la creación de la vista


utilizando el constructor son las siguentes:

DataViewRowState Descripción
CurrentRows La versión de fila Current de todas las filas
Unchanged, Added y Modified. Éste es el valor
predeterminado.
Added La versión de fila Current de todas las filas
Added.
Deleted La versión de fila Original de todas las filas
Deleted.
ModifiedCurrent La versión de fila Current de todas las filas
Modified.
ModifiedOriginal La versión de fila Original de todas las filas
Modified.
None Ninguna fila.
OriginalRows La versión de fila Original de todas las filas
Unchanged, Modified y Deleted.
Unchanged La versión de fila Current de todas las filas
Unchanged.

En otro aporte enviare un código para poder modificar los datos mediante DataView, les
adelanto que se puede controlar esto con las propiedades AllowNew, AllowEdit y
AllowDelete. Tenga en cuenta que los cambios definitivos en la base de datos se
efectuan con los métodos AcceptChanges o RejectChanges de DataTable de origen.
Una cosa muy importante, sabemos que las aplicaciones constan siempre de varios
DataTables relacionados, para sincronizar las vistas de todas las tablas del DataSet es
ideal utilizar un DatAViewManager.

A continuación sigue código en Visual Basic:

Private Sub CargarFormulario(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

'Combo con las letras


Dim aLetras() As String = {"<ALL>", "A", "B", "C", "D", "E", "F", "G", "H", "I",
"J", "K", "L", "M", "N", "Ñ", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y",
"Z"}
cboLetraInicial.Items.AddRange(aLetras)
cboLetraInicial.SelectedIndex = 0

'Combo con los Operadores


Dim aOperadores() As String = {"<", "<=", "=", ">=", ">"}
cboOperador.Items.AddRange(aOperadores)
cboOperador.SelectedIndex = 0
'Combo con los nombres de campo
Dim aCampos As String() = {"ProductId", "ProductName", "UnitPrice",
"UnitsInStock", "UnitsOnOrder"}
cboCampos.Items.AddRange(aCampos)

'Conectar a la Base de datos: Conexión, Adaptador y DataSet


Dim cn As New SqlConnection("workstation id=HOME;packet size=4096;user
id=fernnado;integrated security=SSPI;data source=(local);persist security
info=False;initial catalog=Northwind")
Dim daProductos As New SqlDataAdapter("Select ProductId, ProductName,
UnitPrice, UnitsInStock, UnitsOnOrder from Products", cn)
Dim dsDatos As New DataSet
daProductos.Fill(dsDatos, "Productos")
With drgProductos
.CaptionText = "Productos Registrados"
.CaptionForeColor = Color.Red
.ReadOnly = True
End With

'Etiquetas por defecto


'El ordenamiento de los Productos por defecto tiene el siguiente orden
lblFiltroActual.Text = "Todos"
lblOrdenActual.Text = "ProductName ASC"

'No olvidemos que para filtrar necesitamos la vista


dvProductos = New DataView(dsDatos.Tables("Productos"), "ProductName like
'%'", "ProductName ASC", DataViewRowState.OriginalRows)

'Origen del Grid


drgProductos.DataSource = dvProductos
End Sub

Private Sub OrdenarUnica(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdOrdenCampos.Click
'PROCEDIMIENTO QUE ORDENA LA VISTA CON UNA SOLA CLAVE
If cboCampos.SelectedIndex = -1 Then
MessageBox.Show("Seleccione el campo para ordenar...", "Atención",
MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
Exit Sub
End If

'Cadena de ordenamiento
Dim vCadenaOrden As String = cboCampos.SelectedItem & " " &
IIf(optASCcampos.Checked, "ASC", "DESC")
dvProductos.Sort = vCadenaOrden
drgProductos.DataSource = dvProductos
lblOrdenActual.Text = vCadenaOrden
End Sub
El código completo se encuentra en el archivo adjunto al final del artículo, suerte a
todos y A SEGUIR DESARROLLANDO, cualquier consulta al correo que se encuentra
al inicio.

Controles de Lista enlazados a Base de datos

Como llenar ListBox, ComboBox y CheckedListBox

Sres. Desarriolladores, este artículo pretende mostrar como enlazar los controles de
lista ListBox, ComboBox y CheckedListBox al contenido de una tabla en una base de
datos de SQL Server.

En el artículo que comparto con ustedes utilizo las tablas Customers, Products y Region
de la base de datos Northwind.

UN POCO DE TEORIA

En las aplicaciones de escritorio son muy utilizados los controles de lista, especialmente
los controles ListBox y ComboBox. También para mostrar un grupo de casillas de
verificación se utiliza el control CheckedListBox.

He publicado otros artículos que muestran el uso de estos controles pero sin enlace a
base de datos:

El control ComboBox:
http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_Co
mboBox.htm

El control ListBox, Opciones principales:


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_Li
stBox.htm

Controles en Visual Basic .Net - El control CheckedListBox:


http://www.elguille.info/colabora/puntoNET/FernandoLuque_Controles.htm

Controles de Lista en Visual Basic .Net


http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesBasic
os.htm

Para no llenar de texto el artículo, les comento que en le ayuda de Visual Studio
se encuentra la explicación detallada de como manejar estos controles, les
incluyo una parte:

Las propiedades Items, SelectedItems y SelectedIndices proporcionan acceso a las tres


colecciones que ListBox utiliza. En la tabla siguiente se presentan las tres colecciones
que ListBox utiliza y se indica su uso dentro del control.

Clase de colección Uso dentro del cuadro de lista


ListBox.ObjectCollection Contiene todos los elementos
incluidos en el control ListBox.
ListBox.SelectedObjectCollection Contiene una colección de los
elementos seleccionados, que
constituye un subconjunto de los
elementos incluidos en el control
ListBox.
ListBox.SelectedIndexCollection Contiene una colección de los
índices seleccionados, que
constituye un subconjunto de los
índices de
ListBox.ObjectCollection. Estos
índices especifican los elementos
seleccionados.

En los tres ejemplos siguientes se muestran las tres colecciones indizadas que admite la
clase ListBox.

En la tabla siguiente, se muestra un ejemplo de cómo ListBox.ObjectCollection


almacena los elementos de ListBox así como su estado de selección dentro de un
control ListBox de ejemplo.

Índice Elemento Estado de selección


dentro del control
ListBox
0 objeto1 No seleccionado
1 objeto2 Seleccionado
2 objeto3 No seleccionado
3 objeto4 Seleccionado
4 objeto5 Seleccionado

En función de la clase ListBox.ObjectCollection que se muestra en la tabla anterior,


esta tabla indica cómo aparecerá la colección ListBox.SelectedObjectCollection.

Índice Elemento
0 objeto2
1 objeto4
2 objeto5

En función de la clase ListBox.ObjectCollection que se muestra en la tabla anterior,


esta tabla indica cómo aparecerá la colección ListBox.SelectedIndexCollection.

Índice Índice de elemento


0 1
1 3
2 4
El método Add de la clase ListBox.ObjectCollection permite agregar elementos a
ListBox. El método Add puede aceptar cualquier objeto al agregar un miembro a
ListBox. Cuando se agrega un objeto a ListBox, el control utiliza el texto definido en el
método ToString del objeto, a menos que se especifique un nombre de miembro del
objeto en la propiedad DisplayMember. Para agregar elementos, además del método
Add de la clase ListBox.ObjectCollection, puede usar también la propiedad
DataSource de la clase ListControl.

NUESTRO EJEMPLO

En este artículo que comparto con ustedes señores desarrolladores, les muestro como
llenar los controles con los elementos de una base de datos de dos formas:

1. Mostrando varios campos de una tabla o lo que es lo mismo varias


columnas de un DataTable haciendo un recorrido por este. Por ejemplo:

Dim i As Integer
For i = 0 To dsDatos.Tables("Productos").Rows.Count - 1
'Llenar ProductId, ProductName y UnitPrice
Dim vdato As String
vdato = dsDatos.Tables("Productos").Rows(i).Item(0).ToString
vdato &= Space(5) &
dsDatos.Tables("Productos").Rows(i).Item(1).ToString
vdato &= Space(5) &
dsDatos.Tables("Productos").Rows(i).Item(5).ToString
cboTres.Items.Add(vdato)
Next

2. Especificando las propiedades de los controles de Lista DataSource,


DisplayMember y ValueMember, de esta forma se especifica como
sigue:

Propiedad Índice de elemento


DataSource Especifica el origen
de datos
DisplayMember La columna del
origen de datos que
se mostrará
ValueMember El dato que se
utilizará como
elemento a
seleccionar.

Por ejemplo:

cboTodos.DataSource = dsDatos.Tables("Productos")
cboTodos.DisplayMember = dsDatos.Tables("Productos").Columns(1).ToString
cboTodos.ValueMember = dsDatos.Tables("Productos").Columns(0).ToString
A continuación sigue código en Visual Basic:

Private Sub List03Campos(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLlenar.Click

'Definir la cadena de Conexión


Dim cn As New SqlConnection("workstation id=HOME;packet size=4096;user
id=fernnado;integrated security=SSPI;data source=(local);persist security
info=False;initial catalog=Northwind")

'Crear el SQLDataAdapter
Dim daDatos As New SqlDataAdapter("Select * from Customers", cn)

'Crear el DataSet
Dim dsDatos As New DataSet

'Llenar el DataTable
daDatos.Fill(dsDatos, "Clientes")

'Para llenar la Lista


lstClientes01.Items.Clear() 'Borrar los datos que tenga

Dim i As Integer
For i = 0 To dsDatos.Tables("Clientes").Rows.Count - 1
'Llenar CustomerId, CompanyName, ContactName
Dim vdato As String
vdato = dsDatos.Tables("Clientes").Rows(i).Item(0).ToString
vdato &= Space(5) & dsDatos.Tables("Clientes").Rows(i).Item(1).ToString
vdato &= Space(5) & dsDatos.Tables("Clientes").Rows(i).Item(2).ToString
lstClientes01.Items.Add(vdato)
Next
End Sub

Private Sub ListTodosCampos(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLlenar01.Click

'Definir la cadena de Conexión

'' ES CIERTO....LA PUEDO DEFINIR EN LA ZONA DE DECLARACIONES


'' Y LUEGO INSTANCIARLA EN CADA PROCEDIMIENTO ...

Dim cn As New SqlConnection("workstation id=HOME;packet size=4096;user


id=fernnado;integrated security=SSPI;data source=(local);persist security
info=False;initial catalog=Northwind")
'Crear el SQLDataAdapter
Dim daDatos As New SqlDataAdapter("Select * from Customers", cn)
'Crear el DataSet
Dim dsDatos As New DataSet
'Llenar el DataTable
daDatos.Fill(dsDatos, "Clientes")

'Para llenar la lista solo basta especificar las


'propiedades DataSource, DisplayMember y ValueMember
lstClientes02.DataSource = dsDatos.Tables("Clientes")
lstClientes02.DisplayMember = dsDatos.Tables("Clientes").Columns(1).ToString
lstClientes02.ValueMember = dsDatos.Tables("Clientes").Columns(0).ToString
End Sub

El código completo está en el archivo adjunto al final del artículo, cualquier consulta al
correo que se encuentra al inicio del artículo. No olvides dar tu voto en mi
PanoramaBox. Suerte a todos y a seguir desarrollando.

DataSets Tipificados y No Tipificados I

Diferencias entre los tipos de DataSet

Sres. Desarrolladores, este es el primero de una serie de artículos que estoy preparando
para explicar el uso de DataSets, para los que desarrollamos aplicaciones en Visual
Studio tanto para Windows como aplicaciones Web sabemos que toda la información la
manejamos en DataSets, por lo que creo necesario que conozcamos lo mejor posible
estos.

UN POCO DE TEORIA

Un DataSet es un reservorio de datos en la memoria del Cliente en aplicaciones


Windows y en la memoria del Servidor para las aplicaciones ASP .Net, estas trabajan
en ambientes desconectados, la estructura de un DataSet es similar a la de una base de
datos en el cual se exponen de manera jerárquica las tablas, filas y columnas que
contiene.

El modelo de trabajo con datos desde una base de datos en aplicaciones con Visual
Studio .Net necesita de una Adaptador, este relaciona el DataSet con la Tabla
correspondiente en la base de datos, se encarga de la Inserción, Modificación,
Eliminación y Selección de registros.

El uso de DataSets provee de las sigueintes ventajas:

 Trabajar con Varias Tablas.- Las cuales se pueden manejar de manera


individual o relacionadas
 Tener diferentes origenes de los datos.- Por ejemplo desde SQL Server 7.0,
SQL Server 2000 y Oracle entre otros.
 Intercambio de datos entre aplicaciones.- Al tener soporte para XML, se
puede leer y escribir datos utilizando esquemas XML con mucha facilidad.
 Enlazar datos a controles.- Es mas fácil enlazar el control de los formularios
Windows al elemento correspondiente del DataSet que cargar el valor después
de la ejecución de un comando.
Vea: Como enlazar controles de lista a base de datos:
http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm

Partes principales de una DataSet

 Un DataSet incluye la colección Tables, que contiene los DataTables creados en


este.
 Un DataSet incluye la colección Relations que contiene los DataRelations
creados entre tablas.
 Los DataTables creados contienen las sigueintes colecciones:
o Columns, que contienen todos los DataColumns del DataTable
o Rows, que contienen todos los DataRows del DataTable

DataSet Tipificados

Los DataSets tipificados son aquellos que tienen como referencia un esquema XML
presente en la aplicación (archivo con extensión xsd), estos tipos de DataSets pueden ser
creados desde el IDE siguiendo los siguientes pasos:

Creado usando el IDE de Visual Studio:

1. Abrir el modo diseño del formulario donde se incluirá el DataSet, seleccionar la


ficha Datos del cuadro de herramientas, incluir un SQLConnection y configurar
el ConnectionString con la base de datos a trabajar
2.
3. Insertar un SQLDataAdapter y configurarlo seleccionando la conexión creada en
el paso 1 siguiendo el asistente.

4. Pulsar click en Siguiente


5. Seleccionar la cadena previamente configurada y pulsar click en Siguiente
6. Escribir la instrucción Select o utilizar el Generador de Consultas, luego pulsar
click en Siguiente
7. Pulsar click en Finalizar. Es necesario anotar que en este paso los Detalles deben
presentar todos un aspa de haberse generado.
8. Luego de creado es SQLDataAdapter, se puede generar el DataSet Tipificado,
pulsar botón derecho en el Adaptador y seleccionar la opción Generar conjunto
de Datos .
9. Seleccionar si se creará uno nuevo o el esquema se creará en una existente.
Fíjese en la casilla de verificación Agregar este conjunto de datos al
diseñador, debe estar activada.

En el diseñador se creara un archivo con extensión xsd, para nuestro ejemplo si lo


abrimos se muestra como sigue:

TIPS

 Si prefieren pueden borrar el los objetos creados, es decir el SQLConnection y el


SQLDataAdapter y quedarse con el DataSet Tipificado.
 Crear mediante código la conexión y el Adaptador.

NUESTRO EJEMPLO

En el ejemplo que comparto con ustedes señores desarrolladores, uso la tabla Customers
de la Base de datos Northwind, con esta creo dos tablas en Master y cada una la uno a
cada uno de los Grids presentes en formulario.

En un segundo aporte relacionado con este incluiré como relacionar o manejar los
DataSet no Tipificados, ademas de como instanciarlos.

A continuación sigue código en Visual Basic .Net:

'Tipificado ---- dsCustomers.xsd


dsTDatos = New dsCustomers 'deCustomers en un DataSet Tipificado
'Crear el Adaptador
Dim daTDatos As New SqlDataAdapter("Select * from ClientesTyped", cn)
'Llenar el DataSet, creando el DataTable ClientesTyped
datDatos.Fill(dsTDatos, "ClientesTyped")

'Origen del Grid Typed


dgDatosT.DataSource = dsTDatos.Tables("ClientesTyped")
With dgDatosT 'Opciones del Grid.
.CaptionText = "DataSet Tipificado"
.CaptionForeColor = Color.Orange
.ReadOnly = True
End With

'No Tipificado

dsUDatos = New DataSet


Dim daUDatos As New SqlDataAdapter("Select * from ClientesUnTyped", cn)
daUDatos.Fill(dsUDatos, "ClientesUnTyped")
'Origen del Grid UnTyped
dgDatosU.DataSource = dsUDatos.Tables("ClientesUnTyped")
With dgDatosU
.CaptionText = "DataSet NO Tipificado"
.CaptionForeColor = Color.Red
.ReadOnly = True
End With

El código completo se encuentra en el archivo adjunto al final del artículo. No olviden


calificar el PanoramaBox, suerte y... A SEGUIR DESARROLLANDO.

El control TabControl
Manejo de los TabPages

Sres. Desarrolladores, este aporte pretende explicar el manejo del control TabControl,
este control puede ser utilizado cuando se tienen demasiados datos en un solo
formulario y es posible separarlos.

El control se muestra con un conjunto de TabPages o fichas dentro de las cuales se


pueden agregar todo tipo de controles, inclusive otro TabControl.

Para insertar fichas debe agregarse una opción a la colección TabPages. Especificar la
propiedad Text para el texto que mostrará la ficha.

Es un control que posee muchas propiedades y métodos pero que la mayoría de usuarios
las usamos por defecto.

EL EJEMPLO

En el aporte que comparto con ustedes intento mostrar como administrar las diferentes
fichas, teniendo en cuenta los ingresos de datos. Es muy útil, bajen el fichero zip y
ejecuten.

A continuación sigue código en Visual Basic:

Este es el procedimiento para administrar la selección de las fichas

Private Sub SeleccionPages(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles tbCuadro.SelectedIndexChanged

'Seleccionar las páginas de Premios, Concurso y Puntajes


'sin agregar concursantes.-

If vAgregado = False AndAlso tbCuadro.SelectedIndex > 0 Then


tbCuadro.SelectedIndex = 0
MessageBox.Show("Falta ingresar Concursantes", "Atención",
MessageBoxButtons.OK, MessageBoxIcon.Stop)
ElseIf vAgregado = True And cConcursantes = 1 And tbCuadro.SelectedIndex = 1
Then
tbCuadro.SelectedIndex = 0
MessageBox.Show("Mínimo 02 Concursantes", "Atención",
MessageBoxButtons.OK, MessageBoxIcon.Stop)
Exit Sub
ElseIf tbCuadro.SelectedIndex = 2 And vConcurso = False Then
tbCuadro.SelectedIndex = 1
MessageBox.Show("Falta Seleccionar Premios", "Atención",
MessageBoxButtons.OK, MessageBoxIcon.Stop)
Exit Sub
ElseIf tbCuadro.SelectedIndex = 1 Then
If cboAgregados.Items.Count = 0 Then
For i = 0 To aConcursantes.GetLength(1) - 1
cboAgregados.Items.Add(aConcursantes(0, i))
Next
End If
End If
End Sub

El código completo está en el archivo adjunto, al final del artículo, no olvides


calificarme, me motiva a seguir publicando y compartiendo mis conocimientos. Suierte
y A SEGUIR DESARROLLANDO

DataSets Tipificados y No Tipificados II

Manejo de registros

Sres. Desarrolladores, continuando con el artículo referente a DataSet, en el anterior


explicaba los componentes del DataSet, Ventajas y otros temas, el artículo está en el
enlace:
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm

En este artículo pretendo mostrar como se acceden a los datos cuando se trabajan con
DataSets Tipificados y como se acceden cuando se trabajan con DataSets NO
Tipificados.

AL GRANO

En el ejemplo que comparto con ustedes he colocado información en cajas de texto y


me conecto a la Tabla Customers (Clientes) de la base de datos Northwind. El esquema
presente en el DataSet tipificado dsCustomers.xsd, se llama ClientesTyped, que tiene
la misma estructura de la tabla Customers de Northwind.

DataSet Tipificado

 Al contenido de este tipo de DataSet se puede acceder directamente utilizando el


nombre del Esquema o elemento presente. Para definirlo debemos tener presente
en el proyecto un archivo xsd con el elemento que servirá como base para
nuestro DataTable. La definición de Typed DataSet podría ser como sigue:

Dim dsTDatos as New dsCustomers

Donde: dsTDatos es la instancia del DataSet Tipificado y dsCustomers es el


archivo xsd presente en el proyecto.

 Para definir un DataRow utilizando el DataSet tipificado se utiliza la línea:

Dim drRegistro1 As dsCustomers.ClientesTypedRow

Donde dsCustomers es el DataSet tipificado incluído en el proyecto y


ClientesTypedRow en el DataRow correspondiente.

 Para acceder a los elementos del DataRow se utiliza lo siguiente:


drRegistro1.CompanyName = txtCompanyName.Text

Donde txtCompanyName.Text es el contenido de una caja de texto. Note que los


elementos del DataRow están presentes como si se tratara de las propiedades del objeto.

 Para recorrer el DataTable podemos utilizar la siguiente estructura::

For i = 0 To dsTDatos.ClientesTyped.Count - 1

...código necesaio

Next i

Donde: dsTdatos es el nombre del DataSet y ClientesTyped es el DataTable.

 Para acceder al registro i podemos utilizar el subindice de los DataRows, como


por ejemplo:

dsTDatos.ClientesTyped(i).ContactName.ToString

Donde ContactName es uno de los campos para mostrar en el control ListBox.

DataSet NO TIPIFICADO

 El trabajo con DataSets no Tipificados es algo diferente, un Untyped DataSet


no tiene un esquema definido en un archivo presente en el proyecto (archivo
xsd), este se basa en la clase base DataSet, para definirlo utilizamos:

Dim dsUDatos as New DataSet

 Usando el SQLDataAdapter llenamos el DataTable con el método Fill, es


conveniente asignar un nombre al DataTable que se crea, luego resulta mas
sencillo trabajar con las tablas del DataSet. La siguiente línea crea un DataTable
ClientesUnTyped:

daClientes.Fill( dsUDatos, "ClientesUnTyped")

Donde: daClientes es el SQLDataAdapter , dsUDatos es el DataSet que debe estar


previamente definido y ClientesUnTyped es el nombre del DataTable a crear.

 Para definir un DataRow

Dim drRegistro as DataRow


drRegistro = dsUDatos.Tables("ClientesUnTyped").NewRow

 Para acceder a los elementos del DataRow se utiliza lo siguiente:

drRegistro1("CompanyName") = txtCompanyName.Text
Donde txtCompanyName.Text es el contenido de una caja de texto. Note que los
elementos del DataRow se acceden utilizando (" ")

 Para recorrer el DataTable podemos utilizar la siguiente estructura::

For i = 0 To dsUDatos.Tables("ClientesUnTyped").Rows.Count - 1

...código necesaio

Next i

Donde: dsUdatos es el nombre del DataSet y ClientesUnTyped es el DataTable.

 Para acceder al registro i podemos utilizar el subindice de los DataRows, como


por ejemplo:

dsTDatos.Tables("ClientesUnTyped").Rows(i) ("ContactName").ToString

Donde ContactName es uno de los campos para mostrar en el control ListBox.

Notas IMPORTANTES:

 El acceso a datos de DataSet tipificados es mas fácil y rápido en


tiempo de ejecución que el acceso a DataSets sin tipo.
 La sintaxis para el conjunto de datos con tipo proporciona
comprobación de tipos en tiempo de compilación, lo que lo hace
mas útil para evitar cometer errores.
 Use DataSet sin tipo cuando los datos no tienen siempre el mismo
esquema. o estructura.

A continuación sigue código en Visual Basic:

Private Sub frmMoves_Load(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

'Definir la cadena de conexión


Dim cn As New SqlConnection("workstation id=HOME;packet size=4096;user
id=fernnado;integrated security=SSPI;data source=(local);persist security
info=False;initial catalog=Northwind")

'Abrir la conexión
cn.Open()
'Crear el SQLCommand
Dim coClientes As New SqlCommand
coClientes.Connection = cn
coClientes.CommandType = CommandType.Text
'Se usarán dos tablas adicionales con los mismos datos
'de Customers: ClientesTyped y ClientesUnTyped
'Para ClientesTyped...comprobar si existe y borrarla

coClientes.CommandText = _
"IF EXISTS (SELECT * FROM sysobjects WHERE id =
object_id(N'[ClientesTyped]') and OBJECTPROPERTY(id, N'IsUserTable') = 1) DROP
TABLE [ClientesTyped] "

coClientes.ExecuteNonQuery() 'Ejecuta el comando


'Para ClientesUnTyped...comprobar si existe y borrarla
coClientes.CommandText = _
"IF EXISTS (SELECT * FROM sysobjects WHERE id =
object_id(N'[ClientesUnTyped]') and OBJECTPROPERTY(id, N'IsUserTable') = 1)
DROP TABLE [ClientesUnTyped] "

coClientes.ExecuteNonQuery() 'Ejecuta el comando


'Luego crear las dos tablas basadas en Customers de Northwind
'Crear ClientesTyped
coClientes.CommandText = _
"CREATE TABLE ClientesTyped (" & _
"CustomerID nchar (5) PRIMARY KEY ," & _
"CompanyName nvarchar (40) NOT NULL," & _
"ContactName nvarchar (30) NULL," & _
"ContactTitle nvarchar (30) NULL," & _
"Address nvarchar (60) NULL," & _
"City nvarchar (15) NULL," & _
"Region nvarchar (15) NULL ," & _
"PostalCode nvarchar (10) NULL," & _
"Country nvarchar (15) NULL," & _
"Phone nvarchar (24) NULL," & _
"Fax nvarchar (24) NULL )"

coClientes.ExecuteNonQuery() 'Ejecuta Crear Tabla ClientesTyped

'Crear ClientesUnTyped
coClientes.CommandText = _
"CREATE TABLE ClientesUnTyped (" & _
"CustomerID nchar (5) PRIMARY KEY ," & _
"CompanyName nvarchar (40) NOT NULL," & _
"ContactName nvarchar (30) NULL," & _
"ContactTitle nvarchar (30) NULL," & _
"Address nvarchar (60) NULL," & _
"City nvarchar (15) NULL," & _
"Region nvarchar (15) NULL ," & _
"PostalCode nvarchar (10) NULL," & _
"Country nvarchar (15) NULL," & _
"Phone nvarchar (24) NULL," & _
"Fax nvarchar (24) NULL )"
coClientes.ExecuteNonQuery() 'Ejecuta Crear Tabla ClientesUnTyped

'Insertar los registros a las Tablas Creadas

'TABLA ClientesTyped
coClientes.CommandText = _
"INSERT INTO ClientesTyped " & _
"(CustomerID,CompanyName,ContactName,ContactTitle," & _
"Address,City,Region,PostalCode,Country,Phone,Fax )" & _
"(Select CustomerID,CompanyName,ContactName,ContactTitle," & _
"Address,City,Region,PostalCode,Country," & _
"Phone,Fax from Customers)"

coClientes.ExecuteNonQuery()

'TABLA ClientesUntyped

coClientes.CommandText = _
"INSERT INTO ClientesUnTyped " & _
"(CustomerID , CompanyName, ContactName, ContactTitle," & _
"Address ,City,Region,PostalCode,Country,Phone ,Fax )" & _
"(Select CustomerID , CompanyName, ContactName, ContactTitle,"
&_
"Address , City, Region, PostalCode, Country," & _
"Phone , Fax from Customers)"
coClientes.ExecuteNonQuery()

'Hasta acá necesitamos el SQLCommand coClientes


coClientes.Dispose()

'Tipificado ---- dsCustomers.xsd

dsTDatos = New dsCustomers 'dsCustomers en un DataSet Tipificado

'Crear el Adaptador

Dim daTDatos As New SqlDataAdapter("Select * from ClientesTyped", cn)

'Llenar el DataSet, creando el DataTable ClientesTyped

daTDatos.Fill(dsTDatos, "ClientesTyped")

'No Tipificado

dsUDatos = New DataSet

Dim daUDatos As New SqlDataAdapter("Select * from ClientesUnTyped", cn)


daUDatos.Fill(dsUDatos, "ClientesUnTyped")

'CERRAMOS LA CONEXION

cn.Close()

'Los datos siguientes son solo para ejemplo


'Llenados con mis datos

txtCustomerId.Text = "FLS23"
txtcompanyNema.Text = "Net Desarrollo SAC"
txtContactName.Text = "Ing. Fernando Luque"
txtContactTitle.Text = "Gerente General"
txtAddress.Text = "Av. Brasil 3546 Magdalena"
txtCity.Text = "Lima"
txtRegion.Text = "Oeste"
txtCountry.Text = "Perú"
txtPostalCode.Text = "51"
txtPhone.Text = "045968879"
txtFax.Text = "054-567466"

End Sub

El código completo se encuentra en el archivo adjunto al final del artículo, recuerda dar
tu opinión para PanoramaBox, suerte a todos y A SEGUIR DESARROLLANDO.

Typed DataSet - Ejemplo I

Llenar un Control DataGrid y actualizarlo

Sres Desarrolladores, esta vez comparto con ustedes un ejemplo sencillo de como
trabajar con DataSets Tipificados, la parte teórica de como incluir desde el IDE y crear
un DataSet Tipificado la encuentran en:
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm

Otro artículo con el tema es:


http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm

En este artículo muestro unicamente como llenar un control DataGrid y según los datos
agregados, modificados o eliminados, actualizarlo directamente en la Base de datos.
El formulario se presenta como sigue:
El ejemplo tiene incluidos desde el IDE los siguientes objetos:

 SQLConnection -- Configurado a la Base de datos Pubs


 SQLDataAdapter -- Utilizando la tabla Authors
 DataSet -- Creado a partir del SQLDataAdapter anterior.

El esquema creado tiene la misma estructura de la Tabla Authors, como se ve en la


figura siguiente:

Los objetos insertados desde el IDE de Visual Studio son:


A continuación sigue código en Visual Basic:

Imports System.Data.SqlClient
Imports System.Data

Public Class frmAutores


Inherits System.Windows.Forms.Form

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


*****ESTE CODIGO LO HE ELIMINADO....
#End Region

Private Sub Cargar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

daAutores.Fill(dsAutores)

DataGrid1.DataSource = dsAutores.Tables(0)

End Sub

Private Sub Actualizar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles cmdActualizar.Click

daAutores.Update(dsAutores)

End Sub

End Class

Como se darán cuenta, no hay que escribir casi nada de código. Solo llenar
el DataTable con el SQLDataAdapter y especificar la propiedad DataSource del control
DataGrid, para actualizar se utiliza el Adaptador con el método Update.

Bajense el código completo al final del artículo, suerte a todos y A SEGUIR


DESARROLLANDO
Examinar Tabla con Claves Foráneas

Tabla Productos (Products), Proveedores (Suppliers) y Categorias (Categories) -


Base de datos Northwind

Sres. Desarrolladores, este aporte es util para saber como mostrar la información de una
Tabla cuando esta tiene, en alguno de sus campos datos de otras tablas (Claves Foraneas
- Foreing Keys).

Sabemos que al desarrollar una aplicación todas las tablas se encuentran relacionadas,
aquellos atributos que son claves foráneas deben tener en cuenta los datos de otra tabla
(vaya si digo lo mismo), para el aporte que comparto con ustedes, los datos del
Proveedor y la Categoría en la tabla Productos son claves foráneas.

EL EJEMPLO

Para el ejemplo presento un formulario similar al siguiente:

Los datos del Proveedor y la Categoría se muestran en controles ComboBox. Para la


lista completa de los Productos se ha utilizado un ListView. En otro aporte enviaré
como se trabajan con los datos.

A continuación sigue código en Visual Basic:


Private Sub CargarForm(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

'Conexión

Dim cn As New SqlConnection("workstation id=HOME;packet size=4096;user


id=fernando;integrated security=SSPI;data source=(local);persist security
info=False;initial catalog=Northwind")

'Adaptadores
Dim daProductos As New SqlDataAdapter("Select * from Products", cn)
Dim daProveedores As New SqlDataAdapter("Select SupplierId,CompanyName
from Suppliers order by SupplierId", cn)
Dim daCategorias As New SqlDataAdapter("Select * from Categories", cn)

'Instancia del DataSet


dsDatos = New DataSet

'Llenar el DataSet
daProductos.Fill(dsDatos, "Productos")
daProveedores.Fill(dsDatos, "Proveedores")
daCategorias.Fill(dsDatos, "Categorias")

'Llenar ListView
For i = 0 To dsDatos.Tables("Productos").Rows.Count - 1
lvProductos.Items.Add(dsDatos.Tables("Productos").Rows(i)("ProductID"))
lvProductos.Items(i).SubItems.Add(dsDatos.Tables("Productos").Rows(i)("Prod
uctName"))
lvProductos.Items(i).SubItems.Add(dsDatos.Tables("Productos").Rows(i)("Unit
sInStock"))
lvProductos.Items(i).SubItems.Add(dsDatos.Tables("Productos").Rows(i)("Unit
Price"))
lvProductos.Items(i).SubItems.Add(dsDatos.Tables("Productos").Rows(i)("Unit
sOnOrder"))
Next

'Origenes de los combos


cboProveedor.DataSource = dsDatos.Tables("Proveedores")
cboProveedor.DisplayMember =
dsDatos.Tables("Proveedores").Columns("CompanyName").ToString
cboProveedor.ValueMember =
dsDatos.Tables("Proveedores").Columns("SupplierID").ToString
ProveedorActivar()

cboCategorias.DataSource = dsDatos.Tables("Categorias")
cboCategorias.DisplayMember =
dsDatos.Tables("Categorias").Columns("CategoryName").ToString
cboCategorias.ValueMember =
dsDatos.Tables("Categorias").Columns("CategoryID").ToString
CategoriaActivar()
'Llenar las Cajas de texto y el CheckBox
LlenarRegistro()

End Sub

Para llenar el Registro con los campos de la misma tabla Products

Private Sub LlenarRegistro()

txtProductID.Text = dsDatos.Tables("Productos").Rows(vposicion)("ProductID")

txtProductName.Text =
dsDatos.Tables("Productos").Rows(vposicion)("ProductName")

txtUnitsInStock.Text =
dsDatos.Tables("Productos").Rows(vposicion)("UnitsInStock")

txtUnitPrice.Text = dsDatos.Tables("Productos").Rows(vposicion)("UnitPrice")

txtReorderLevel.Text =
dsDatos.Tables("Productos").Rows(vposicion)("ReorderLevel")

txtUnitsOnOrder.Text =
dsDatos.Tables("Productos").Rows(vposicion)("UnitsOnOrder")

txtQuantityPerUnit.Text =
dsDatos.Tables("Productos").Rows(vposicion)("QuantityPerUnit")

chkDiscontinued.Checked =
CType(dsDatos.Tables("Productos").Rows(vposicion)("Discontinued"), Boolean)

End Sub

En el ejemplo se ha trabajado con un DataSet no Tipificado, para más información de


Tipos de DataSets pueden visitar:

http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm

Para el control ListView tienen:

http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm
El código completo del aporte se encuentra al final del artículo, solo recuerda que tienes
que actualizar la cadena de conexión y listo. Cualquier consulta a mi correo que aparece
al inicio del artículo. Muchas suerte a todos y...A SEGUIR DESARROLLANDO..

Typed DataSets - Ejercicio II

Examinar una tabla - Selección de Registros

Sres. Desarrolladores, siguiendo con los artículos referentes al manejo de DataSets


Tipificados comparto en esta ocasión con ustedes otro ejemplo. Los artículos anteriores
se encuentran en:

Ejemplo de Typed DataSets


http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetI.htm

Teoría de Typed y UnTyped DataSets


http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm

Sobre el control Tabcontrol


http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_TabControl.htm

El Ejemplo

En esta oportunidad el ejemplo muestra un form con el siguiente diseño:


Al seleccionar un registro en la ficha Registro Seleccionado se muestran sus datos de la
siguiente forma:
En el proyecto se ha incluído un DataSet tipificado con el siguiente elemento:

A continuación sigue código en Visual Basic:

Private Sub Cargar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

daAutores.Fill(dsDatos)

Pos = 0

CargarDatos()

dgAutores.DataSource = dsDatos.Tables(0)

End Sub

Private Sub DataGrid1_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles dgAutores.Click

Me.Pos = dgAutores.CurrentRowIndex

CargarDatos()

End Sub

Private Sub CargarDatos()

Dim fila As DataRow

fila = dsDatos.Tables(0).Rows(Pos)

Me.txtIdAutor.Text = fila(0)
Me.txtApellidos.Text = fila(1)

Me.txtNombres.Text = fila(2)

Me.txtFono.Text = fila(3)

Me.txtDire.Text = fila(4)

Me.txtCiudad.Text = fila(5)

Me.txtEstado.Text = fila(6)

Me.txtPostal.Text = fila(7)

Me.txtContacto.Text = IIf(fila(8), "Si", "No")

Me.lblRegistro.Text = "Registro " & Me.Pos + 1 & " de " &


dsDatos.Tables(0).Rows.Count

End Sub

El código completo está en el archivo adjunto al final del artículo. La Base de datos es
Pubs y la tabla con la que se trabaja en Authors. Actualiza tu cadena de conexión.

Suerte a todos y A SEGUIR DESARROLLANDO

Borrar el contenido de los controles

Todos los controles en un procedimiento

Sres. Desarrolladores, este aporte pretende ahorrar algo de tiempo en las tareas de la
eliminación del contenido de los controles en la tarea de agregar registros.

Muchos de nuestras aplicaciones y de nuestras tablas especificamente contienen muchos


datos, cuando se agrega un nuevo registro es necesario borrar el contenido de cajas de
texto, combobox, desactivar casillas de verificación, etc, en esta tarea muchos siguen
utilizando una línea de código para cada control mas o menos de la siguiente forma:

txtIdEmpleado.Clear()
txtNombre.Clear()
txtDireccion.Clear()
txtFono.Clear()

De esta forma lógicamente se aumenta considerablemente la cantidad de líneas de


código cuando nuestra tabla tiene bastantes campos.

Nuestro Formulario:
Este ejemplo muestra un par de botones de comando...uno para limpiar el contenido de
las cajas de texto y otro para los combobox, ustedes señores desarrolladores usen este
ejemplo para implementar y optimizar sus procedimiento.

A continuación sigue código en Visual Basic:

Para el botón Limpiar Cajas se ha implementado lo siguiente:

Para el botón Limpiar Combos se ha implementado el siguiente código

En ambos procedimientos se incluyen dos parámetros:

Me.GetContainerControl -- Método de la Clase Form que obtiene los controles


contenidos en este.

Variable para el Tipo de control -- "CT" para cajas de texto y "CO" para ComboBox

El procedimiento LimpiarControles es como sigue:


Espero que ayude a ustedes a reducir la cantidad de código de sus aplicaciones y por
consiguiente aumente su performance.

Suerte a todos y A SEGUIR DESARROLLANDO.

El código completo de este pequeño aporte está en el final del artículo, no olviden
calificar en PanoramaBox, me alienta a seguir compartiendo con ustedes mis
conocimientos.

El control ListView usando Base de Datos

Llenar el control con los registros de tablas

Sres. Desarrolladores, continuando con el control ListView, comparto con ustedes este
ejemplo de como llenar el control con los datos de un DataTable.

Personalmente creo que el trabajo con este es mas sencillo que el de un Grid, la cantidad
de código (si lo hacen por código obvio) es mayor en un Grid para formatearla que
usando el control ListView. Siempre habrán seguidores de unos y otros controles, lo
importante es saber como utilizarlos y en ese sentido esta mi aporte.

El Ejemplo

El formulario para el ejemplo se muestra de la siguiente manera:

TabPage para Todos los productos


TabPage para Productos por Categoría
TabPage para Productos por Proveedor
A continuación sigue código en Visual Basic:

En la zona de Declaraciones:

El procedimiento Load del Formulario (Clase):


El Procedimiento para Llenar todos los registros del DataTable

El código completo del ejercicio está en el archivo adjunto al final del artículo. No
olviden votar en PanoramaBox, me alienta a seguir compartiendo con ustedes mis
conocimientos.

Typed DataSet - Ejercicio III

Llenar un grid con la selección de un ComboBox

Sres. Desarrolladores, les envio otro ejemplo sencillo pero creo sumamente util de como
manejar DataSet Tipificados.Los artículos anteriores se encuentran en:
Ejemplos de Typed DataSets
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetI.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetII.htm

Teoría de Typed y UnTyped DataSets


http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm

De como formatear los Grids


http://www.elguille.info/colabora/NET2005/FernandoLuque_FormateandoDataGrid.ht
m

De controle de lista enlazados a Base de datos


http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm

El ejemplo

El formulario es sencillo, se presenta como la sigueinte figura:

Se han agregado desde el IDE los siguientes objetos:

Donde:
 cnRegion -- es un objeto SQLConnection que conecta a Northwind
 daRegion -- un SQLDataAdapter con la tabla Region
 daTerritorios -- un SQLDataAdapter con la tabla Territories
 dsRegiones -- el DATASET TIPIFICADO

El esquema del Typed DataSet se visualiza en la figura siguiente:

A continuación sigue código en Visual Basic:

Para cargar el Formulario:

Al seleccionar una opción del ComboBox Regiones:


Existe otra forma de trabajo con el mismo DataSet, simplemente usando relaciones
entre los DataTables, está forma resulta mas sencilla, este ejemplo se desarrollo en el
curso de la Tercera Estrella.

Espero que les sirva, no olviden votar en PanoramaBox, eso me alienta a


seguir compartiendo con ustedes mis conocimientos. El código completo se encuentra
en el empaquetado adjunto al final del artículo, bájalo, es sencillo.

Suerte a todos y A SEGUIR DESARROLLANDO.

El control TreeView

Llenar un árbol con Categorías - Productos

Sres. Desarrolladores, esta primera entrega del control TreeView permite enseñar como
construir un TreeView con los datos de dos tablas.

Un poco de Teoría

El control TreeView muestra los datos de manera jerárquica de manera similar a como
lo muestra el panel izquierdo en el Explorador de Windows. Estos elementos se llaman
Nodos y estos pueden contener a su vez otros nodos llamados nodos secundarios.

Algunas propiedades importantes:


Propiedad Descripción
Cuando se establece a True los nodos se
CheckBoxes
muestran con casillas de verificación
Similar al control ListView presenta una
FullRowSelect
barra en la opción o nodo seleccionada
Cuando se establece en True muestra
HotTracking comentarios en cada nodo al ubicar el mouse
en este.
Relaciona el control TreeView con un control
ImageList ImageList, utilice ImageIndex para establecer
el ícono de cada nodo.
Indent Sangría de los nodos secundarios en pixels
Permite editar la etiqueta de los nodos cuando
LabelEdit
se encuentra en True
Contiene la lista de todos los nodos del nivel
Nodes
superior en la vista de árbol.
ShowLines Estas opciones permiten mostrar líneas, el
ShowPlustMinus indicador que contiene nodos secundarios (+
ShowRootLines -) y las líneas del nodo Raíz.

EL EJEMPLO

El formulario en modo ejecución con un nodo expandido se presenta de la siguiente


forma.
A continuación sigue código en Visual Basic:

En la zona de declaraciones.

Al cargar el formulario.

Espero sea útil para sus aplicaciones, en las siguientes entregas incluiré mas
funcionalidad.
No olviden votar en PanoramaBox, eso me alienta a seguir compartiendo con ustedes
mis conocimientos. El código completo se encuentra en el empaquetado adjunto al final
del artículo, bájalo, es sencillo.

Suerte a todos y A SEGUIR DESARROLLANDO.

GDI+ Gráficos en Visual Basic .Net - I

Textos artísticos

Sres. Desarrolladores, esta es la primera entrega de una colección de artículos que les
enseñará como crear textos artísticos usando GDI+ así como de animaciones sencillas.

UN POCO DE TEORIA

GDI+ es un subsistema de sistema operativo Microsoft Windows XP que se encarga de


mostrar información en pantallas y tambien en impresoras. Es la sucesora de GDI que
era la Interface de Dispositivo Gráfico incluída en versiones anteriores de Windows.

GDI+ es una interfaz de Programación de Aplicaciones (API) que se expone a través de


un conjunto de clases implementadas como código administrado.

Partes de GDI+

Los servicios de GDI+ se engloban en tres amplias categorías:

 Gráficos vectoriales 2D
 Imágenes
 Tipografía

Gráficos vectoriales 2D

Los gráficos vectoriales están relacionados con el dibujo de tipos primitivos (como
líneas, curvas y figuras) que se especifican mediante conjuntos de puntos en un sistema
de coordenadas. Por ejemplo, una línea recta puede especificarse mediante sus dos
extremos, y un rectángulo puede especificarse mediante un punto que indique la
ubicación del borde superior izquierdo y un par de números que indiquen el ancho y el
alto. Un trazado simple puede especificarse mediante una matriz de puntos que se van a
conectar mediante líneas rectas. Una curva spline de Bézier es una curva sofisticada,
especificada por cuatro puntos de control.

GDI+ proporciona clases (y estructuras) que almacenan información acerca de los


propios tipos primitivos, las clases que almacenan información sobre la forma en que
deben dibujarse los tipos primitivos y las clases que realmente realizan el dibujo. Por
ejemplo, la estructura Rectangle almacena la ubicación y el tamaño de un rectángulo; la
clase Pen almacena información sobre el color de línea, ancho de línea y estilo de línea;
y la clase Graphics dispone de métodos para dibujar líneas, rectángulos, trazados y
otras figuras. También existen varias clases Brush que almacenan información sobre la
forma en que las figuras cerradas y los trazados van a rellenarse con colores o modelos.
Se puede registrar una imagen vectorial (una secuencia de comandos gráficos) en un
metarchivo. GDI+ proporciona la clase Metafile para registrar, mostrar y guardar
metarchivos. Las clases MetafileHeader y MetaHeader le permiten inspeccionar los
datos almacenados en un encabezado de metarchivo.

Imágenes

Hay ciertos tipos de imágenes que no se pueden o son muy difíciles de mostrar con las
técnicas de gráficos vectoriales. Por ejemplo, las imágenes de los botones de la barra de
herramientas y las imágenes que aparecen en forma de iconos serían difíciles de
especificar en forma de colecciones de líneas y curvas. Una fotografía digital de alta
resolución de un estadio de béisbol abarrotado sería aún más difícil de crear con las
técnicas vectoriales. Las imágenes de este tipo se almacenan como mapas de bits,
matrices de números que representan los colores de puntos individuales de la pantalla.
GDI+ proporciona la clase Bitmap para mostrar, manipular y guardar mapas de bits.

Tipografía

La tipografía se ocupa de la presentación de texto en diversidad de fuentes, tamaños y


estilos. GDI+ proporciona una gran compatibilidad para esta tarea tan compleja. Una de
las nuevas características de GDI+ es la función de alisado subpíxel, que proporciona
una apariencia más regular al texto que se muestra en una pantalla LCD.

Texto con GDI+

Se puede utilizar cualquier objeto Graphics como superficie para representar texto. La
representación de texto requiere la utilización de un objeto Brush, que indica qué
modelo rellenará el texto, y un objeto Font, que describirá el modelo que se debe
rellenar. La fuente puede ser cualquiera de las instaladas en el sistema, y el pincel puede
ser de cualquier tipo. Por lo tanto, es posible pintar texto con un color sólido, con un
modelo o incluso con una imagen.

EL EJEMPLO

Para nuestro primer ejemplo hemos creado un formulario como el que se muestra en la
siguiente figura:
Figura 01

El texto artístico se muestra en un control PictureBox, antes de dibujar líneas, formas,


objetos o manipular imágenes con GDI+ es necesario crear un objeto Graphics, que
representa la superficie de dibujo de GDI+. Para crear el objeto Graphics se puede
utilizar el método CreateGraphics del formulario o de un control, el control o
fomulario deben existir con anterioridad.

Para nuestro ejemplo la creación del objeto gráfico es como se ve en las sigueintes
líneas de código:

Una vez creado el objeto Graphics este se puede utilizar para representar líneas, formas,
texto o manipular imágenes. Nuestro ejemplo muestra como dibujar texto, los objetos
principales para esto son: Las clases Pen, Brush y Font y la estructura Color.

La clase Brush
Las clases que se derivan de esta clase permiten crear objetos utilizados para rellenar el
interior de formas gráficas.Las clases derivadas de Brush son: SolidBrush,
TextureBrush y LinearGradientBrush.

Pasos para presentar texto usando GDI+

1. Crear un objeto graphics.

Dim grafico As Graphics

2. Cree una instancia de la clase Brush que desee usar para pintar el texto.
Por ejemplo:
3. Dim mybrush As New Drawing2D.LinearGradientBrush(ClientRectangle, _
4. Color.Red, Color.Yellow, Drawing2D.LinearGradientMode.Horizontal)
5. Cree la fuente en la que desee que aparezca el texto. Por ejemplo:

Dim myFont as New Font("Times New Roman", 24)

6. Invoque al método Graphics.DrawString del objeto Graphics para


representar el texto.
 Si suministra un objeto RectangleF, el texto se ajustará a la línea dentro
del rectángulo.
 De otro modo, el texto comenzará en las coordenadas de inicio que
proporcione.
 ' Visual Basic
 g.DrawString("Net Desarrollo", myFont, myBrush, New _
 RectangleF(10, 10, 100, 200))
 g.DrawString("Ing. Fernando Luque Sánchez", myFont, myBrush, 10,
10)

En nuestro ejemplo usamos los pincel tipo HashBrush o LinearGradientBrush según el


botón de opción seleccionado (Ver fígura 01). El pincel LinearGradientBrush se puede
mostrar como la figura 02
Figura 02

A continuación sigue código en Visual Basic:


El codigo completo está en el empaquetado al final del artículo. Suerte a todos y no se
olviden dar su opinión en PanoramaBox, eso me alienta a seguir compartiendo con
ustedes mis conocimientos.

GDI+ Gráficos en Visual Basic .Net - II

Texto con Sombra

Sres. Desarrolladores, esta es la segunda entrega de una colección de artículos que les
enseñará como crear textos artísticos usando GDI+ así como de animaciones sencillas.

ALGO DE TEORIA

GDI+ es un subsistema de sistema operativo Microsoft Windows XP que se encarga de


mostrar información en pantallas y tambien en impresoras. Es la sucesora de GDI que
era la Interface de Dispositivo Gráfico incluída en versiones anteriores de Windows.
GDI+ es una interfaz de Programación de Aplicaciones (API) que se expone a través de
un conjunto de clases implementadas como código administrado.

Nota: La parte teórica completa se encuentra en la primera entrega:


http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm

Pasos para presentar texto SHADOW usando GDI+

1. Crear un objeto graphics.

Dim grafico As Graphics

2. Cree los pinceles para la fuente y la sombre


3. Dim pincelSombra As Brush = Brushes.Magenta
Dim pincelFuente As
4. Brush = Brushes.DarkBlue
5. Cree la fuente en la que desee que aparezca el texto. Por ejemplo:

Dim miLetra as New Font("Times New Roman", Me.nuSize.Value,


FontStyle.Bold, GraphicsUnit.Pixel)

6. Invoque al método Graphics.DrawString del objeto Graphics para


representar el texto.
 Debe especificarse el tamaño y la ubicación del texto.

El ejemplo

En este ejemplo muestro como crear texto artístico con Sombra (Shadow).
Figura 01

A continuación sigue código en Visual Basic:


El codigo completo está en el empaquetado al final del artículo. Suerte a todos y no se
olviden dar su opinión en PanoramaBox, eso me alienta a seguir compartiendo con
ustedes mis conocimientos.

GDI+ Gráficos en Visual Basic .Net - III

Texto en Contorno

Sres. Desarrolladores, esta es la tercera entrega de una colección de artículos que les
enseñará como crear textos artísticos usando GDI+ así como de animaciones sencillas.

Las anteriores

Los anteriores entregas están en:

http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto02.htm

Pasos para presentar texto Contorno usando GDI+

1. Crear un objeto graphics.

Dim grafico As Graphics

2. Cree los pinceles para la fuente y la sombre


3. Dim pincelSombra As Brush = Brushes.Magenta
Dim pincelFuente As Brush = Brushes.White

Note la diferencia con la entrega anterior que el color de Fuente para


4. contorno es Blanco
5. Cree la fuente en la que desee que aparezca el texto. Por ejemplo:

Dim miLetra as New Font("Times New Roman", Me.nuSize.Value,


FontStyle.Bold, GraphicsUnit.Pixel)

6. Invoque al método Graphics.DrawString del objeto Graphics para


representar el texto.
 Debe especificarse el tamaño y la ubicación del texto.

El ejemplo

En este ejemplo muestro como crear texto artístico con Contorno .


Figura 01

A continuación sigue código en Visual Basic:

Private Sub Contorno(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdContorno.Click

'Texto artístico Contorno


'Definicón del objeto grafico, pincel

Dim grafico As Graphics


'Para Shadow se definen los colores de fuente y de la sombra

Dim pincelSombra As Brush = Brushes.DarkBlue


Dim pincelFuente As Brush = Brushes.White

'Creamos la fuente
Dim miLetra As New Font("Times New Roman", Me.nuSize.Value, _
FontStyle.Bold, GraphicsUnit.Pixel)

'CREACION DEL GRAFICO


grafico = Me.pcTexto.CreateGraphics
grafico.Clear(Color.White)

'Calcular el tamaño del texto


Dim TextoSize As SizeF
TextoSize = grafico.MeasureString(Me.txtTexto.Text, miLetra)

'Los valores para la ubicación


Dim xPos, yPos As Single
xPos = (Me.pcTexto.Width - TextoSize.Width) / 2
yPos = (Me.pcTexto.Height - TextoSize.Height) / 2

'Ya están definidos los elementos:


'Grafico, Pinceles, Fuente, Tamaño y posición
'Dibujar el texto ahora...usar el método DrawString
'Primero la sombre y luego el frente.

grafico.DrawString(Me.txtTexto.Text, miLetra, pincelSombra, _


xPos + Me.nuContorno.Value, yPos + Me.nuContorno.Value)
grafico.DrawString(Me.txtTexto.Text, miLetra, pincelFuente, _
xPos, yPos)
End Sub

El codigo completo está en el empaquetado al final del artículo. Suerte a todos y no se


olviden dar su opinión en PanoramaBox, eso me alienta a seguir compartiendo con
ustedes mis conocimientos.

GDI+ Gráficos en Visual Basic .Net - IV

Texto en Block, Cursiva y Reflejo

Sres. Desarrolladores, esta es la cuarta entrega de una colección de artículos que les
enseñará como crear textos artísticos usando GDI+ así como de animaciones sencillas.

Las anteriores

Los anteriores entregas están en:

http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto02.htm

http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto03.htm

En esta entrega presento como dibujar el texto en Block, Cursiva y Reflejo

El ejemplo

En este ejemplo muestro como crear texto artístico Block .


Figura 01

En este ejemplo muestro como crear texto artístico Cursiva.


Figura 02

En este ejemplo muestro como crear texto artístico Reflejo.


Figura 03

A continuación sigue código en Visual Basic:

Este es para el texto tipo Block

Private Sub Block(ByVal sender As System.Object, ByVal e _


As System.EventArgs) Handles cmdBlock.Click

'Texto artístico Bloque


'Definicón del objeto gráfico, pincel
Dim grafico As Graphics

'Para Block se definen los colores de fuente y de la sombra


Dim pincelSombra As Brush = Brushes.DarkBlue
Dim pincelFuente As Brush = Brushes.GreenYellow

'Creamos la fuente
Dim miLetra As New Font("Times New Roman", Me.nuSize.Value, _
FontStyle.Bold, GraphicsUnit.Pixel)

'CREACION DEL GRAFICO


grafico = Me.pcTexto.CreateGraphics
grafico.Clear(Color.White)

'Calcular el tamaño del texto


Dim TextoSize As SizeF
TextoSize = grafico.MeasureString(Me.txtTexto.Text, miLetra)

'Los valores para la ubicación


Dim xPos, yPos As Single
xPos = (Me.pcTexto.Width - TextoSize.Width) / 2
yPos = (Me.pcTexto.Height - TextoSize.Height) / 2

'Ya están definidos los elementos:


'Grafico, Pinceles, Fuente, Tamaño y posición
'Dibujar el texto ahora...usar el método DrawString
'Primero la sombre y luego el frente.
'Dibujar todo el sombreado inclinado

Dim i As Integer
For i = CInt(Me.nuBlock.Value) To 0 Step -1
grafico.DrawString(Me.txtTexto.Text, miLetra, pincelSombra, _
xPos - i, yPos + i)
Next

'Dibujar la parte frontal


grafico.DrawString(Me.txtTexto.Text, miLetra, pincelFuente, xPos, yPos)

End Sub

El codigo completo está en el empaquetado al final del artículo. Suerte a todos y no se


olviden dar su opinión en PanoramaBox, eso me alienta a seguir compartiendo con
ustedes mis conocimientos.

Borrar el contenido de los controles II

Incluye controles GroupBox y TabControl

Sres. Desarrolladores, este aporte pretende ahorrar algo de tiempo en las tareas de la
eliminación del contenido de los controles en la tarea de agregar registros.

La primera entrega esta en el link:


http://www.elguille.info/colabora/NET2005/FernandoLuque_BorrarContenidos.htm

Algo de teoría del uso de controles en:


http://www.elguille.info/colabora/puntoNET/FernandoLuque_Controles.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm

El manejo de los TabPages del control TabControl


http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_TabControl.htm

Sobre el control ComboBox


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ComboBox.ht
m

Sobre el control ListBox


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ListBox.htm

Sobre el control ListView


http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewBD.htm

Ante la llegada de inquietudes de como borrar ListViews, como borrar el contenido de


las cajas de texto o de los controles contenidos en un GroupBox o como borrar el
contenido de los controles en un control TabControl, les comparto el ejemplo ampliado
con algunas sugerencias.

1. Utilice siempre procedimientos Sub o Function optimizando el código, no abuse


de estos.
2. Para este tipo de procedimientos en aplicaciones MDI puede definirlos como
públicos en un módulo y reducir considerablemente las líneas de código.
3. Si la cantidad de campos de una tabla es muy grande, en el formulario utilice
controles TabControl, recuerde que este ES UN CONTENEDOR como el
control GroupBox

Nuestro Formulario:

A continuación sigue código en Visual Basic:


Para limpiar los controles del Formulario:

Public Sub LimpiarControles(ByVal frmForm As Form, ByVal tipo As String)


Dim ctlControl As Object

For Each ctlControl In frmForm.Controls


If tipo = "CT" Then
If ctlControl.GetType Is GetType(System.Windows.Forms.TextBox) Then
ctlControl.Text = ""
End If
End If
If tipo = "CO" Then
If ctlControl.GetType Is GetType(System.Windows.Forms.ComboBox) Then
ctlControl.Text = ""
End If
End If

If tipo = "LB" Then


If ctlControl.GetType Is GetType(System.Windows.Forms.ListBox) Then
ctlControl.Items.clear()
End If
End If

If tipo = " LV" Then


If ctlControl.GetType Is GetType(System.Windows.Forms.ListView) Then
ctlControl.Items.clear()
End If
End If

Application.DoEvents()

Next ctlControl
End Sub

Para ejecutar este procedimiento tenemos los siguientes eventos implementados:

1. Para las Cajas de texto pasamos el parámetro CT

Private Sub LimpiarCajas(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLimpiaCajas.Click
Me.LimpiarControles(Me.GetContainerControl, "CT")
End Sub

2. Para las ComboBox pasamos el parámetro CO


Private Sub cmdLimpiarCombos_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdLimpiarCombos.Click
Me.LimpiarControles(Me.GetContainerControl, "CO")
End Sub

3. Para los ListBox pasamos el parámetro LB

Private Sub LimpiarListas(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLimpiarListas.Click
Me.LimpiarControles(Me.GetContainerControl, "LB")
End Sub

4. Para los ListView pasamos el parámetro LV

Private Sub LimpiarListViews(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLimpiarListViews.Click
Me.LimpiarControles(Me.GetContainerControl, " LV")
End Sub

Para limpiar los controles de un GroupBox se implementa el sigueinte


procedimiento

'Procedimiento para borrar controles en un GroupBox

Private Sub Limpiar(ByVal Grupo As GroupBox, ByVal tipo As String)


Dim miControl As Object

For Each miControl In Grupo.Controls


If tipo = "CT" Then
If miControl.GetType Is GetType(System.Windows.Forms.TextBox) Then
miControl.Clear()
End If
End If

''' implementar para otros controles en el GroupBox


Application.DoEvents()
Next
End Sub

y para ejecutarlo se implementa lo siguiente:

Private Sub LimpiarCajasGrupo(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLimpiarCajasGrupo.Click
Limpiar(Me.GroupBox1, "CT")
End Sub
Suerte a todos y A SEGUIR DESARROLLANDO.

El código completo de este pequeño aporte está en el final del artículo, no olviden
calificar en PanoramaBox, me alienta a seguir compartiendo con ustedes mis
conocimientos.

GDI+ Crear gráficos permanentes

Utilización del método OnPaint - Formas Básicas

Sres. Desarrolladores, en las entregas anteriores publiqué como crear de forma sencilla
gráficos utilizando GDI+, estas entregas están en los siguientes enlaces:

Textos Artísticos:
http://elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm

Texto con sombra:


http://elguille.info/colabora/NET2005/FernandoLuque_GDITexto02.htm

Texto en Contorno:
http://elguille.info/colabora/NET2005/FernandoLuque_GDITexto03.htm

Texto en Block, Cursiva y Reflejo:


http://elguille.info/colabora/NET2005/FernandoLuque_GDITexto04.htm

Los que siguieron y bajaron los gráficos se dieron cuenta de lo siguiente, EL GRAFICO
SE DIBUJA y AL CAMBIAR DE FORMULARIO Y CAMBIAR LA APLICACION Y
REGRESAR......¡¡¡¡ DESAPARECE !!!

Existe una forma de graficar lo que deseamos para crear una mejor presentación de
manera permanente, es decir, cambiarmos de enfoque nuestro formulario, regresamos y
permanece la imagen dibujada.

El Ejemplo
A continuación sigue código en Visual Basic:

Protected Overrides Sub OnPaint(ByVal e As PaintEventArgs)

'Definición del Objeto Gráfico


Dim grafico As Graphics
grafico = e.Graphics

'El Pincel
Dim pincel As New Pen(Color.Red, 4)

'Un Rectángulo
grafico.DrawRectangle(pincel, 10, 50, 120, 30)
'Otra Forma para el Rectángulo
Dim Rectangulo As New Rectangle(150, 20, 100, 50)
grafico.DrawRectangle(pincel, Rectangulo)

' Líneas
grafico.DrawLine(New Pen(Color.Olive, 4), 60, 100, 100, 100)
grafico.DrawLine(New Pen(Color.OrangeRed, 4), 20, 130, 100, 130)
grafico.DrawLine(New Pen(Color.Magenta, 4), 30, 200, 150, 100)

'Un Triágulo - Se define un Array de Puntos (Point)


Dim PuntosTriangulo() As Point = {New Point(150, 350), New Point(80, 280),
New Point(30, 400)}
grafico.DrawPolygon(New Pen(Color.Orange, 3), PuntosTriangulo)

'Texto Artístico
'Para Block se definen los colores de fuente y de la sombra
Dim pincelSombra As Brush = Brushes.DarkBlue
Dim pincelFuente As Brush = Brushes.GreenYellow
'Creamos la fuente
Dim miLetra As New Font("Times New Roman", 55, FontStyle.Bold,
GraphicsUnit.Pixel)

Dim TextoSize As SizeF


TextoSize = grafico.MeasureString("Net Desarrollo", miLetra)
'Los valores para la ubicación
Dim xPos, yPos As Single
xPos = 300
yPos = 30

'Ya están definidos los elementos:


'Grafico, Pinceles, Fuente, Tamaño y posición.
'Dibujar el texto ahora...usar el método DrawString
'Primero la sombre y luego el frente. Dibujar todo el sombreado inclinado

Dim i As Integer
For i = 10 To 0 Step -1
grafico.DrawString("Net Desarrollo", miLetra, pincelSombra, _
xPos - i, yPos + i)
Next

'Dibujar la parte frontal


grafico.DrawString("Net Desarrollo", miLetra, pincelFuente, _
xPos, yPos)

'Elipses
Dim RectaElipse As New Rectangle(30, 400, 300, 50)
grafico.DrawEllipse(New Pen(Color.SlateBlue, 6), RectaElipse)

End Sub

Como pueden darse cuenta, al implementar el método OnPaint del formulario los
objetos dibujados en este procedimiento permanecen en este mientras esta abierto, al
cambiar de enfoque al formulario y al redimensionar también.

El código completo esta en el empaquetado al final del artículo, no olvides votar, eso
me alienta a seguir publicando.
DataBindings en Visual Basic .Net

Maestro - Detalle

Un poco de teoría

Sres. Desarrolladores, reiniciando mis publicaciones comparto con ustedes un pequeño


ejemplo que detalla el uso de DataBindings, esta propiedad obtiene los enlaces de datos
del control. La propiedad DataBinding se utiliza para obtener acceso al
ControlBindingsCollection que representa a la colección de enlaces de datos de un
control.

Al enlazar un control a datos usando DataBindings se puede enlazar cualquier propiedad


de un control a la propiedad de un objeto...que como se hace, de la siguiente forma:

'Bindings para las cajas de texto

txtApellido.DataBindings.Add("Text", dtEmpleados, "LastName")

txtApellido.DataBindings.Add("Tag", dtEmpleados, "EmployeeID")

txtNombre.DataBindings.Add("Text", dtEmpleados, "FirstName")

En las líneas de código precedentes se han agregado DataBindings a dos cajas de texto,
al control con nombre txtApellido se ha relacionado las propiedades Text y Tag a los
objetos LastName y EmployeeID del DataTable dtEmpleados respectivamente.

Al control TextBox con nombre txtNombre se ha relacionado o enlazado con el objeto


FirsName del DataTable con nombre dtEmpleados.

La Clase BindingContext

Para manejar la navegación entre los registros podemos utilizar un BindingContext que
administra la colección de objetos BindingManagerBase para cualquier objeto que se
herede de la clase Control. El BindigManagerBase permite la sincronización de
controles con enlace al mismo origen. La Clase CurrencyManager que administra la
lista de objetos Binding se hereda de la clase BindingManagerBase y
mantiene sincronizados los controles señalando el elemento actual de la lista.

Normalmente, se utiliza el objeto BindingContext de la clase Form con el fin de


devolver objetos BindingManagerBase para los controles con enlace a datos del
formulario. Si se utiliza un control contenedor, como GroupsBox, Panel o TabControl,
para incluir controles con enlace a datos, se puede crear un objeto BindingContext sólo
para ese control contenedor y sus controles. De este modo, cada parte de un formulario
puede ser administrada por su propio objeto BindingManagerBase.

En el ejemplo para los botones de navegación entre registros he utilizado en


BindingContext de la clase Form, el objeto dtEmpleados y la propiedad Position para
visualizarlos individualmente, el código se muestra como sigue:
Private Sub Mover(ByVal sender As System.Object, _
ByVal e As System.EventArgs) _
Handles cmdPrimero.Click, cmdAnterior.Click, _
cmdSiguiente.Click, cmdUltimo.Click

If sender Is cmdPrimero Then


Me.BindingContext(dtEmpleados).Position = 0
ElseIf sender Is cmdAnterior Then
Me.BindingContext(dtEmpleados).Position -= 1
ElseIf sender Is cmdSiguiente Then
Me.BindingContext(dtEmpleados).Position += 1
ElseIf sender Is cmdUltimo Then
Me.BindingContext(dtEmpleados).Position = dtEmpleados.Rows.Count - 1
End If
dvVentas.RowFilter = "EmployeeID = " & txtApellido.Tag.ToString
End Sub

El ejemplo

El formulario tiene el siguiente aspecto:

A continuación sigue código en Visual Basic (o C# o C++.NET):


En la zona de declaraciones:

'Elementos necesarios

Dim cn As SqlConnection 'conexion


'Adaptadores

Dim daEmpleados As SqlDataAdapter


Dim daOrdenes As SqlDataAdapter
Dim daDetalle As SqlDataAdapter
Dim daVentas As SqlDataAdapter

'DataTables
Dim dtEmpleados As DataTable
Dim dtOrdenes As DataTable
Dim dtDetalle As DataTable
Dim dtVentas As DataTable

'vistas
Dim dvOrdenes As DataView
Dim dvDetalle As DataView
Dim dvVentas As DataView

'El dataset
Dim dsDatos As DataSet

Al cargar el Windows Form

Private Sub CARGAR(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

cn = New SqlConnection("user id=sa;initial catalog=Northwind;persist security


info=False")
dsDatos = New DataSet

'Adaptadores: Empleados, Órdenes y Detalle de las Órdenes

daEmpleados = New SqlDataAdapter("SELECT EmployeeID, LastName,


FirstName, HireDate FROM Employees", cn)
daEmpleados.Fill(dsDatos, "Empleados")

'Ordenes
Dim vInsOrdenes As String
vInsOrdenes = "SELECT Od.OrderID, SUM(CONVERT(money, (Od.UnitPrice *
"&_
" Od.Quantity) * (1 - Od.Discount) / 100) * 100) " & _
" AS Total, o.EmployeeID, o.OrderDate, " & _
" c.CompanyName" & vbCrLf & _
"FROM [Order Details] Od " & _
" INNER JOIN Orders o " & _
" ON Od.OrderID = o.OrderID" & vbCrLf & _
" INNER JOIN Customers c " & _
" ON o.CustomerID = c.CustomerID" & vbCrLf & _
"GROUP BY Od.OrderID, o.EmployeeID, o.OrderDate, c.CompanyName"

'Esta instruccion select tiene 5 campos: OrderID, Total orden,

'Id del empleado, Fecha y Nombre de la compañía

daOrdenes = New SqlDataAdapter(vInsOrdenes, cn)


daOrdenes.Fill(dsDatos, "Ordenes")

'EMPLEADOS y su total de Ventas

Dim vInsVentas As String


vInsVentas = "SELECT e.employeeid, sum(UnitPrice * Quantity) as " & _
" 'Total Ventas' " & _
"FROM [order details] od " & _
" INNER JOIN orders o " & _
" ON o.orderid = od.orderid " & _
" INNER JOIN employees e " & _
" ON e.employeeid = o.employeeid" & vbCrLf & _
"GROUP BY e.employeeid"

daVentas = New SqlDataAdapter(vInsVentas, cn)


daVentas.Fill(dsDatos, "Ventas")

'Detalle de las ordenes


Dim vinsDetalle As String
vinsDetalle = "SELECT od.OrderID, od.UnitPrice, od.Quantity, od.Discount, " &
_
" p.ProductName, c.CategoryName, " & _
" (od.UnitPrice * od.Quantity) As SubTotal " & _
"FROM [order details] od " & _
" INNER JOIN Products p ON od.ProductID = p.ProductID " & _
" INNER JOIN Categories c ON c.CategoryID = p.CategoryID " & _
"ORDER BY od.OrderID"

daDetalle = New SqlDataAdapter(vinsDetalle, cn)


daDetalle.Fill(dsDatos, "Detalle")

'Definicion de los DataTables

dtEmpleados = dsDatos.Tables("Empleados")
dtOrdenes = dsDatos.Tables("Ordenes")
dtDetalle = dsDatos.Tables("Detalle")
dtVentas = dsDatos.Tables("Ventas")
'Las Vistas
dvOrdenes = dtOrdenes.DefaultView
dvDetalle = dtDetalle.DefaultView
dvVentas = dtVentas.DefaultView

'Procedimiento para crear los Bindings

CrearBindings()
dvVentas.RowFilter = "EmployeeID = " & txtApellido.Tag.ToString
'Mostrar las Ordenes, el Detalle y el Registro
Mostrarordenes()
MostrarDetalle()
RegistroActual()
End Sub

El código completo se encuentra en el archivo adjunto. Bájalo y no te olvides de votar,


tus puntos me alientan a seguir compartiendo.

Suerte a todos y a seguir desarrollado.

Aplicaciones en N-Capas en Visual Basic .Net

Maestro - Detalle

Un poco de teoría

Sres. Desarrolladores, en esta ocasión comparto con ustedes un ejemplo de como


desarrollar una aplicación usando Visual Basic .Net en N-Capas.

Modelos de Acceso a datos

Los modelos de acceso a datos han evolucionado junto a los modelos de equipos, desde
los modelos centralizados hasta los modelos distribuidos. La cantidad de usuarios de los
sistemas antes no tenia en número que tiene ahora cambiando desde aplicaciones de un
usuario o aplicaciones simples (en un equipo unicamente) hasta aplicaciones en Internet,
el último modelo es el modelo de Servicios Web XML (XML Web Services).

Definición de Capa

En el modelo de acceso a datos, una capa es un nivel lógico en el cual residen


componentes o aplicaciones lógicas. Las capas pueden residir en uno a mas equipos o
servidores, el número de capas hace referencia al número de niveles y no al número de
equipos en los cuales los servicios son divididos. Las capas que generalmente se
incluyen en aplicaciones son:

1. Capa de Cliente: conocida como capa de Presentación es la que contiene las


interfaces en las que el usuario interactua con el sistema.
2. Capa de la Lógica de Negocios: el cual contiene la lógica que interactua con el
origen de datos. Esta capa intermedia contiene la parte de la aplicación que
interactua con los datos, por ejemplo: la creación de una cadena de conexión al
origen de datos.
3. Capa de acceso a Datos: la cual se relaciona directamente con el origen de
datos

Beneficios del trabajo con Capas

 Escalabilidad en las aplicaciones


 Distribución mas efectiva
 Cambios en la aplicaciones mas sencillos de manejar e implementar
 Separación de funciones
 Permite aplicaciones en diferentes sistemas operativos
 Clientes menos pesados (thin Client)

El ejemplo

El formulario tiene el siguiente aspecto:

A continuación sigue código en Visual Basic (o C# o C++.NET):

La Biblioteca de clases del Acceso a Datos: VBNCapasAccesoDatos


'Ing. Fernando Luque Sánchez
'Net Desarrollo SAC
'Asesoramiento y Desarrollo

Imports System.Data
Imports System.Data.SqlClient

Public Class VBNCapasAcceso


'Capa de Acceso a Datos
'Definición del String de Cadena de conexión

Protected Const sCN As String = _


"user id=sa;initial catalog=Northwind;persist security info=False"

'Los Adaptadores
Private daCat As SqlDataAdapter
Private daProd As SqlDataAdapter

'Declarar eventos que proveen información a la Capa de Presentación


Public Event DataSetCreado(ByVal vCreado As Boolean)

'Creamos una función para retornar el DataSet


Public Function CrearDataSet() As DataSet
Dim dsDatos As DataSet
Dim cn As New SqlConnection(sCN)
'Las instancias de los Adaptadores
daCat = New SqlDataAdapter("Select CategoryId, CategoryName, Description
from Categories", cn)
daProd = New SqlDataAdapter("Select * from Products", cn)

dsDatos = New DataSet


daCat.Fill(dsDatos, "Categorias")
daProd.Fill(dsDatos, "Productos")

'Indica que el evento de creación del DataSet fue exitoso


RaiseEvent DataSetCreado(True)
'Retorna el DataSet
Return dsDatos
End Function
End Class

En la zona de declaraciones del formulario

Dim dsDatos1 As DataSet


'Definir dos DataTables
Dim dtCat As DataTable
Dim dtProd As DataTable
'Las Vistas
Dim dvCat As DataView
Dim dvProd As DataView

'Instanciar la clase de acceso a datos


Protected WithEvents cAcceso As VBNCapasAcceso

Al cargar el Windows Form

'PROCEDIMIENTO AL CARGAR EL FORMULARIO


Private Sub Cargar(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
'Instanciar la clase
cAcceso = New VBNCapasAcceso

'Obtener el DataSet de la Clase VBNCapasAcceso


dsDatos1 = cAcceso.CrearDataSet
'Origen de los DataTable
dtCat = dsDatos1.Tables("Categorias")
dtProd = dsDatos1.Tables("Productos")

'Origen de las Vistas


dvCat = dtCat.DefaultView
dvProd = dtProd.DefaultView

'Origen de los Grid


dgCat.DataSource = dvCat
dgCat.CaptionText = "Categorias"
dgCat.Select(0)

'Llenar el Grid de Productos


LlenarGridProductos()

EstilosGrid() 'Solamente para las Categorías...por espacio y tiempo


End Sub

El código completo se encuentra en el archivo adjunto. Bájalo y no te olvides de votar,


tus puntos me alientan a seguir compartiendo.

Suerte a todos y a seguir desarrollando.

Creando un Explorador de Windows

Uso de Clases para crear Componentes

Sres. Desarrolladores, este aporte pretende ayudar a ustedes a crear una pequeña
aplicación simulando el Explorador de Windows, en este primer envío, solamente está
implementada la funcionalidad para ver los archivos y carpetas.
Este ejemplo incluye el uso de Clases para su ejecución, si bien es cierto muchos opinan
que resulta mas fácil directamente, envío primero este, donde desde código se
implementa hasta la interface.

Un poco de teoría

El NameSpace System.IO
Este NameSpace contiene todos los tipos que permiten leer y escribir en los archivos y
secuencia de datos, así como tipos que proporcionan compatibilidad básica con los
archivos y directorios.

Algunas Clases de System.IO

Clase Descripción
Expone métodos estáticos para crear, mover y
Directory
enumerar archivos en directorios y subdirectorios
Expone métodos de instancia para crear, mover y
DirectoryInfo
enumerar archivos en directorios y subdirectorios.
Proporciona métodos estáticos para crear, copiar,
eliminar, mover y abrir archivos y contribuye a la
creación de objetos FileStream.
Utilice la clase FileStream para leer, escribir, abrir y
cerrar archivos en un sistema de archivos, así como
para manipular otros identificadores del sistema
File
operativo relacionados con archivos, como
canalizaciones, entrada estándar y salida estándar
amd. Puede especificar que las operaciones de lectura
y escritura sean sincrónicas o asincrónicas.
FileStream almacena en el búfer la entrada y la
salida para obtener un mejor rendimiento.
Proporciona métodos de instancia para crear, copiar,
FileInfo eliminar, mover y abrir archivos y contribuye a la
creación de objetos FileStream.
Expone un objeto Stream alrededor de un archivo; se
admiten operaciones de lectura y escritura sincrónica
FileStream
y asincrónica. Un objeto Stream proporciona una
vista genérica de una secuencia de bytes.
Ejecuta operaciones en instancias de String que
contienen información de rutas de archivos o
Path
directorios. Estas operaciones se ejecutan de forma
adecuada para múltiples plataformas.

Las Clases de Componentes

Una clase es una unidad de código reutilizable. También lo es un componente. Para


crear un componente, se empieza con una clase. Una clase se convierte en un
componente cuando se ajusta a un estándar para la interacción con componentes. Este
estándar se proporciona a través de la interfaz IComponent. Cualquier clase que
implemente la interfaz IComponent es un componente. Tales estándares permiten que
los programadores conecten rápidamente componentes entre sí para crear programas
mayores. Common Language Specification (CLS) describe el modo en que pueden
interactuar los componentes creados para Common Language Runtime.

.NET Framework proporciona la interfaz IComponent y la clase base Component para


facilitar la creación de componentes que funcionen bien en el entorno de diseño y las
clases UserControl y Control, que facilitan la creación de componentes visuales.

Inicializar y finalizar un componente

Un componente se inicializa por medio de su constructor (Sub New en Visual Basic) y


se destruye por medio de su destructor (Sub Finalize en Visual Basic). Se llama al
constructor del componente cuando se crea una instancia de éste; después, no es posible
llamar al constructor. La llamada al destructor se realiza inmediatamente antes de
destruirlo mediante la recolección de elementos no utilizados y la reclamación de la
memoria que ocupa.

Para nuestro ejemplo hemos creado las clases de componentes cpDirectorio, cpArchivos
y cpMenu, el constructor de la clase de componente para cpDirectorios es:

Public Sub New()


'Cargar las imagenes en la Propiedad ImageList del TreeView

Me.ImageList = New ImageList


With Me.ImageList.Images
.Add(New Bitmap("..\Imagenes\35FLOPPY.BMP")) 'Disco 3½
.Add(New Bitmap("..\Imagenes\CLSDFOLD.BMP")) 'Folder
.Add(New Bitmap("..\Imagenes\OPENFOLD.BMP")) 'Folder seleccionado
End With

' Construir el arbol


ConstruirArbol()
End Sub

En esta clase especificamos una lista de imágenes y agregamos 03 imágenes para


mostrar en el TreeView. (Ver mas adelante el ejemplo). Se ejecuta el procedimiento
ConstruirArbol()

'Crea el árbol
Public Sub ConstruirArbol()
BeginUpdate()
Nodes.Clear()

' Drives como principales


Dim astrDrives As String() = Directory.GetLogicalDrives()
Dim strDrive As String
For Each strDrive In astrDrives
Dim tnDrive As New TreeNode(strDrive, 0, 0)
Nodes.Add(tnDrive)
AgregarDir(tnDrive)
' Drive C por defecto
If strDrive = "C:\" Then
Me.SelectedNode = tnDrive
End If
Next
EndUpdate()
End Sub

La finalización de un componente

Si el componente hereda de System.ComponentModel.Component, se proporciona


una implementación predeterminada de Dispose. Esta implementación puede
reemplazarse para proporcionar código de limpieza personalizado. Si genera un
componente mediante la creación de una implementación personalizada de
IComponent, es recomendable que implemente IDisposable para proporcionar al
componente un método Dispose.

El componente necesitará un método Dispose si asigna objetos del sistema, conexiones


de base de datos u otros recursos escasos que deban liberarse tan pronto como el usuario
termine con el componente.

También debe implementarse un método Dispose si el componente contiene referencias


a otros objetos que tengan métodos Dispose .

El Ejemplo

El formulario en tiempo de ejecución tiene el siguiente aspecto


A continuación sigue código en Visual Basic:

Para poder utilizar el componente debemos usar la instrucción Imports:

'Importar el componente creado


Imports VBExplorador.cpDirectorios

Constructor del Formulario:

Public Sub New()


MyBase.New()

'El Diseñador de Windows Forms requiere esta llamada.


InitializeComponent()
'Agregar cualquier inicialización después de la llamada a InitializeComponent()
' Instancia del ListView para archivos
lvArchivos = New cpArchivos
lvArchivos.Parent = Me
lvArchivos.Dock = DockStyle.Fill

' El Splitter
Dim split As New Splitter
split.Parent = Me
split.Dock = DockStyle.Left
split.BackColor = SystemColors.Control

' El TreeView y su Evento


tvCarpetas = New cpDirectorios
tvCarpetas.Parent = Me
tvCarpetas.Dock = DockStyle.Left
'Evento
AddHandler tvCarpetas.AfterSelect, AddressOf SeleccionDirectorio

' Menu Ver


Dim mnuView As New MenuItem("& Vista")
mnuView.Index = 1
Me.mnPrincipal.MenuItems.Add(mnuView)

'Array con las opciones del menú vista


Dim astrView As String() = {"Iconos Grandes", "Iconos Pequeños", "Lista",
"Detalles"}
Dim aview As View() = {View.LargeIcon, View.SmallIcon, View.List,
View.Details}
' Manejadores
Dim manejador As New EventHandler(AddressOf VistaMenu)

Dim i As Integer
For i = 0 To 3
'Clase cpMenu
Dim miv As New cpMenu
miv.Text = astrView(i)
miv.View = aview(i)
miv.RadioCheck = True
'el manejador
AddHandler miv.Click, manejador

'Por defecto Detalle


If i = 3 Then
mivChecked = miv
mivChecked.Checked = True
lvArchivos.View = mivChecked.View
End If
' Agregar
mnuView.MenuItems.Add(miv)
Next i
End Sub

Noten que en el constructor se han definido los objetos a utilizar, un TreeView, un


control Splitter y un ListView.

Acerca de estos controles pueden ver los artículos:


ListView
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewBD.htm
TreeView
http://www.elguille.info/colabora/NET2005/FernandoLuque_TreViewBDatos.htm

En una segunda publicación enviaré como crear esta pequeña aplicación sin Clases de
componentes, estén atentos

El código completo se encuentra en el archivo adjunto al final del artículo, antes de


bajarlo espero que votes por este aporte para alentarme a seguir publicando.

Suerte a todos y A SEGUIR DESARROLLANDO

Creando un Explorador de Windows

Sres. Desarrolladores, este aporte pretende ayudar a ustedes a crear una pequeña
aplicación simulando el Explorador de Windows, en este segundo envío, solamente está
implementada la funcionalidad para ver los archivos y carpetas.

Este ejemplo incluye el uso de controles para su ejecución directamente desde el IDE,
en el ejemplo anterior se creó la aplicación usando Clases de componentes. El link es el
siguiente:

FernandoLuque_Explorador01.htm

Un poco de teoría

El NameSpace System.IO (lo mismo del artículo anterior)


Este NameSpace contiene todos los tipos que permiten leer y escribir en los archivos y
secuencia de datos, así como tipos que proporcionan compatibilidad básica con los
archivos y directorios.

Algunas Clases de System.IO

Clase Descripción
Expone métodos estáticos para crear, mover y
Directory
enumerar archivos en directorios y subdirectorios
Expone métodos de instancia para crear, mover y
DirectoryInfo
enumerar archivos en directorios y subdirectorios.
Proporciona métodos estáticos para crear, copiar,
eliminar, mover y abrir archivos y contribuye a la
creación de objetos FileStream.
File Utilice la clase FileStream para leer, escribir, abrir y
cerrar archivos en un sistema de archivos, así como
para manipular otros identificadores del sistema
operativo relacionados con archivos, como
canalizaciones, entrada estándar y salida estándar
amd. Puede especificar que las operaciones de lectura
y escritura sean sincrónicas o asincrónicas.
FileStream almacena en el búfer la entrada y la
salida para obtener un mejor rendimiento.
Proporciona métodos de instancia para crear, copiar,
FileInfo eliminar, mover y abrir archivos y contribuye a la
creación de objetos FileStream.
Expone un objeto Stream alrededor de un archivo; se
admiten operaciones de lectura y escritura sincrónica
FileStream
y asincrónica. Un objeto Stream proporciona una
vista genérica de una secuencia de bytes.
Ejecuta operaciones en instancias de String que
contienen información de rutas de archivos o
Path
directorios. Estas operaciones se ejecutan de forma
adecuada para múltiples plataformas.

El Ejemplo

El formulario en tiempo de ejecución tiene el siguiente aspecto

A continuación sigue código en Visual Basic:


Al Cargar el Formulario

Private Sub Cargar(ByVal sender As System.Object, _

ByVal e As System.EventArgs) Handles MyBase.Load

LlenarArbol()

AgregarArchivos(tvDir.SelectedNode.Text)

End Sub

El procedimiento para llenar el TreeView

Private Sub LlenarArbol()


tvDir.BeginUpdate()
tvDir.Nodes.Clear()
' Drives como principales
Dim astrDrives As String() = Directory.GetLogicalDrives()
Dim strDrive As String
For Each strDrive In astrDrives
Dim tnDrive As New TreeNode(strDrive, 0, 0)
tvDir.Nodes.Add(tnDrive)
AgregarDir(tnDrive)
' Drive C por defecto
If strDrive = "C:\" Then
tvDir.SelectedNode = tnDrive
End If
Next
tvDir.EndUpdate()
End Sub

Para Agregar el Directorio

Private Sub AgregarDir(ByVal tn As TreeNode)


tn.Nodes.Clear()
Dim strPath As String = tn.FullPath
Dim diDirectory As New DirectoryInfo(strPath)
Dim aDir() As DirectoryInfo 'array para subcarpetas

Try
' Obtiene en un array todos los subdirectorios
aDir = diDirectory.GetDirectories()
Catch exp As Exception
Exit Sub
End Try

Dim di As DirectoryInfo
For Each di In aDir
' Crea un Nodo y pasa el nombre y la imagen
Dim tnDir As New TreeNode(di.Name, 1, 2)
'Agrega el Nodo creado
tn.Nodes.Add(tnDir)
Next
End Sub

Para Llenar los archivos en el ListView

'Llenar los archivos del directorio seleccionado


Private Sub AgregarArchivos(ByVal vDir As String)
'Por defecto esta seleccionado el directorio raíz de C:\
lvArchivos.Items.Clear()
'Obtener los directorios o subcarpetas
Dim diDirectories As New DirectoryInfo(vDir)
Dim afiFiles() As FileInfo 'Array de archivos

Try
' Array de todos los archivos
afiFiles = diDirectories.GetFiles()
Catch
Return 'Para que no salga error
End Try

Dim fi As FileInfo
For Each fi In afiFiles
'Crear ListViewItem y asginarle el nombre del archivo
Dim lvi As New ListViewItem(fi.Name)
'Imagen
Select Case Path.GetExtension(fi.Name).ToUpper()
Case ".EXE"
lvi.ImageIndex = 1
Case Else
lvi.ImageIndex = 0
End Select
' Tamaño y fecha de modificación: Length - LastWriteTime
lvi.SubItems.Add(fi.Length.ToString("N0"))
lvi.SubItems.Add(fi.LastWriteTime.ToString())

'Atributos
Dim strAttr As String = ""
If (fi.Attributes And FileAttributes.Archive) <> 0 Then strAttr += "A"
If (fi.Attributes And FileAttributes.Hidden) <> 0 Then strAttr += "H"
If (fi.Attributes And FileAttributes.ReadOnly) <> 0 Then strAttr += "R"
If (fi.Attributes And FileAttributes.System) <> 0 Then strAttr += "S"
lvi.SubItems.Add(strAttr)
'Añadir el Item
lvArchivos.Items.Add(lvi)
Next fi
End Sub

'Procedimiento para volver a llenar los archivos del ListView


Private Sub tvDir_AfterSelect(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.TreeViewEventArgs) _
Handles tvDir.AfterSelect
'Tomar el Camino completo con e
AgregarArchivos(e.Node.FullPath)
End Sub

Acerca de estos controles pueden ver los artículos:

ListView
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewBD.htm
TreeView
http://www.elguille.info/colabora/NET2005/FernandoLuque_TreViewBDatos.htm

El código completo se encuentra en el archivo adjunto al final del artículo, antes de


bajarlo espero que votes por este aporte para alentarme a seguir publicando.

Suerte a todos y A SEGUIR DESARROLLANDO

GDI+ Trabajando con Lápices

Líneas y Curvas con animación

Sres Desarrolladores, presento en esta oportunidad un ejemplo de como manejar lápices


(Pens) y sus variantes. En artículos anteriores he descrito el uso de diferentes tipos de
gráficos usando GDI+.

Los enlaces son:

1. GDI+ Gráficos en Visual Basic: Textos Artísticos


http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto01.htm

2. GDI+ Gráficos en Visual Basic: Textos con sombra


http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto02.htm

3. GDI+ Gráficos en Visual Basic: Textos en contorno


http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto03.htm

4. GDI+ Gráficos en Visual Basic: Textos Block, Cursiva y Reflejo


http://www.elguille.info/colabora/NET2005/FernandoLuque_GDITexto04.htm
5. GDI+ Crear gráficos permanentes
http://www.elguille.info/colabora/NET2005/FernandoLuque_GraficosPermanentes.
htm

Respecto a los manejadores puedes consultar el siguiente artículo:


http://www.elguille.info/colabora/NET2005/FernandoLuque_Controlando_Eventos_y_
Arreglos.htm

ALGO DE TEORIA

La forma de dibujar usando GDI+, que es una interfaz de Programación de Aplicaciones


(API) que se expone a través de un conjunto de clases implementadas como código
administrado, utiliza los diversos métodos de la clase Graphics algunos de los
cuales los podemos encontrar en la siguiente tabla:

Método Descripción

Dibuja una línea que conecta los dos


DrawLine puntos especificados por los pares de
coordenadas.

Dibuja una serie de segmentos de


DrawLines línea que conectan una matriz de
estructuras Point.

Dibuja un archivo que representa una


parte de una elipse especificada por
DrawArc
un par de coordenadas, un valor de
ancho y un valor de alto.

Dibuja una curva spline cardinal a


DrawCurve través de una matriz especificada de
estructuras Point.

Dibuja una o una serie de curvas


DrawBezier
spline de Bézier a partir de una matriz
DrawBeziers
de estructuras Point

DrawRectangle Dibuja una serie de rectángulos


DrawRectangles especificados por las estructuras
Rectangle

Dibuja un polígono definido por una


DrawPolygon
matriz de estructuras Point

NUESTRO EJEMPLO

El formulario tiene el siguiente diseño:

A continuación sigue código en Visual Basic:

AL CARGAR EL FORMULARIO
Private Sub Cargar(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load

' Estilo
cboEstilo.Items.Add(DashStyle.Solid)
cboEstilo.Items.Add(DashStyle.Dash)
cboEstilo.Items.Add(DashStyle.DashDot)
cboEstilo.Items.Add(DashStyle.DashDotDot)
cboEstilo.Items.Add(DashStyle.Dot)
cboEstilo.Items.Add(DashStyle.Custom)

' Combo para el inicio de la Flecha


cboInicioFlecha.Items.Add(LineCap.DiamondAnchor)
cboInicioFlecha.Items.Add(LineCap.ArrowAnchor)
cboInicioFlecha.Items.Add(LineCap.DiamondAnchor)
cboInicioFlecha.Items.Add(LineCap.Flat)
cboInicioFlecha.Items.Add(LineCap.Round)
cboInicioFlecha.Items.Add(LineCap.RoundAnchor)

' Combo para el Final de la Flecha


cboFinalFlecha.Items.Add(LineCap.DiamondAnchor)
cboFinalFlecha.Items.Add(LineCap.ArrowAnchor)
cboFinalFlecha.Items.Add(LineCap.DiamondAnchor)
cboFinalFlecha.Items.Add(LineCap.Flat)
cboFinalFlecha.Items.Add(LineCap.Round)
cboFinalFlecha.Items.Add(LineCap.RoundAnchor)

' El Relleno
cboRelleno.Items.Add(DashCap.Flat)
cboRelleno.Items.Add(DashCap.Round)
cboRelleno.Items.Add(DashCap.Triangle)

' Unión de Líneas


cboUnion.Items.Add(LineJoin.Bevel)
cboUnion.Items.Add(LineJoin.Miter)
cboUnion.Items.Add(LineJoin.MiterClipped)
cboUnion.Items.Add(LineJoin.Round)

' Alineación
cboAlinear.Items.Add(PenAlignment.Center)
cboAlinear.Items.Add(PenAlignment.Inset)
cboAlinear.Items.Add(PenAlignment.Left)
cboAlinear.Items.Add(PenAlignment.Outset)
cboAlinear.Items.Add(PenAlignment.Right)
End Sub

LOS MANEJADORES

'Manejadores para todos los controles


'cboForma.SelectedIndexChanged, udAncho.ValueChanged,
'txtColor.TextChanged, cboAlinear.SelectedIndexChanged,
'cboInicioFlecha.SelectedIndexChanged, cboFinalFlecha.SelectedIndexChanged,
'cboRelleno.SelectedIndexChanged, cboEstilo.SelectedIndexChanged,
'udLimite.ValueChanged, cboTransforma.SelectedIndexChanged,
'cboPincel.SelectedIndexChanged, cboUnion.SelectedIndexChanged

AddHandler cboForma.SelectedIndexChanged, AddressOf Dibujar


AddHandler udAncho.ValueChanged, AddressOf Dibujar
AddHandler txtColor.TextChanged, AddressOf Dibujar
AddHandler cboAlinear.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboInicioFlecha.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboFinalFlecha.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboRelleno.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboEstilo.SelectedIndexChanged, AddressOf Dibujar
AddHandler udLimite.ValueChanged, AddressOf Dibujar
AddHandler cboTransforma.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboPincel.SelectedIndexChanged, AddressOf Dibujar
AddHandler cboUnion.SelectedIndexChanged, AddressOf Dibujar

El PROCEDIMIENTO QUE DIBUJA

'Definir el procedimiento Dibujar para cuando el Formulario se Activa


'Los Manejadores se insertaron en el Constructor usando AddHandler

Private Sub Dibujar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Activated

' Elimina el gráfico


pcDibujo.CreateGraphics().Clear(pcDibujo.BackColor)
pcDibujo.Refresh()
' Elimina Transformación
vLapiz.ResetTransform()
' Relleno personalizado
vLapiz.DashPattern = New Single() {0.5, 0.25, 0.75, 1.5}

'PARA EL COLOR O RELLENO DEL LAPIZ


If optColor.Checked Then ' Seleccionada la opción de Color
vLapiz.Color = vLapizColor
Else 'Lápiz con Brush

'TIPO DE PINCEL
Select Case cboPincel.Text
Case "Solid"
'Pincel y lápiz del mismo color
vPincel = New SolidBrush(vLapizColor)
Case "Hatch"
'TIPO DE BRUSH
vPincel = New HatchBrush(HatchStyle.DarkVertical, vLapizColor)
Case "Texture"
' TEXTURA - UNA IMAGEN
vPincel = New TextureBrush( _
New Bitmap("..\Textura.jpg"), WrapMode.Tile)
Case "Gradient"
'DEGRADE
vPincel = New LinearGradientBrush( _
New Point(0, 0), _
New Point(pcDibujo.Width, pcDibujo.Height), _
Color.Chocolate, Color.DarkBlue)
End Select
vLapiz.Brush = vPincel
End If

'Valores para los elementos del lápiz


vLapiz.Width = udAncho.Value 'Ancho
vLapiz.DashStyle = CType(cboEstilo.SelectedItem, DashStyle) 'Estilo linea
vLapiz.MiterLimit = udLimite.Value 'Limite
vLapiz.StartCap = CType(cboInicioFlecha.SelectedItem, LineCap) 'inicio flecha
vLapiz.EndCap = CType(cboFinalFlecha.SelectedItem, LineCap) 'Final Flecha
vLapiz.DashCap = CType(cboRelleno.SelectedItem, DashCap) ' DashCap
vLapiz.LineJoin = CType(cboUnion.SelectedItem, LineJoin) ' Unión
vLapiz.Alignment = CType(cboAlinear.SelectedItem, PenAlignment) 'Alinear.

' Transformación
Select Case cboTransforma.Text
Case "None"
' Elimina la Transformación
vLapiz.ResetTransform()
Case "Scale"
vLapiz.ScaleTransform(0.5, 2)
Case "Rotate"
vLapiz.RotateTransform(45)
Case "Translate"
vLapiz.TranslateTransform(2, 4)
End Select

'Crear
grafico = pcDibujo.CreateGraphics()

If Me.cboForma.Text = "Líneas" Then


' Dibujar líneas simples usando vLapiz
grafico.DrawLine(vLapiz, 50, 50, pcDibujo.Width - 35, 35)
grafico.DrawLine(vLapiz, 35, 80, 35, pcDibujo.Height - 35)
grafico.DrawLine(vLapiz, 120, 120, pcDibujo.Width - 35, _
pcDibujo.Height - 35)

'Usando VLapizAncho para el efecto


grafico.DrawLine(vLapizAncho, 50, 50, pcDibujo.Width - 35, 35)
grafico.DrawLine(vLapizAncho, 35, 80, 35, pcDibujo.Height - 35)
grafico.DrawLine(vLapizAncho, 120, 120, pcDibujo.Width - 35, _
pcDibujo.Height - 35)
ElseIf Me.cboForma.Text = "Líneas Intersectadas" Then

' ´Dibujar Líneas intersactadas, se usa un array de puntos


Dim ptArray(5) As PointF
ptArray(0) = New PointF(35, 35)
ptArray(1) = New PointF(100, pcDibujo.Height - 50)
ptArray(2) = New PointF(150, 135)
ptArray(3) = New PointF(pcDibujo.Width - 40, 180)
ptArray(4) = New PointF(pcDibujo.Width \ 2, pcDibujo.Height - 50)
ptArray(5) = New PointF(300, 25)

' Dibujar Guia


grafico.DrawLines(vLapiz, ptArray)
' Lápìz ancho
grafico.DrawLines(vLapizAncho, ptArray)
ElseIf Me.cboForma.Text = "Círculos y Curvas" Then
' Dibujar círculo y curva
grafico.DrawEllipse(vLapiz, 25, 25, 200, 200)
grafico.DrawArc(vLapiz, 255, 5, pcDibujo.Width - 255, _
pcDibujo.Height - 55, 10, 150)

'Làpiz ancho
grafico.DrawEllipse(vLapizAncho, 25, 25, 200, 200)
grafico.DrawArc(vLapizAncho, 255, 5, pcDibujo.Width - 255, _
pcDibujo.Height - 55, 10, 150)
End If
End Sub

El código completo se encuentra en el archivo adjunto al final del artículo, no olvides de


votar antes de bajarlo en la casilla que se encuentra al inicio en la parte izquierda de la
página, eso me anima a seguir publicando. Cualquier consulta no dudes en escribir,
conforme el tiempo me lo permita contestaré todas sus dudas.

Herencia en Visual Basic .Net - I

Implementación de un formulario Plantilla

Sres. Desarrolladores, en esta oportunidad comparto con ustedes un ejemplo práctico y


pequeño sobre Herencia, la idea del artículo es dar a conocer como implementar
herencia, si bien este ejemplo es simple les puede dar la idea de como implementar otros
mas complicados,

ALGO DE TEORIA

Visual Basic.Net es compatible con la herencia, la capacidad de definir clases que


sirvan como base para las clases derivadas. Las clases derivadas heredan, y pueden
extender, las propiedades, métodos y eventos de la clase base. Las clases derivadas
también pueden reemplazar métodos heredados con nuevas implementaciones. De
forma predeterminada, todas las clases creadas con Visual Basic .NET se pueden
heredar.

La herencia permite escribir y depurar una clase una vez, y después volver a utilizar ese
código una y otra vez como base de nuevas clases. La herencia también permite utilizar
el polimorfismo basado en la herencia, la posibilidad de definir clases que pueden
utilizarse de forma intercambiable mediante código cliente en tiempo de ejecución, pero
con funcionalidad diferente, incluyo con métodos o propiedades denominados de
manera idéntica.

La instrucción Inherits

La instrucción Inherits se utiliza para declarar una nueva clase, denominada clase
derivada, basada en una clase existente conocida como clase base. Las clases derivadas
heredan, y pueden extender, las propiedades, métodos, eventos, campos y constantes
definidos en la clase base. En la siguiente sección se describen algunas de las reglas de
herencia, así como los modificadores que se pueden utilizar para cambiar la forma en
que las clases heredan o son heredadas:

 De forma predeterminada, todas las clases son heredables a menos que se


marquen con la palabra clave NotInheritable. Las clases pueden heredar de
otras clases del proyecto o de clases en otros ensamblados a los que hace
referencia el proyecto.
 A diferencia de los lenguajes que permiten la herencia múltiple, Visual Basic
.NET sólo permite la herencia simple en las clases; es decir, las clases
derivadas sólo pueden tener una clase base. Aunque no se permite la herencia
múltiple en las clases, éstas pueden implementar múltiples interfaces, lo que
permite lograr de manera eficaz los mismos fines.
 Para evitar la exposición de elementos restringidos en una clase base, el tipo de
acceso de una clase derivada debe ser igual o más restrictivo que el de su clase
base. Por ejemplo, una clase Public no puede heredar una clase Friend o
Private, y una clase Friend no puede heredar una clase Private.

Modificadores de herencia

Visual Basic .Net presenta las siguientes instrucciones y modificadores de nivel de clase
para ofrecer compatibilidad con la herencia:

 Instrucción Inherits: especifica la clase base.


 Modificador NotInheritable: impide que los programadores utilicen la clase
como clase base.
 Modificador MustInherit: especifica que la clase sólo se debe utilizar como
clase base. Las instancias de las clases MustInherit no se pueden crear
directamente; sólo se pueden crear como instancias de clase base de una clase
derivada. Otros lenguajes de programación, como C++ y C#, utilizan el término
clase abstracta para describir tal clase.

Reemplazar propiedades y métodos en clases derivadas

De forma predeterminada, una clase derivada hereda métodos de su clase base. Si una
propiedad o método heredado debe comportarse de forma diferente en la clase derivada,
puede ser reemplazado; es decir, puede definirse una nueva implementación del método
en la clase derivada. Los siguientes modificadores se utilizan para controlar cómo se
reemplazan propiedades y métodos:

 Overridable: permite reemplazar una propiedad o un método de una clase en


una clase derivada.
 Overrides: reemplaza una propiedad o un método Overridable definido en la
clase base.
 NotOverridable: impide reemplazar una propiedad o método en una clase que
hereda. Los métodos Public son NotOverridable de manera predeterminada.
 MustOverride: requiere que una clase derivada reemplace una propiedad o un
método. Cuando se utiliza la palabra clave MustOverride, la definición del
método consiste simplemente en la instrucción Sub, Function o Property. No
se permite ninguna otra instrucción y, específicamente, no existe ninguna
instrucción End Sub ni End Function. Los métodos MustOverride deben
declararse en las clases MustInherit.

La palabra clave MyBase

Puede utilizar la palabra clave MyBase para llamar a métodos de una clase base cuando
reemplace métodos en una clase derivada. Por ejemplo, suponga que diseña una clase
derivada que reemplaza un método heredado de la clase base. El método reemplazado
puede llamar al método de la clase base y modificar el valor devuelto como se muestra
en el fragmento de código siguiente:
Class DerivedClass
Inherits BaseClass
Public Overrides Function CalcularPago(ByVal Dist As Double, _
ByVal Rate As Double) As Double
' Llama al método de la Clase Base y retorna el Valor
Return MyBase.CalcularPago(Dist, Rate) * 2
End Function
End Class

En la lista siguiente se describen las restricciones de uso de MyBase:

 MyBase hace referencia a la clase base inmediata y a sus miembros heredados.


No se puede utilizar para tener acceso a miembros Private de la clase.
 MyBase es una palabra clave, no un objeto real. MyBase no se puede asignar a
una variable, pasar a procedimientos ni utilizar en una comparación Is.
 No es necesario definir el método al que califica MyBase en la clase base
inmediata; puede definirse en una clase base heredada indirectamente. Para
compilar correctamente una referencia calificada mediante MyBase, alguna
clase base debe contener un método correspondiente al nombre y el tipo de los
parámetros que aparezcan en la llamada.
 No puede utilizar MyBase para llamar a métodos de clase base con el
modificador MustOverride.
 No se puede utilizar MyBase para calificarse a sí misma. Por tanto, el siguiente
código no es válido:
 MyBase.MyBase.BtnOK_Click() ' Syntax error.
 No se puede utilizar MyBase en módulos.
 No se puede utilizar MyBase para tener acceso a miembros de clase base
marcados como Friend si la clase base está en un ensamblado diferente.

La palabra clave MyClass

La palabra clave MyClass permite llamar a un método Overridable implementado en


la clase y asegurarse de que se llama a la implementación del método en esta clase y no
a la de un método reemplazado en una clase derivada.

 MyClass es una palabra clave, no un objeto real. No se puede asignar a una


variable, pasar a procedimientos ni utilizar en una comparación Is.
 MyClass hace referencia a la clase base inmediata y a sus miembros heredados.
 MyClass puede utilizarse como calificador de miembros Shared.
 MyClass no se puede utilizar en módulos estándar.
 MyClass puede utilizarse para calificar un método que está definido en un clase
base y que no tiene ninguna implementación del método proporcionado en esa
clase. Tal referencia tiene el mismo significado que MyBase.Method.

Fuente: MSDN Library de Visual Studio .Net 2003

EL EJEMPLO

El formulario Base llamado frmPlantilla tiene el siguiente diseño:


En la clase base se ha creado una función con el siguiente código:

Protected Function CrearDataSet() As DataSet


Try
Dim cn As New SqlConnection("user id=sa;initial catalog=Northwind;persist
security info=False")
Dim daClientes As New SqlDataAdapter("Select
CustomerId,CompanyName,ContactName, Address from Customers", cn)
Dim dsDatos As New DataSet
daClientes.Fill(dsDatos, "Clientes")
Return dsDatos
Catch Ex As Exception
MessageBox.Show("Error: " & Ex.Message)
End
End Try
End Function

La clase heredada, que es otro formulario tiene el siguiente diseño:


A continuación sigue código en Visual Basic:

Al cargar el formulario heredado

Private Sub CargarConGrid(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

lblTitulo.Text = "Clientes - Herencia en Visual Basic .Net"


'Especificar el origen del Grid
'La función: CrearDataSet se encuentra en el
'formulario frmPlantilla que es del cual se hereda
dgClientes.DataSource = CrearDataSet.Tables("Clientes")
dgClientes.CaptionText = "Clientes Registrados"
'Darle formato al Grid
FormatearGrid()

End Sub
Note en la porción de código anterior la línea:
dgClientes.DataSource = CrearDataSet.Tables("Clientes")
en esta instrucción se ejecuta la función CrearDataSet implementada en la clase Base.

La línea de definición de la clase derivada es como sigue:

Public Class frmClientesGrid


Inherits VBHerencia.frmPlantilla

Los pasos para crear un formulario heredado son los siguientes:

1. Botón derecho en el Proyecto, seleccionar Agregar, luego Agregar formulario


heredado... se muestra lo siguiente:

2. Escribir el nombre del formulario heredado y pulsar click en Abrir


3. Seleccionar el objeto (formulario) del cual se heredará y pulsar click en Aceptar

Al crearse el formulario heredado para nuestro ejemplo aparece con el siguiente diseño
visto desde el IDE, en este hemos insertado un Grid, note los identificadores de los
controles que pertenecen a la clase Base.
Para terminar con el ejemplo, formateamos el Grid con el siguiente procedimiento

Private Sub FormatearGrid()


Dim EstiloTabla As New DataGridTableStyle
With EstiloTabla
.AlternatingBackColor = Color.LightCyan
.BackColor = Color.LightYellow
.ForeColor = Color.DarkGreen
.GridLineColor = Color.Chocolate
.GridLineStyle = System.Windows.Forms.DataGridLineStyle.None
.HeaderBackColor = Color.MidnightBlue
.HeaderFont = New Font("Times New Roman", 8.0!, FontStyle.Bold)
.HeaderForeColor = Color.White
.MappingName = "Clientes"
End With
' Formato para las columnas
Dim Col01 As New DataGridTextBoxColumn
With Col01
.HeaderText = "Id. Cliente "
.MappingName = "CustomerID"
.Width = 70
End With
Dim Col02 As New DataGridTextBoxColumn
With Col02
.HeaderText = "Compañía"
.MappingName = "CompanyName"
.Width = 200
End With

Dim Col03 As New DataGridTextBoxColumn


With Col03
.HeaderText = "Contacto"
.MappingName = "ContactName"
.Width = 150
End With

Dim Col04 As New DataGridTextBoxColumn


With Col04
.HeaderText = "Dirección"
.MappingName = "Address"
.Width = 180
End With
'Añadir los estilos de columnas al estiloTabla
EstiloTabla.GridColumnStyles.AddRange _
(New DataGridColumnStyle() _
{Col01, Col02, Col03, Col04})
'Añadir el estilo al Grid
dgClientes.TableStyles.Add(EstiloTabla)
End Sub

Respecto al formateo de Grid pueden visitar:


http://www.elguille.info/colabora/NET2005/FernandoLuque_FormateandoDataGrid.ht
m

Usando Estilos en Cascada en Aplicaciones Web

Formateando tu sitio Web

Sres. Desarrolladores, se que me extrañaron mucho, pero estuve y aun estoy algo
ocupado con unos proyectos pero definitivamente la fuerza y las ganas por colaborar
con sus conocimientos es mayor. Sin mas preámbulos vamor con lo nuestro.

Definición de Hoja de Estilos

Una hoja de estilos en cascada (CSS) contiene definiciones de estilos que se aplican
a los elementos de un documento HTML. Los estilos CSS definen la forma de mostrar
los elementos y su posición en la página. En lugar de asignar individualmente atributos
a cada elemento de la página, puede crear una regla general que aplique atributos
específicos siempre que un explorador Web encuentre una instancia de un elemento o
un elemento asignado a un cierto estilo CLASS.

Puede aplicar estilos CSS en línea a un elemento HTML individual, agrupados en un


bloque <STYLE> de la parte HEAD de una página Web o importado desde un archivo
de hoja de estilos en cascada (CSS). Es posible vincular un mismo archivo externo de
hoja de estilos en cascada a muchas páginas Web, con el fin de proporcionar una
apariencia uniforme a todo un sitio Web.

Para utilizar las reglas de estilo CSS en el Diseñador HTML, la propiedad targetSchema
del documento HTML se debe establecer en un explorador Web compatible con HTML
4.0 o superior. Los exploradores más antiguos, compatibles sólo con HTML 3.2 o
anteriores, ignorarán los estilos CSS. Cuando la propiedad targetSchema está
establecida en un explorador Web más antiguo, el entorno de desarrollo integrado (IDE)
oculta las opciones y propiedades de CSS que sólo están disponibles en exploradores
más recientes. Si se establece la propiedad targetSchema en un explorador compatible
con HTML 4.0, las reglas de estilo CSS constituyen el mejor método para especificar la
apariencia y la posición deseadas de los elementos HTML.

Cascada

Las reglas de estilo CSS se aplican "en cascada", es decir, las reglas de estilo globales se
seguirán aplicando a todos los elementos HTML a menos que sean sustituidas por las
reglas de estilo locales. En general, las reglas de estilo locales tienen prioridad sobre las
reglas de estilo globales. Esto significa que un estilo definido en un bloque STYLE de
una página Web, por ejemplo, puede modificar desde una página concreta el estilo de
todo el sitio Web definido en una hoja de estilos CSS externa. De forma similar, un
estilo en línea definido dentro de una etiqueta HTML individual de la página puede
modificar en una línea los estilos definidos para este tipo de elemento en todo el sitio.

Las partes de las reglas de estilo globales que no sean modificadas por las reglas de
estilo CSS locales seguirán aplicándose a los elementos HTML incluso después de que
se hayan aplicado los estilos locales. En el ejemplo anterior, los estilos CSS locales que
se aplican al texto escrito entre etiquetas <H1> reemplazan algunas reglas de estilo
globales del explorador Web para el texto de las etiquetas <H1> (centrar el texto de las
etiquetas <H1> y cambiar el color a rojo), pero no modifican las otras reglas (mostrar
todo el texto de las etiquetas <H1> en una fuente más grande y en negrita). Las reglas
de estilo globales y locales se aplican (en ese orden), y se muestra el texto de las
etiquetas <H1> de la página con una fuente grande, en negrita, y centrado y de color
rojo.

La siguiente tabla muestra como trabajan los estilos:

Nivel Definido en Aplica en


Toda la página donde
Global El archivo de hoja de estilo
se hace referencia
El elemento Head de la Todos los elementos en
Page
página la página actual
InLine Un elemento HTML Sólo el elemento
correspondiente

Nuestro Web Form por defecto, sin estilos

El archivo de Estilos

Un documento de hoja de estilos CSS externa es un archivo de texto sin formato con
una extensión .css que sólo contiene reglas de estilo. La instrucción

<LINK REL=stylesheet Type="text/css" HREF="MiEstilo.css">

aplica a la página las reglas de estilo de la hoja de estilos CSS externa "MiEstilo.css".

La imagen siguiente muestra el archivo Style.css


En la imagen anterior se muestra que se ha asignado al elemento BODY los siguientes
formatos: Negrita (bold), tamaño de 1.5 cm, espaciado normal, color rojo (red), letra
Itálica, fuente Verdana, espaciado de letras normal, color de fondo antiquewhite
y alineación derecha.

Crear los estilos


Para crear los estilos debemos seleccionar el elemento correspondiente de la ventana
Esquema CSS que se muestra en la parte izquierda. Una vez seleccionado se puede
pulsar clic en el botón Generar Estilo, presente en la barra de herramientas Hoja de
Estilos, tambien usando el menú Estilo y luego seleccionar Generar Estilo. La ventana
para generar el estilo se muestra asi:
Especificar el formato para cada elemento presente como: Fuente, Fondo, Texto, etc y
pulsar click en Aceptar

Otra forma
Se pueden asignar los formatos al estilo directamente usando la ventana de edición, la
imagen siguiente muestra el Intelissence que se despliega.
Seleccione el adecuado y especifique el formato, obviamente es mas complicado esta
forma.

Agregar Reglas de Estilo


Se puede agregar reglas para aplicar los estilos de acuerdo a las preferencias del
diseñador, para esto debemos seleccionar la opción Agregar regla de Estilo del menú
Estilos, la ventana se muestra de la siguiente manera
Nótese que para esta regla de estilo se ha incluído tres elementos (A:link, A:active y
A:visited) en una jerarquía definida, al final pulsar clic en Aceptar, después de agregar
se muestra:

Luego de agregar la Regla de estilo debe definirse el estilo de este, la forma mas
sencilla la he descrito lineas arriba, una vez definido el estilo puede quedar así:
Uso de los estilos
Cuando crea una aplicación en Visual Basic .Net automáticamente se crea un archivo de
estilo Style.css (para aplicaciones en C# debe insertarse) pero para utilizar los estilos
definidos en este debemos insertar el enlace de este en el HEAD de la página. La
imagen muestra resaltada la línea que debemos incluir:
Una vez asignada la Hoja de Estilos nuestro Web Form se muestra como sigue,
je,je,je...decidi cambiar algunas líneas de texto:
Crear estilo para un elemento específico
Se puede crear un estilo para un elemento específico, para esto debemos incluir su
definición utilizando el ID del elemento (Nombre) precedido del símbolo #. La
siguiente imagen muestra un estilo definido para el elemento con ID lblTitulo
Después de creado el estilo en la definición de la etiqueta debemos añadir el atributo
CssClass, la definición de la etiqueta es como sigue:

<asp:label id="lblTitulo" runat="server" CssClass="lblTitulo>

Y la presentación de la etiqueta lo muestra la siguiente imagen:

Después de asignar o cambiar algunos estilos para los elementos presentes para asignar
al texto presente basta seleccionarlo y utilizar el botón Formato de Bloque presente en la
barra de herramientas de Formato, después de jugar un poco hice esto bien feo...je,je,je.
Recuerden votar por este artículo, sus votos me animan a seguir publicando,
además que son un premio a mi esfuerzo.

Una cosilla que esta de mas: Crea un directorio Virtual y copias los archivos del
empaquetado que puedes bajarlo en el enlace al final del artículo... ya sé que sabías
hacerlo... no te enojes.

Espero que les sea útil, en las siguientes entregas veremos como:

 Crear estilos para listados


 Cambiar estilos en tiempo de ejecución
 Definir comportamientos de los estilos (behaviors)
 Manejo de varias hojas de estilo en mi sitio Web.

Reciban un fuerte abrazo (aunque un poquito atrazado) por Navidad y que todos sus
sueños y proyectos se cumplan y que el próximo año sea mucho mejor del que se
termina.

Feliz año 2006 y como siempre A SEGUIR DESARROLLANDO


Controles de Validación en ASP .Net

Sres. Desarrolladores, se que me extrañaron mucho, pero estuve y aun estoy algo
ocupado con unos proyectos pero definitivamente la fuerza y las ganas por colaborar
con sus conocimientos es mayor. Sin mas preámbulos vamos con lo nuestro.(párrafo
repetido de mi artículo anterior...je,je,je)

Validación de Datos

La validación de datos garantiza la corrección y precisión de todos los valores de datos


de la aplicación. La validación de datos de la aplicación puede diseñarse utilizando
distintos enfoques: código de interfaz de usuario, código de aplicación o restricciones de
bases de datos.

Hay varios tipos de validación de datos:

 Validación del tipo de datos.


 Comprobación del intervalo.
 Comprobación del código.
 Validación compleja.

Una de las formas más sencillas de validación de datos consiste en comprobar el tipo de
datos. La validación del tipo de datos responde a preguntas tan simples como "¿Es
alfabética la cadena?" y "¿Es numérico el número?". Normalmente, validaciones tan
simples se pueden controlar con la interfaz de usuario de la aplicación.

Como ampliación del tipo sencillo de validación, la comprobación del intervalo


garantiza que el valor proporcionado esté entre los valores máximo y mínimo
permitidos. Por ejemplo, un código de servicio con tipo de datos "character" sólo puede
admitir caracteres alfabéticos de la A a la Z; el resto de caracteres no sería válido. Al
igual que ocurre en el caso de la validación del tipo de datos, la interfaz de la aplicación
puede proporcionar normalmente la validación de intervalo necesaria aunque, como
alternativa de diseño, se puede crear una regla de empresa para controlar validaciones
de intervalo.

La comprobación del código es un poco más complicada y requiere normalmente una


tabla de búsqueda. Por ejemplo, supongamos que la aplicación calcula los impuestos
sobre ventas correspondientes únicamente a determinados códigos de estados. Será
necesario crear una tabla de validación que contenga códigos de estados sujetos a
impuestos que estén autorizados. Esta tabla de validación puede formar parte de una
regla de empresa, o se puede implementar directamente en la base de datos a efectos de
búsqueda mediante consulta.

A veces, una validación sencilla de búsqueda y de campo no es suficiente. Por ejemplo,


consideremos el caso de una petición de asistencia sanitaria que tiene un importe
facturado de 123,57 dólares, pero cuyo importe permitido puede depender de una
acumulación variable anual con un límite de 1.500 dólares (sin superar directiva de
duración máxima de 100.000 dólares). En esta situación, la validación de datos va más
allá de la pantalla de entrada de datos inmediata y consiste también en una evaluación
minuciosa de cómo se ha de pagar la petición basándose en los límites de la directiva y
en las acumulaciones anual y de vida. Este tipo de validación de datos compleja de
varios archivos se suele controlar mejor con reglas de empresa basadas en
procedimientos.

Las estructuras de archivos antiguas tienen el inconveniente de que los datos se


corrompen con frecuencia (por ejemplo, campos numéricos en blanco o con caracteres
alfabéticos). Cuando se crea una aplicación empresarial, se debe crear también una
utilidad de comprobación para verificar la corrección de cada uno de los campos de
todos los registros de los archivos que utiliza la aplicación. Si no se realiza esta acción,
los resultados producidos por la aplicación pueden ser imprevisibles.

Controles de Validación en ASP .Net

Los controles de servidor de validación son un conjunto de controles que permiten


validar un control de servidor de entrada asociado, como un control TextBox, y mostrar
un mensaje personalizado cuando se produce un error en la validación. Cada control de
validación realiza un tipo determinado de validación. Por ejemplo, se puede validar
frente a un valor específico o un intervalo de valores mediante los controles
CompareValidator y RangeValidator, respectivamente. Se puede incluso definir
criterios de validación propios mediante el control CustomValidator. Dado que el
mensaje de error se muestra en el control de validación, se puede controlar el lugar
donde se muestra el mensaje en la página Web colocando el control de validación en el
lugar deseado. También se puede mostrar un resumen de los resultados de todos los
controles de validación en la página mediante el control ValidationSummary.

De manera predeterminada, la validación se realiza al hacer clic en un control de botón,


como Button, ImageButton o LinkButton. Para impedir que se realice la validación al
hacer clic en un control de botón, establezca la propiedad CausesValidation del control
de botón en false. Esta propiedad suele estar establecida en false para un botón cancel o
clear con el fin de impedir que se realice la validación cuando se hace clic en el
botón.Las reglas de estilo CSS se aplican "en cascada", es decir, las reglas de estilo
globales se seguirán aplicando a todos los elementos HTML a menos que sean
sustituidas por las reglas de estilo locales. En general, las reglas de estilo locales tienen
prioridad sobre las reglas de estilo globales. Esto significa que un estilo definido en un
bloque STYLE de una página Web, por ejemplo, puede modificar desde una página
concreta el estilo de todo el sitio Web definido en una hoja de estilos CSS externa. De
forma similar, un estilo en línea definido dentro de una etiqueta HTML individual de la
página puede modificar en una línea los estilos definidos para este tipo de elemento en
todo el sitio.

Propiedades básicas de los controles de Validación

La siguiente tabla muestra las principales propiedades que se aplican a todos los
controles de validación.

Propiedad Descripción

ControlToValidate Id. de programación del control de salida que evaluará el control de


validación. Si no es un Id. legítimo, se iniciará una excepción.
Display Modo en que se muestra el control de validación especificado. Esta
propiedad puede ser uno de los siguientes valores:

Ninguno — El control de validación jamás se muestra en línea.


Utilice esta opción cuando desee mostrar el mensaje de error sólo en
un control ValidationSummary

Estático — El control de validación muestra un mensaje de error si


se produce un error en la validación. Se asigna un espacio en la
página Web para el mensaje de error incluso si el control de entrada
supera la validación. No cambia el diseño de la página cuando el
control de validación muestra su mensaje de error. Como el diseño
de página es estático, si hay varios controles de validación para el
mismo control de entrada, éstos deberán ocupar distintas
ubicaciones en la página.

Dinámico — El control de validación muestra un mensaje de error


si se produce un error en la validación. El espacio para el mensaje de
error se asigna dinámicamente en la página cuando se produce un
error en la validación. De este modo, varios controles de validación
pueden compartir la misma ubicación física en la página.
EnableClientScript Indica si está habilitada la validación en el cliente. Para deshabilitar
la validación en el cliente en los exploradores que admitan esta
función, establezca la propiedad EnableClientScript en false.

Enabled Indica si está habilitado el control de validación. Para impedir que el


control de validación valide un control de entrada, establezca esta
propiedad en false.

ErrorMessage Mensaje de error que se va a mostrar en el control


ValidationSummary si se produce un error en la validación. Si no
está establecida la propiedad Text del control de validación, también
se muestra este texto en el control de validación cuando se produce
un error en la validación. Se utiliza normalmente la propiedad
ErrorMessage para proporcionar diferentes mensajes para el
control de validación y el control ValidationSummary.

ForeColor Especifica el color en el que se va a mostrar el mensaje en línea


cuando se produce un error en la validación.

IsValid Indica si el control de entrada especificado por la propiedad


ControlToValidate se determina como válido.

Text Si esta establecida esta propiedad, se muestra este mensaje en el


control de validación cuando se produce un error en la validación. Si
no está establecida esta propiedad, el texto especificado en la
propiedad ErrorMessage se muestra en el control.

Descripción de los controles de Validación

Los controles de Validación los encontramos en el cuadro de herramientas, la imagen


siguiente muestra los controles encerrados marcados.

RequiredFieldValidator

Utilice el control RequiredFieldValidator para convertir un control de entrada en un


campo obligatorio. El control de entrada no supera la validación si el valor que contiene
no cambia con respecto al valor inicial cuando se realizó la validación. Esto impide que
el usuario deje el control de entrada asociado sin modificar. De manera predeterminada,
el valor inicial es una cadena vacía (""), que indica que se ha de especificar un valor en
el control de entrada para que éste supere la validación.

Nota Antes de realizar la validación se quitan los espacios adicionales situados al


principio y al final del valor de entrada. De este modo, se evita que un espacio
introducido en el control de entrada supere la validación.

A veces, se desea tener un valor inicial que no sea una cadena vacía. Esto resulta útil
cuando hay un valor predeterminado para un control de entrada y se desea que el
usuario seleccione otro valor. Por ejemplo, puede haber un control ListBox con una
entrada seleccionada, de manera predeterminada, que contiene instrucciones para que el
usuario seleccione un elemento de la lista. El usuario debe seleccionar un elemento del
control, pero se desea que el usuario no seleccione el elemento que contiene las
instrucciones. Para impedir que el usuario seleccione este elemento, especifique su valor
como valor inicial. Si el usuario selecciona este elemento, RequiredFieldValidator
mostrará su mensaje de error. Para especificar el valor inicial del control de entrada
asociado, establezca la propiedad InitialValue.

Nota La propiedad InitialValue no establece el valor predeterminado del control de


entrada. La propiedad InitialValue no tiene que coincidir ni siquiera con el valor
predeterminado del control de entrada. Indica simplemente el valor que el usuario no
podrá especificar en el control de entrada. El control de entrada no superará la
validación si contiene este valor al realizarse la validación.

Se pueden asociar varios controles de validación al mismo control de entrada. Se puede


utilizar, por ejemplo, un control de validación RequiredFieldValidator para asegurar
que se han escrito datos en un control y usar al mismo tiempo un control de validación
RangeValidator para comprobar que estos datos están comprendidos en un intervalo
especificado.

CompareValidator

El control CompareValidator permite comparar el valor especificado por el usuario en


un control de entrada, como un control TextBox, con el valor especificado en otro
control de entrada o con un valor constante. También se puede usar el control
CompareValidator para determinar si el valor especificado en un control de entrada se
puede convertir al tipo de datos especificado por la propiedad Type.

Especifique el control de entrada que desee validar estableciendo la propiedad


ControlToValidate. Si desea comparar un control de entrada específico con otro control
de entrada, establezca la propiedad ControlToCompare en el nombre del control que
desee comparar.

En lugar de comparar el valor de un control de entrada con otro control de entrada, se


puede comparar el valor de un control de entrada con un valor constante. Especifique el
valor constante con el que desee comparar estableciendo la propiedad
ValueToCompare.

La propiedad Operator permite especificar el tipo de comparación que se va a realizar,


como mayor que, igual que, etc. Si se establece la propiedad Operator en
ValidationCompareOperator.DataTypeCheck, el control CompareValidator
omitirá las propiedades ControlToCompare y ValueToCompare e indicará
simplemente si el valor especificado en el control de entrada puede convertirse al tipo
de datos especificado por la propiedad Type.

Nota Si el control de entrada está vacío, no se llamará a ninguna función de validación


y la validación se realizará correctamente. Utilice un control RequiredFieldValidator
para impedir que el usuario omita un control de entrada.

RangeValidator

El control RangeValidator permite comprobar si la entrada de un usuario se encuentra


entre un límite inferior y un límite superior especificados. Se pueden comprobar los
intervalos entre pares de números, caracteres alfabéticos y fechas. Los límites se
expresan como constantes.

Utilice la propiedad ControlToValidate para especificar el control de entrada que se va a


validar. Las propiedades MinimumValue y MaximumValue especifican los valores
mínimo y máximo del intervalo válido, respectivamente.

La propiedad Type se utiliza para especificar el tipo de datos de los valores que se van a
comparar. Los valores que se van a comparar se convierten a este tipo de datos antes de
realizarse cualquier comparación.

Nota Si el control de entrada está vacío, no se llamará a ninguna función de validación


y la validación se realizará correctamente. Utilice un control RequiredFieldValidator
para impedir que el usuario omita un control de entrada. De manera similar, si el valor
del control de entrada no se puede convertir al tipo de datos especificado por la
propiedad Type, la validación también se llevará a cabo correctamente. Se recomienda
encarecidamente utilizar un control CompareValidator adicional, con su propiedad
Operator establecida en ValidationCompareOperator.DataTypeCheck, con el fin de
comprobar el tipo de datos del valor de entrada.

Nota El control RangeValidator iniciará una excepción si el valor especificado por la


propiedad MaximumValue o MinimumValue no se puede convertir al tipo de datos
especificado por la propiedad Type.

RegularExpressionValidator

El control RegularExpressionValidator se utiliza para determinar si el valor de un


control de entrada coincide con un modelo definido por una expresión regular. Este tipo
de validación permite comprobar secuencias de caracteres previsibles, como las de los
números de la seguridad social, las direcciones de correo electrónico, los números de
teléfono y los códigos postales, entre otras.

Nota Si el control de entrada está vacío, no se llamará a ninguna función de validación


y la validación se realizará correctamente. Utilice un control RequiredFieldValidator
para impedir que el usuario omita un control de entrada.

La validación se realiza tanto en el cliente como en el servidor, salvo en el caso de que


el explorador no admita la validación en el cliente o ésta haya sido explícitamente
deshabilitada (estableciendo la propiedad EnableClientScript en false).

Utilice la propiedad ValidationExpression para especificar la expresión regular utilizada


para validar el control de entrada. La sintaxis de la validación mediante expresiones
regulares presenta algunas diferencias en el cliente y en el servidor. En el cliente, se
utiliza la sintaxis de expresiones regulares de JScript. En el servidor, se utiliza la
sintaxis Regex. Dado que la sintaxis de las expresiones regulares de JScript es un
subconjunto de la sintaxis Regex , se recomienda utilizar la primera para obtener los
mismos resultados en el cliente y en el servidor.alidator

CustomValidator
El control CustomValidator permite crear un control de validación con lógica de
validación personalizada. Por ejemplo, se puede crear un control de validación que
compruebe si el valor especificado en un cuadro de texto es un número par.
Los controles de validación siempre realizan la comprobación de validación en el
servidor. También tienen una implementación completa en el cliente que permite a los
exploradores compatibles con DHTML (como Microsoft Internet Explorer 4.0 ó
posterior) realizar la validación en el cliente.
La validación en el cliente mejora el proceso de validación ya que se comprueban los
datos proporcionados por el usuario antes de enviarlos al servidor. De este modo se
pueden detectar los errores en el cliente antes de enviar el formulario y se evita la acción
de ida y vuelta de la información necesaria para la validación en el servidor. Para crear
una función de validación en el servidor, proporcione un controlador del evento
ServerValidate que realiza la validación.
Para obtener acceso a la cadena del control de entrada que se va a validar, utilice la
propiedad Value del objeto ServerValidateEventArgs que se ha pasado al controlador de
eventos como parámetro. A continuación, se almacena el resultado de la validación en
la propiedad IsValid del objeto ServerValidateEventArgs.

Para crear una función de validación en el cliente, agregue primero la función de


validación en el servidor que se ha descrito anteriormente. A continuación, agregue a la
página .aspx la función de secuencia de comandos de validación en el cliente. Si utiliza
VBScript, la función deberá tener la siguiente forma:

Sub ValidationFunctionName (source, arguments)

Si utiliza JScript, la función deberá tener la siguiente forma:

Function ValidationFunctionName (source, arguments)

Utilice la propiedad ClientValidationFunction para especificar el nombre de la función


de secuencia de comandos de validación en el cliente que está asociada al control
CustomValidator. Como la función de secuencia de comandos se ejecuta en el cliente, la
función debe estar en un lenguaje que admita el explorador de destino, como VBScript
o JScript.

Al igual que en el caso de la validación en el servidor, la propiedad Value del parámetro


arguments permite obtener acceso al valor que se va a validar. Para devolver el
resultado de la validación, establezca la propiedad IsValid del parámetro arguments.

PRECAUCIÓN Al crear una función de validación en el cliente, asegúrese de incluir


asimismo la función de validación en el servidor. Si crea una función de validación en el
cliente sin una función correspondiente en el servidor, código malicioso podrá omitir la
validación. Se pueden asociar varios controles de validación a un control de entrada
individual para validar diferentes criterios.

Por ejemplo, se pueden aplicar varios controles de validación a un control TextBox que
permite al usuario especificar la cantidad de elementos que se han de agregar a un
carrito de la compra. Se puede utilizar un control CustomValidator para asegurar que el
valor especificado es menor que la cantidad del inventario y un control
RequiredFieldValidator para asegurar que el usuario especifica un valor en el control
TextBox.

Nota Si el control de entrada está vacío, no se llamará a ninguna función de validación y


la validación se realizará correctamente. Utilice un control RequiredFieldValidator para
impedir que el usuario omita un control de entrada. Se puede usar un control
CustomValidator sin establecer la propiedad ControlToValidate. Esto se suele hacer
cuando se validan varios controles de entrada o controles de entrada que no se pueden
usar con controles de validación, como el control CheckBox. En este caso, la propiedad
Value del parámetro arguments pasado al controlador de eventos para el evento
ServerValidate y a la función de validación en el cliente, siempre contiene una cadena
vacía (""). Sin embargo, se sigue llamando a estas funciones de validación en los casos
en los que resulte apropiado para determinar la validez en el cliente y en el servidor.
Para obtener acceso al valor que se va a validar, es preciso hacer referencia mediante
programación al control de entrada que se desea validar y, a continuación, recuperar el
valor de la propiedad apropiada. Por ejemplo, para validar un control CheckBox en el
servidor, no establezca la propiedad ControlToValidate del control de validación y
utilice el siguiente código para el controlador del evento ServerValidate:

Sub ServerValidation (source As object, args As ServerValidateEventArgs)

args.IsValid = (CheckBox1.Checked = True)

End Sub

Mostrar el resumen de los errores cometidos


El control ValidationSummary permite resumir los mensajes de error de todos los
controles de validación de una página Web en una sola ubicación. El resumen puede
aparecer en forma de lista, lista con viñetas o un único párrafo, en función del valor de
la propiedad DisplayMode. El mensaje de error que se muestra en el control
ValidationSummary para cada control de validación en la página viene especificado
por la propiedad ErrorMessage de cada control de validación. Si no está establecida la
propiedad ErrorMessage del control de validación, no se mostrará ningún mensaje de
error en el control ValidationSummary correspondiente a dicho control de validación.
También se puede especificar un título personalizado en la sección de encabezado del
control ValidationSummary estableciendo la propiedad HeaderText.

Para controlar si se muestra o se oculta el control ValidationSummary, establezca la


propiedad ShowSummary. El resumen también se puede mostrar en un cuadro de
mensaje estableciendo la propiedad ShowMessageBox en true.

Fuente: MSDN Library

Nuestro Ejemplo
Definiciones:

Para nuestro ejemplo, las definiciones resultantes de los controles utilizados es como
sigue:

Control a Validar Definición

<asp:requiredfieldvalidator id="rfvNombre"
runat="server" ToolTip="Ver error al final de la página"
Para txtNombre
Display="Dynamic" ControlToValidate="txtNombre"
RequiredFieldValidator
ErrorMessage="Falta Ingreso de
Nombre">*</asp:requiredfieldvalidator>
<asp:requiredfieldvalidator id="rfvDire" runat="server"
Para txtDire
Display="Dynamic" ControlToValidate="txtDire"
RequiredFieldValidator ErrorMessage="Falta Ingreso de
Dirección">*</asp:requiredfieldvalidator>

<asp:requiredfieldvalidator id="rfvEdad" runat="server"


Display="Dynamic" ControlToValidate="txtEdad"
ErrorMessage="Ingrese
Para txtDire Edad">*</asp:requiredfieldvalidator>
RequiredFieldValidator y <asp:comparevalidator id="CompareValidator2"
CompareValidator runat="server" Display="Dynamic"
ControlToValidate="txtEdad" ErrorMessage="Edad
mínima : 18 años" Type="Integer"
Operator="GreaterThanEqual"
ValueToCompare="18">**</asp:comparevalidator>
<asp:requiredfieldvalidator id="rfvEmail" runat="server"
Display="Dynamic" ControlToValidate="txtEmail"
ErrorMessage="Falta Ingreso de
Para txtEmail Email">*</asp:requiredfieldvalidator>
RequiredFieldValidator y
RegularExpressionValidato <asp:regularexpressionvalidator id="revEmail"
r runat="server" ControlToValidate="txtEmail"
ErrorMessage="Formato de correo no valido"
ValidationExpression="\w+([-+.]\w+)*@\w+([-
.]\w+)*\.\w+([-
.]\w+)*">**</asp:regularexpressionvalidator>
<asp:requiredfieldvalidator id="rfvPass1" runat="server"
Display="Dynamic" ControlToValidate="txtPass1"
ErrorMessage="Falta
Password">*</asp:requiredfieldvalidator>

<asp:requiredfieldvalidator id="rfvPass2" runat="server"


Para txtPass1 y txtPass2 Display="Dynamic" ControlToValidate="txtPass2"
RequiredFieldValidator y ErrorMessage="Ingrese nuevamente el
CompareValidator Password">*</asp:requiredfieldvalidator>

<asp:comparevalidator id="CompareValidator1"
runat="server" Display="Dynamic"
ControlToValidate="txtPass2" ErrorMessage="Password
No coincide"
ControlToCompare="txtPass1">**</asp:comparevalidator
>
<asp:comparevalidator id="cvFecha" runat="server"
Display="Dynamic" ControlToValidate="txtFecha"
ErrorMessage="Fecha incorrecta, debe ser antes de la
Para txtFecha
fecha actual" Type="Date"
CompareValidator
Operator="LessThan">*</asp:comparevalidator>
(este es un dato opcional)
 Se comprueba que la fecha sea anterior a la fecha
actual
 En el Load de la página se escribe el siguiente
código

If Not Page.IsPostBack Then

cvFecha.ValueToCompare = Today

End If
<asp:requiredfieldvalidator id="rfvFono" runat="server"
Display="Dynamic" ControlToValidate="txtFono"
ErrorMessage="Falta Ingreso de
Teléfono">*</asp:requiredfieldvalidator>

<asp:regularexpressionvalidator id="revFono"
runat="server" Display="Dynamic"
ControlToValidate="txtFono" ErrorMessage="Formato de
teléfono no valido" ValidationExpression="\(\d{3}\)\-
\d{3}\-\d{7}">**</asp:regularexpressionvalidator>

Nota: La expresión de Validación se ha escrito


directamente según el formato, ya,ya,ya....si tu teléfono
tiene otro formato aqui te doy el conjunto de caracteres que
puedes utilizar.

Caracter Definición

Para txtFono Debe ser un la letra a en


RequiredFieldValidator y a
minúsculas
RegularExpressionValidato
r
1 Debe ser el número 1

? 0 o un caracter

* 0 o N caracteres

1 o mas caracteres (al


+
menos uno)

Rango de 0 a n números
[0-n]
enteros

{n} Longitud de n caracteres

Separador de múltiples
|
opciones
El caracter que sique es
\
un comodín

\w Debe ser un caracter

\d Debe ser un Dígito

\. Debe ser el punto

Existen expresiones regulares como un correo, un sitio


Web, etc que vienen el plantillas definidas.
<asp:requiredfieldvalidator id="rfvValor" runat="server"
Display="Dynamic" ControlToValidate="txtValor"
ErrorMessage="Valor no
Para txtValor ingresado">*</asp:requiredfieldvalidator>
RequiredFieldValidator y
RangeValidator <asp:rangevalidator id="rangefvValor" runat="server"
Display="Dynamic" ControlToValidate="txtValor"
ErrorMessage=" Valor fuera del rango" Type="Double"
MaximumValue="800"
MinimumValue="230">**</asp:rangevalidator>

Al cometer algunos errores la página se muestra de la siguiente forma, al final de la


página se ha inclído un control ValidationSummary que muestra un resumen de los
errores cometidos.
Recuerden votar por este artículo, sus votos me animan a seguir publicando,
además que son un premio a mi esfuerzo.

Una cosilla que esta de mas: Crea un directorio Virtual y copias los archivos del
empaquetado que puedes bajarlo en el enlace al final del artículo... ya sé que sabías
hacerlo... no te enojes.

Reciban un fuerte abrazo (aunque un poquito atrazado) por Navidad y que todos sus
sueños y proyectos se cumplan y que el próximo año sea mucho mejor del que se
termina.

Feliz año 2006 y como siempre A SEGUIR DESARROLLANDO

Usando Store Procedures en aplicaciones ASP .Net


Uso de Parámetros

Sres. Desarrolladores, empezando este año 2006 quiero compartir con ustedes algunos
ejemplo de como usar Store Procedures en Aplicaciones Web ASP .Net.

Algo de Teoría
Un Store Procedure es un procedimiento de base de datos el cual se utiliza en una
determinada base de datos. El Store Procedure o Procedimiento Almacenado puede ser
accedido por cualquier aplicación con el fin de manipular los datos de esta.

El Store Procedure tiene escrito sus propias sentencias SQL llamadas sentencias
Transact-SQL, son similares a las funciones o procedimientos en las aplicaciones, son
llamados por su nombre y pueden tener parámetros tanto de ingreso de datos, de salida
o ambos.

Tipos de Procedimientos Almacenados


Existen tres tipos de Store Procedures:

1. Store Procedure que retorna registros

Este tipo de Store Procedures son utilizados para buscar registros específicos, ordenar o
filtrar estos y reportan su resultado el cual se almacena en un DataSet o en un control de
lista, son basados en sentencias SQL.

Ejemplo: Un Store Procedure que presente los clientes o pasajeros que viajaron en el
último mes que paso, y guardarlos en un DataSet o en un ListBox.

2. Store Procedure que retorna un Valor.

Este tipo de Store Procedures son utilizados para ejecutar un comando en una base de
datos o una función que retorna un valor único. El resultado de estos tipos de Store
Procedure se asignan generalmente a una variable.

Ejemplo: Mostrar el total de Items vendidos o atendidos en una orden.

3. Store Procedure que realiza una acción

Este tipo de Store Procedures son utilizados para realizar una acción determinada dentro
de una base de datos, no retornan registros ni valores. Las sentencias utilizadas en estos
tipos de Store Procedures pueden incluir actualizaciones, ediciones, modificaciones o
eliminaciones de registros.

Ejemplo: Modificar el correo electrónico de un cliente o su dirección.

Porque usar Store Procedures

Existen varios motivos por los cuales un desarrollador puede decidir usar Store
Procedures, una de las mas resaltantes es que resulta mas eficiente, mas seguro y no
requiere de conocimiento de como está diseñada la base de datos, en la siguiente tabla
se pueden resumir los principales beneficios del uso de Store Procedures:
Beneficio Descripción
Un Store Procedure es un clásico ejemplo de
Programación programación modular. Este se crea solo, se testea
Modular solo y se puede llamar muchas veces desde
diversas aplicaciones.
Los Store Procedure pueden crearse
independientemente por un especialista en base de
Distribución datos, mientras que pueden ser utilizados por los
desarrolladores de aplicaciones Web o por otros
desarrolladores.
Usando Store Procedures se aumentan
significativamente la seguridad en una base de
Seguridad
datos. Unicamente los testeadores y los dueños de
la base de datos pueden modificarlos.
El Store Procedure tiene mejor performance que
Ejecución rápida realizar las sentencias de manejo de datos
directamente desde la aplicación
Es posible que si una operación que requiera de
muchas sentencias se pueda ejecutar estas
Reduce el tráfico de
directamente en el Store Procedure, en nuestra
red
aplicación posiblemente realicemos esto con una
línea, la que ejecuta o invoca al SP.
El desarrollador de la base de datos puede cambiar
Flexibilidad
la estructura de esta sin afectar a las aplicaciones.

Crear Store Procedures


Consideraciones previas: Puede crear procedimientos almacenados mediante la
instrucción CREATE PROCEDURE de Transact-SQL. Pero antes de crear uno, tenga
en cuenta lo siguiente:

 Las instrucciones CREATE PROCEDURE no se pueden combinar con


otras instrucciones SQL en el mismo lote.
 De forma predeterminada, el permiso para crear procedimientos
almacenados corresponde al propietario de la base de datos, que puede
transferirlo a otros usuarios.
 Los procedimientos almacenados son objetos de base de datos y sus
nombres deben ajustarse a las reglas para los identificadores.
 Sólo puede crear un procedimiento almacenado en la base de datos
actual.
 Cuando cree un procedimiento almacenado, deberá especificar lo
siguiente:
 Todos los parámetros de entrada y de salida del lote o del procedimiento
que realiza la llamada.
 Las instrucciones de programación que realicen operaciones en la base
de datos, incluidas las llamadas a otros procedimientos.
 El valor de estado devuelto al lote o al procedimiento que realiza la
llamada, a fin de indicar que la operación se ha realizado correctamente o
que se ha producido un error (y el motivo del mismo).

Desde el Administrador Corporativo de SQL Server


Las dos imágenes muestran la forma:

Botón derecho en la base de datos, seleccionar Nuevo y luego Procedimiento


Almacenado

Seleccionar Procedimientos Almacenados de la base de datos donde se creará, pulsar


botón derecho y seleccionar Nuevo Procedimiento Almacenado, este proceso lo
muestra la siguiente figura:
Luego de cualquiera de los dos procedimientos se presenta:
En esta ventana escribimos el Store Procedure.

Tips:

 El botón Comprobar la Sintaxis no indica que el Store Procedure


funcione bien, unicamente que lo que hemos escrito sintácticamente este
correcto.
 Use el Analizados de consultas con las instrucciones que quiera realizar,
luego agregue estas en la edición del procedimiento, obviamente con los
cambios necesarios, es decir, cambiar los datos utilizados como ejemplo
por los respectivos parámetros.
 Usando la ventana Explorador de Servidores (Server Explorer)
también se pueden crear, editar, eliminar o ejecutar Store
Procedures. el usuario que se utilice debe tener acceso requerido
para esta opción.

EL EJEMPLO

Diseñe un WebForm con el siguiente aspecto: Dos DropDownList, dos DataGrids, dos
Buttons y dos etiquetas (Label) para mostrar el total de Items para una orden y el total
de órdenes de un Cliente.
En este se notan dos partes, la primera: la extracción de los detalles de una orden y el
cálculo del total de Items (suma de Quantity) para la orden y la segunda: mostrar las
órdenes de un determinado cliente y la suma de las órdenes generadas.

Para la primera parte se crearon y ejecutaron los siguiente Store Procedures:

CustOrdersDetail.- para extraer el detalle de la orden

ALTER PROCEDURE CustOrdersDetail


(
@OrderID int
)
AS

SELECT ProductName, UnitPrice=ROUND(Od.UnitPrice, 2),


Quantity, Discount=CONVERT(int, Discount * 100),
ExtendedPrice=ROUND(CONVERT(money, Quantity * (1 - Discount) *
Od.UnitPrice), 2)
FROM Products P, [Order Details] Od
WHERE Od.ProductID = P.ProductID and Od.OrderID = @OrderID

TotalItemsOrden.- para calcular el total de Items para la orden mostrada

ALTER PROCEDURE TotalItemsOrden


(
@OrderId nchar(5),
@TotalItems int OUTPUT
)
AS
Select @TotalItems=Sum(Quantity) from [Order Details] where orderId =
@OrderId
RETURN

Nota:
Los dos Store Procedures previos están presentes en la Base de datos Northwind (si no
lo están deben crearse).
El SP CustOrdersDetail tiene un parámetro de entrada llamado @OrderID y es de tipo
de los que retornan registros, el SP TotalItemsOrden tiene dos parámetros llamados
@OrderId y @TotalItems este de tipo OutPut y el SP es de tipo que retorna un valor.

El código implementado el el botón Mostrar es el siguiente

Private Sub cmdMostrar_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles cmdMostrar.Click

'Definir un SQLCommand, El nombre del Store Procedure en CommandText


'El CommandType = StoreProcedure y la conexion
Dim coDetalle As New SqlCommand
coDetalle.CommandText = "CustOrdersDetail"
coDetalle.CommandType = CommandType.StoredProcedure
coDetalle.Connection = cn 'Previamente definida

'El Adaptador y su SelectCommand


Dim daDetalle As New SqlDataAdapter
daDetalle.SelectCommand = coDetalle

'Parámetros si hubieran
Dim miParam As New SqlParameter("@OrderId", SqlDbType.Int)
miParam.Direction = ParameterDirection.Input
coDetalle.Parameters.Add(miParam)
coDetalle.Parameters("@OrderId").Value =
DropDownList1.SelectedItem.ToString

'Llenar el DataSet
'Al llenar el DataSet se ejecuta el Store Procedure
'el SQLCommand del SQLDataAdapter se especificó
'del tipo StoreProcedure
daDetalle.Fill(dsDatos, "Detalle")
'Origen del DataGrid
DataGrid1.DataSource = dsDatos.Tables("Detalle")
DataGrid1.DataBind()

'Para el total de Items


'Se ejecuta el Store Procedure TotalItemsOrden
Dim coTotal As New SqlCommand("TotalItemsOrden", cn)
coTotal.CommandType = CommandType.StoredProcedure

'Dos parámetros: El de Ingreso que es @OrderID


'El de salida es @TotalItems
Dim ParamOrderId As New SqlParameter("@OrderId", SqlDbType.NChar, 5)
ParamOrderId.Direction = ParameterDirection.Input
coTotal.Parameters.Add(ParamOrderId)
coTotal.Parameters("@OrderId").Value = DropDownList1.SelectedItem.ToString

'El parámetro de Salida


Dim ParamTotal As New SqlParameter("@TotalItems", SqlDbType.Int)
ParamTotal.Direction = ParameterDirection.Output
coTotal.Parameters.Add(ParamTotal)

cn.Open()
'Ejecutar el Store Procedure
coTotal.ExecuteScalar()
cn.Close()
lblTotalItems.Text = coTotal.Parameters("@TotalItems").Value.ToString
End Sub

El código completo se encuentra en el archivo ZIP al final del artículo.

Recuerden votar antes de bajar el código fuente en el archivo ZIP al final del artículo,
eso me motiva a seguir compartiendo mis conocimientos.

Artículos relacionados:
Uso de SQLDataReader con Store Procedures:
http://www.elguille.info/colabora/NET2005/FernandoLuque_Usando_SQLDataReader.
htm
Suerte y A SEGUIR DESARROLLANDO

Leer y escribir archivos XML en ASP .Net

Creación de archivos Nested XML

Sres. Desarrolladores, nuevamente para compartir con ustedes sobre el apasionante tema
del desarrollo y la programación de aplicaciones Web ASP .Net utilizando Visual Basic
.Net

Algo de teoría

DataSet, que es una caché de memoria interna de datos recuperados de un origen de


datos, representa un componente fundamental de la arquitectura de ADO.NET. DataSet
está compuesto por una colección de objetos DataTable que se pueden relacionar entre
ellos mediante objetos DataRelation. También se puede imponer la integridad de los
datos de DataSet mediante los objetos UniqueConstraint y ForeignKeyConstraint.

Mientras que los objetos DataTable contienen los datos,


DataRelationCollection permite desplazarse por la jerarquía de la tabla. Las tablas están
incluidas en un DataTableCollection al que se obtiene acceso a través de la propiedad
Tables. Al obtener acceso a los objetos DataTable, hay que tener en cuenta que éstos
distinguen entre mayúsculas y minúsculas condicionalmente. Por ejemplo, si un objeto
DataTable se denomina "mydatatable" y otro "Mydatatable", se considerará que una
cadena utilizada para buscar una de las tablas distingue entre mayúsculas y minúsculas.
Sin embargo, si existe "mydatatable" pero no existe "Mydatatable", se considerará que
la cadena de búsqueda no distingue entre mayúsculas y minúsculas. .

Un DataSet puede leer y escribir datos y esquemas como documentos XML. Los datos
y esquemas pueden transportarse, a continuación, a través de HTTP y cualquier
aplicación puede utilizarlos en cualquier plataforma que sea compatible con XML. Los
esquemas se pueden guardar como esquemas XML mediante el método
WriteXMLSchema, y tanto los esquemas como los datos se pueden guardar mediante el
método WriteXML. Hay que utilizar el método ReadXML para leer un documento
XML que incluya esquema y datos.

En una implementación normal de varios niveles, los pasos de creación y actualización


de un DataSet y, a su vez, de actualización de los datos originales, son los siguientes:

1. Construir y llenar cada DataTable de un DataSet con datos desde un origen de


datos mediante DataAdapter.
2. Cambiar los datos de los objetos DataTable individuales mediante la adición,
actualización o eliminación de objetos DataRow.
3. Llamar al método GetChanges para crear un segundo DataSet que sólo
incorpore los cambios realizados en los datos.
4. Llame al método Update de DataAdapter, pasando el segundo DataSet como
argumento.
5. Se invoca el método Merge para combinar los cambios del segundo DataSet con
el primero.
6. Invocar al método AcceptChanges de DataSet para aceptar los cambios. O bien,
invocar al método RejectedChanges para cancelar los cambios.

En nuestro ejemplo describiremos como manejar documentos XML, leer desde estos la
información y escribir en estos el contenido de un DataSet.

Creación de archivos XML manualmente

Para insertar un archivo XML dentro de nuestra aplicación debemos seguir los
siguientes pasos:

1. Seleccionar Agregar nuevo elemento del menú Proyecto y seleccionar Archivo


XML, escribir el nombre del archivo y pulsar Abrir

2. Escribir el contenido del archivo XML


En la figura anterior se nota el ingreso de dos elementos Cliente dentro del elemento
principal o raiz Clientes, cada elemento ingresado tiene 04 atributos: ClienteId, Nombre,
Apellidos y Profesion.

Tip: En la Vista de datos el ingreso de estos es mas sencillo, previamente debe crearse
la estructura en la vista XML, luego pasar a la vista de datos y agregar los datos. La
vista de datos para el ejemplo anterior es:
En la fila donde aparece el asterisco puede insertarse facilmente otro Cliente.

Creación de un esquema desde el documento XML creado


Una vez creado el documento o archivo XML se puede crear facilmente un esquema
(archivo xsd), simplemente seleccionar en la vista XML la opción Crear esquema del
menú XML, para el archivo XML anterior se creará un esquema como se muestra en la
figura:

Leer los archivos XML simples


Para leer archivos XML utilizamos en método ReadXML del DataSet previamente
instanciado, este método crea un DataTable en el DataSet unicamente con los datos del
archivo XML. La figura siguiente muestra el resultado de leer el archvo XML
Clientes.xml (previamente inserté a toda la familia...)
Importante
ReadXML unicamente lee el contenido del archivo XML cuando tiene un solo nivel
jerárquico, note la estructura del archivo XML People.xml que se muestra en la
siguiente figura:
El elemento Raíz People contiene elementos Person, estos a su vez otro nivel Name y
este anidado los elementos FirstName y LastName, al leer el archivo xml usando
ReadXML el resultado se muestra asi:
Entonces... ¿Cómo se lee el contenido ?
Será posiblemente el contenido de otro artículo, tiene que ver con XMLDataDocument
y XPath (muy interesante),

Escribir archivos XML

Para escribir el contenido de un DataSet en un archivo XML podemos (para el alcance


del artículo):

o Escribir los datos Sin Esquema usando WriteXML y asignando


IgnoreSchema en el parámetro XMLWriteMode
o Escribir los datos Con Esquema usando WriteXML y asignando
WriteSchema en el parámetro XMLWriteMode

Usando los datos de la tabla Products de la base de datos Northwind preparamos el


ejemplo como se muestra:
Los resultados de escribir los datos sin esquema y con esquema se muestran en las
figuras siguientes:
Note que unicamente se muestran los datos de los productos.
En este archivo XML se muestra primero el esquema y luego los artículos.

Código para el botón sin esquema

Private Sub cmdSinEsquema_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdSinEsquema.Click

daProductos.Fill(dsProductos, "Productos")
Dim miCarpeta As String =
System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)
dsProductos.WriteXml(miCarpeta & "\ProductosSinEsquema.XML",
XmlWriteMode.IgnoreSchema)
End Sub

Código para el botón con esquema

Private Sub cmdConEsquema_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdConEsquema.Click

daProductos.Fill(dsProductos, "Productos")
Dim miCarpeta As String =
System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)
dsProductos.WriteXml(miCarpeta & "\ProductosConEsquema.XML",
XmlWriteMode.WriteSchema)
End Sub

Nested XML File


Para mostrar el contenido de un DataSet con tablas relacionadas y guardarlos
relacionados en archivo XML debemos cambiar a True la propiedad Nested del
DataRelation creado.

Private Sub cmdNestedSinEsquema_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdNestedSinEsquema.Click

'Llenar el DataSet dsCatProd previamente creado


daCat.Fill(dsCatProd, "Categorias")
daCatProductos.Fill(dsCatProd, "Productos")

' La Relación
Dim colPadre As DataColumn
colPadre = dsCatProd.Tables("Categorias").Columns("CategoryId")
Dim colHijo As DataColumn
colHijo = dsCatProd.Tables("Productos").Columns("CategoryId")
Dim drCatProd As New DataRelation("CatProd", colPadre, colHijo)

'Definir Nested a True y Agregar la relación


drCatProd.Nested = True
dsCatProd.Relations.Add(drCatProd)
dgCatProd.DataSource = dsCatProd.Tables("Categorias")
dgCatProd.DataBind()

'La carpeta donde guardar el archivo


Dim miCarpeta As String = _
System.Environment.GetFolderPath(Environment.SpecialFolder.Personal)
dsCatProd.WriteXml(miCarpeta & "\CatProdSinEsquemaNested.XML",
XmlWriteMode.IgnoreSchema)
End Sub
El código completo lo puedes bajar en el archivo adjunto al final del artículo, vota antes
en PanoramaBox para premiar mi esfuerzo.Recuerda, compartir los conocimientos es
muy gratificante, vivir de tus conocimientos mucho mas.

Suerte y A SEGUIR DESARROLLAN DO

Uso de XMLDataDocument en aplicaciones Web ASP .Net

Un ejemplo sencillo y práctico

Sres. Desarrolladores, nuevamente para compartir con ustedes sobre el apasionante tema
del desarrollo y la programación de aplicaciones Web ASP .Net utilizando Visual Basic
.Net

El artículo anterior tiene una explicación mas amplia (parte teórica siempre necesaria)
http://www.elguille.info/colabora/NET2006/FernandoLuque_ASPyXML.htm

Artículos relacionados:

Controles de lista enlazados a base de datos


http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm

DataSets tipificados y no Tipificados


http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsI.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_DataSetsII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetI.htm

Typed DataSet: Ejercicio


http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSetII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_TypedDataSet03.htm

Algo de controles básico


http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesBasicos.htm

Para el manejo de Vistas


http://www.elguille.info/colabora/NET2005/FernandoLuque_FiltrosOrdenamientos.htm

Como ven... casi todo para que dominen este apasionante mundo del desarrollo.

XMLDataDocument

Esta clase extiende XMLDocument. Permite cargar datos relacionales o datos XML y
manipularlos utilizando Document Object Model (DOM) del Consorcio W3C. DOM
presenta los datos como una jerarquía de objetos de nodo. Dado que
XmlDataDocument implementa la interfaz IXPathNavigable, también se puede utilizar
como documento de origen de la clase XslTransform.

XmlDataDocument tiene una relación estrecha con la clase DataSet que proporciona
una vista relacional de los datos XML cargados. Los cambios efectuados en
XmlDataDocument se reflejan en DataSet y viceversa.
Para cargar DataSet con datos XML, utilice ReadXmlSchema para generar una
asignación relacional. A continuación, los datos XML se pueden cargar mediante Load
o LoadXML

Para cargar datos relacionales, especifique el DataSet que contenga los datos
relacionales como parámetro del constructor XmlDocument.
Fuente: Ayuda de Visual Studio 2003

El ejemplo

Quiero compartir con ustedes este tema muy interesante, la comunicación a través de
diferentes sistemas heterogeneos se da conversando el mismo idioma: XML.

En esta ocasión quiero resaltar la forma de como se forma un archivo Nested XML, este
se forma activando la propiedad Nested del objeto DataRelation utilizado al escribir el
archivo XML. Nuestro ejemplo en est ocasión simplemente lee el archivo, este se
muestra mas o menos así...

<? xml version="1.0" standalone="yes" ?>


< NewDataSet >
- <xs:schema id="NewDataSet" xmlns=""
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-
microsoft-com:xml-msdata">
-< xs:element name =" NewDataSet" msdata:IsDataSet =" true" msdata:Locale =" es-
PE">
-< xs:complexType >
-< xs:choice maxOccurs =" unbounded">
-< xs:element name =" Categorias">
-< xs:complexType >
-< xs:sequence >
<xs:element name=" categoryId" type=" xs:int" minOccurs="0" />
<xs:element name=" CategoryName" type=" xs:string" minOccurs="0" />
< xs:element name =" Description" type =" xs:string" minOccurs =" 0" />
-< xs:element name =" Productos" minOccurs =" 0" maxOccurs =" unbounded">
-< xs:complexType >
-< xs:sequence >
<xs:element name=" ProductID" type=" xs:int" minOccurs="0" />
<xs:element name=" ProductName" type=" xs:string" minOccurs="0" />
<xs:element name=" SupplierID" type=" xs:int" minOccurs="0" />
<xs:element name=" CategoryID" type=" xs:int" minOccurs="0" />
<xs:element name=" QuantityPerUnit" type=" xs:string" minOccurs="0" />
<xs:element name=" UnitPrice" type=" xs:decimal" minOccurs="0" />
<xs:element name=" UnitsInStock" type=" xs:short" minOccurs="0" />
<xs:element name=" UnitsOnOrder" type=" xs:short" minOccurs="0" />
<xs:element name=" ReorderLevel" type=" xs:short" minOccurs="0" />
<xs:element name=" Discontinued" type=" xs:boolean" minOccurs="0" />
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</ xs:choice >
</xs:complexType>
-< xs:unique name =" Constraint1">
<xs:selector xpath=" .//Categorias" />
<xs:field xpath=" categoryId" />
</xs:unique>
-< xs:keyref name =" CatProd" refer =" Constraint1" msdata:IsNested =" true">
<xs:selector xpath=" .//Productos" />
<xs:field xpath=" CategoryID" />
</xs:keyref>
</xs:element>
</ xs:schema >
-< Categorias >
< categoryId>1</categoryId>
< CategoryName>Beverages</CategoryName>
<Description>Soft drinks, coffees, teas, beers, and ales</Description>
-< Productos >
<ProductID>1</ProductID>
<ProductName>Chai</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit> 10 boxes x 20 bags</QuantityPerUnit>
<UnitPrice>18.0000</UnitPrice>
<UnitsInStock>39</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>10</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
-< Productos >
<ProductID>2</ProductID>
<ProductName>Chang</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
<UnitPrice>19.0000</UnitPrice>
<UnitsInStock>17</UnitsInStock>
<UnitsOnOrder>40</UnitsOnOrder>
<ReorderLevel>25</ReorderLevel>
<Discontinued>false</Discontinued>
</ Productos >
- <Productos>
<ProductID>24</ProductID>
<ProductName>Guaraná Fantástica</ProductName>
< SupplierID > 10 </ SupplierID >
<CategoryID>1</CategoryID>
<QuantityPerUnit>12 - 355 ml cans</QuantityPerUnit>
<UnitPrice>4.5000</UnitPrice>
<UnitsInStock>20</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>true</Discontinued>
</Productos>
-< Productos >
<ProductID>34</ProductID>
<ProductName>Sasquatch Ale</ProductName>
<SupplierID>16</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
<UnitPrice>14.0000</UnitPrice>
<UnitsInStock>111</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>15</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
-< Productos >
<ProductID>35</ProductID>
<ProductName>Steeleye Stout</ProductName>
<SupplierID>16</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>24 - 12 oz bottles</QuantityPerUnit>
<UnitPrice>18.0000</UnitPrice>
<UnitsInStock>20</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>15</ReorderLevel>
<Discontinued>false</Discontinued>
</ Productos >
- <Productos>
<ProductID>38</ProductID>
<ProductName>Côte de Blaye</ProductName>
< SupplierID > 18 </ SupplierID >
<CategoryID>1</CategoryID>
<QuantityPerUnit>12 - 75 cl bottles</QuantityPerUnit>
<UnitPrice>263.5000</UnitPrice>
<UnitsInStock>17</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>15</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
-< Productos >
<ProductID>39</ProductID>
<ProductName>Chartreuse verte</ProductName>
<SupplierID>18</SupplierID>
<CategoryID>1</CategoryID>
<QuantityPerUnit>750 cc per bottle</QuantityPerUnit>
<UnitPrice>18.0000</UnitPrice>
<UnitsInStock>69</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>5</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
.
.
.

</Categorias>
- <Categorias>
<categoryId>2</categoryId>
< CategoryName > Condiments </ CategoryName >
< Description > Sweet and savory sauces, relishes, spreads, and seasonings </
Description >
-< Productos >
<ProductID>3</ProductID>
<ProductName>Aniseed Syrup</ProductName>
<SupplierID>1</SupplierID>
<CategoryID>2</CategoryID>
<QuantityPerUnit>12 - 550 ml bottles</QuantityPerUnit>
<UnitPrice>10.0000</UnitPrice>
<UnitsInStock>13</UnitsInStock>
<UnitsOnOrder>70</UnitsOnOrder>
<ReorderLevel>25</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
-< Productos >
<ProductID>4</ProductID>
<ProductName>Chef Anton's Cajun Seasoning</ProductName>
<SupplierID>2</SupplierID>
<CategoryID>2</CategoryID>
<QuantityPerUnit>48 - 6 oz jars</QuantityPerUnit>
<UnitPrice>22.0000</UnitPrice>
<UnitsInStock>53</UnitsInStock>
<UnitsOnOrder>0</UnitsOnOrder>
<ReorderLevel>0</ReorderLevel>
<Discontinued>false</Discontinued>
</Productos>
.
.
.

En el contenido del archivo anterior llamado CatProdConEsquemaNested.XML. se


pueden ver claramente las siguientes partes:

1. La definición del Esquema donde se puede notar la estructura de los elementos y


los constraints o restricciones
Elemento Categorias
< xs:element name =" Categorias">

Constraint de Categorias y su nodo o Xpath respectivo


-< xs:unique name =" Constraint1">
<xs:selector xpath=" .//Categorias" />

Definición de la Clave foránea de Categorías y Productos


- < xs:keyref name =" CatProd" refer =" Constraint1" msdata:IsNested =" true">
<xs:selector xpath=" .//Productos" />
<xs:field xpath="CategoryID" />

La porción es la siguiente

-< NewDataSet >


- < xs:schema id =" NewDataSet" xmlns ="" xmlns:xs ="
http://www.w3.org/2001/XMLSchema" xmlns:msdata =" urn:schemas-microsoft-
com:xml-msdata">
-< xs:element name =" NewDataSet" msdata:IsDataSet =" true" msdata:Locale =" es-
PE">
-< xs:complexType >
-< xs:choice maxOccurs =" unbounded">
-< xs:element name =" Categorias">
-< xs:complexType >
-< xs:sequence >
<xs:element name=" categoryId" type=" xs:int" minOccurs="0" />
<xs:element name=" CategoryName" type=" xs:string" minOccurs="0" />
< xs:element name =" Description" type =" xs:string" minOccurs =" 0" />
-< xs:element name =" Productos" minOccurs =" 0" maxOccurs =" unbounded">
-< xs:complexType >
-< xs:sequence >
<xs:element name=" ProductID" type=" xs:int" minOccurs="0" />
<xs:element name=" ProductName" type=" xs:string" minOccurs="0" />
<xs:element name=" SupplierID" type=" xs:int" minOccurs="0" />
<xs:element name=" CategoryID" type=" xs:int" minOccurs="0" />
<xs:element name=" QuantityPerUnit" type=" xs:string" minOccurs="0" />
<xs:element name=" UnitPrice" type=" xs:decimal" minOccurs="0" />
<xs:element name=" UnitsInStock" type=" xs:short" minOccurs="0" />
<xs:element name=" UnitsOnOrder" type=" xs:short" minOccurs="0" />
<xs:element name=" ReorderLevel" type=" xs:short" minOccurs="0" />
<xs:element name=" Discontinued" type=" xs:boolean" minOccurs="0" />
</ xs:sequence >
</ xs:complexType >
</ xs:element >
</ xs:sequence >
</ xs:complexType >
</ xs:element >
</ xs:choice >
</ xs:complexType >
-< xs:unique name =" Constraint1">
<xs:selector xpath=" .//Categorias" />
<xs:field xpath=" categoryId" />
</ xs:unique >
-< xs:keyref name =" CatProd" refer =" Constraint1" msdata:IsNested =" true">
<xs:selector xpath=" .//Productos" />
<xs:field xpath=" CategoryID" />
</ xs:keyref >
</ xs:element >
</ xs:schema >

Los datos se presentan de manera jerárquica, note las lineas cambiadas a color azul
donde se presenta la categoria 1 y luego los productos de esa categoria mostrados en
color marrón.

El formulario se muestra asi:


El código implementado para leer el archivo es:

Private Sub cmdLeerDatos_Click(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cmdLeerDatos.Click

'Leer los datos desde la carpeta personal


'LEER EL ESQUEMA
dsdatos.ReadXmlSchema(GetFolderPath(SpecialFolder.Personal) _
& "\CatProdConEsquemaNested.XML")

'LEER LOS DATOS


dsdatos.ReadXml(GetFolderPath(SpecialFolder.Personal) _
& "\CatProdConEsquemaNested.XML")

'Crear el XMLDataDocument
Dim xmlData As New XmlDataDocument(dsdatos)

'Origen del Grid Categorias


dgDatos.DataSource = xmlData.DataSet.Tables(0)
dgDatos.DataBind()

'Productos
Dim vRel As String = dsdatos.Relations(0).RelationName
Dim vPrimero As String = dgDatos.Items.Item(0).Cells(0).Text
Dim mitabla As DataTable = dsdatos.Tables(1)
Dim mifiltro As String = "Categoryid = '" & vPrimero & "'"
Dim miorden As String = "ProductId ASC"

'Crear la Vista
Dim dvVista As New DataView(mitabla, mifiltro, miorden, _
DataViewRowState.CurrentRows)

'Origen del Grid de Productos


dgProductos.DataSource = dvVista
dgProductos.DataBind()

End Sub

El código completo ya sabes que se encuentra al final del artículo, vota previamente en
PanoramaBox, eso me alienta a seguir publicando.

Muy importante: En el empaquetado incluyo el archivo XML, la carpeta de donde lo


lee es Mis documentos del usuario ASPNET ubicada en: C:\Documents and
Settings\NET\ASPNET\Mis documentos

La última, estoy controlando la cantidad de visitantes con una variable de Aplicación.


Utiliza para esto el archivo Global.asax.

Suerte y A SEGUIR DESARROLLANDO

Filtrando un DataView por fechas

Uso de RowFilter

Sres. Desarrolladores, reciban un afectuoso saludo, aqui estoy nuevamente con la


satisfacción de haber logrado la certificación MCSD .Net hace algún tiempo y es por
eso que me alejé un poco de las publicaciones, pero ya estoy nuevamente para compartir
y ayudar.

El Ejemplo

Este ejemplo lo publico debido a una consulta de otro colega, he desarrollado un


pequeño ejemplo que se lo envié y ahora lo publico. Este ejemplo permite especificar un
rango de fechas y filtrar una vista usando RowFilter.

Para ordenar y filtrar un DataView pueden visitar:


http://www.elguille.info/colabora/NET2005/FernandoLuque_FiltrosOrdenamientos.htm

Para el uso del control ListView


http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm

El formulario inicial tiene el siguiente diseño:

Al filtrar las órdenes de Enero de 1997, usando Northwind se muestra como sigue,
notese como se muestra la etiqueta con la cantidad de órdenes.
Nota: Como he puesto en el código a manera de comentario, faltan las consistencias al
especificar el rango de fechas. La idea principal es manejar y construir de manera
correcta la cadena de filtro.

A continuación sigue código en Visual Basic:

Imports System.Data
Imports System.Data.SqlClient

Public Class Form1


Inherits System.Windows.Forms.Form

'La conexion
Dim cn As SqlConnection
'El SQLDataAdaptar
Dim daOrdenes As SqlDataAdapter
'El DataSet
Dim dsDatos As DataSet
'La Vista
Dim dvOrdenes As DataView

El código al cargar el formulario

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


Handles MyBase.Load

cn = New SqlConnection("user id=SA;data source=.;persist security


info=False;initial catalog=Northwind")
daOrdenes = New SqlDataAdapter("Select orderid, orderdate,freight from orders
order by orderdate", cn)

dsDatos = New DataSet

daOrdenes.Fill(dsDatos, "Ordenes")

LlenarlistaOriginal()

End Sub

Llenar la lista sin filtro

Private Sub LlenarlistaOriginal()


For i As Integer = 0 To dsDatos.Tables("Ordenes").Rows.Count - 1

lvOrdenes.Items.Add(dsDatos.Tables("Ordenes").Rows(i)("OrderId"))

lvOrdenes.Items(i).SubItems.Add(Format(dsDatos.Tables("Ordenes").Rows(i)("
OrderDate").ToString, "Short Date"))

lvOrdenes.Items(i).SubItems.Add(dsDatos.Tables("Ordenes").Rows(i)("Freight"
).ToString)

Next
End Sub

El botón filtrar

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As


System.EventArgs) Handles Button1.Click

' ******** SOLO FALTA LA CONSISTENCIA DE LAS FECHAS DE INICIO


Y FIN *****

'La Cadena de filtro

Dim vFechas As String

vFechas = "OrderDate >= " + "'" + Convert.ToString(Format(Me.dtInicio.Value,


"Short Date")) + "'"

vFechas &= "and OrderDate <= " + "'" +


Convert.ToString(Format(Me.dtFinal.Value, "Short Date")) + "'"

'Instancia de la Vista

dvOrdenes = New DataView(dsDatos.Tables("Ordenes"), vFechas, "OrderDate


ASC", DataViewRowState.OriginalRows)
'Limpiar lo que existe

Me.lvOrdenes.Items.Clear()

' Llenar la Vista con el resultado

For i As Integer = 0 To dvOrdenes.Count - 1

lvOrdenes.Items.Add(dvOrdenes.Item(i).Item(0).ToString)

lvOrdenes.Items(i).SubItems.Add(Format(dvOrdenes.Item(i).Item(1).ToString,
"Short Date"))

lvOrdenes.Items(i).SubItems.Add(dvOrdenes.Item(i).Item(2).ToString)

Next

lblsinFiltro.Text = CType(dvOrdenes.Count, String) + " órdenes"

End Sub

End Class

El código completo se encuentra en el archivo adjunto. Bájalo y no te olvides de votar,


tus puntos me alientan a seguir compartiendo.

Suerte a todos y a seguir desarrollado.

Combos con datos relacionados

Controles: ListView y StatusBar

Sres. Desarrolladores, reciban un afectuoso saludo, aqui estoy nuevamente con la


satisfacción de haber logrado la certificación MCSD .Net hace algún tiempo y es por
eso que me alejé un poco de las publicaciones, pero ya estoy nuevamente para compartir
y ayudar.

Para el Guille, te esperamos en Trujillo este 19 de Julio con la gira de INETA,


esperemos compartir conocimientos y gratos momentos.

Clientes y sus órdenes.

Este ejemplo lo publico debido a una consulta de otro colega, he desarrollado un


pequeño ejemplo que se lo envié y ahora lo publico. En este ejemplo presento dos
partes, la primera con el uso de la base de datos Northwind de SQL Server y la
presentación de los Clientes (Customers) en un ComboBox y sus órdenes
registradas (Orders) en otro.

También muestro de manera muy elemental el uso del control ListView, para aprender a
usar este control pueden visitar estos enlaces.
Para el uso del control ListView
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListView.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_Control_ListViewII.htm
http://www.elguille.info/colabora/NET2005/FernandoLuque_ListViewAvanzado.htm

Para el uso del control ComboBox


http://www.elguille.info/colabora/NET2005/FernandoLuque_El_Control_ComboBox.ht
m
http://www.elguille.info/colabora/NET2005/FernandoLuque_ControlesListaBD.htm

El formulario inicial tiene el siguiente diseño:

En la parte superior del formulario se puede visualizar los Clientes en el primer combo
y las órdenes del Cliente seleccionado en el segundo Combo. En la parte inferior como
insertar de manera simple datos en un ListView.

A continuación sigue código en Visual Basic:

Imports System.Data
Imports System.Data.SqlClient

Public Class frmcombos


Inherits System.Windows.Forms.Form

Dim cn As SqlConnection
Dim dsDatos As DataSet
Dim daClientes As SqlDataAdapter
Dim daOrdenes As SqlDataAdapter
Dim reClientesOrdenes As DataRelation

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


--- CODIGO ELIMINADO -----
#End Region

Private Sub Cargar(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles MyBase.Load

'Nueva instancia de la cadena de conexion


cn = New SqlConnection("user id=SA;data source=.;persist security
info=False;initial catalog=Northwind")

'El Adaptador
daClientes = New SqlDataAdapter("select customerid, companyname,
contactname from customers", cn)

'Instancia del DataSet


dsDatos = New DataSet

'Llenar el DataSet
daClientes.Fill(dsDatos, "Clientes")

'Origen del Combo Clientes


Me.cboClientes.DataSource = dsDatos.Tables("Clientes")
Me.cboClientes.DisplayMember =
dsDatos.Tables("Clientes").Columns("CustomerId").ToString
Me.cboClientes.SelectedIndex = 0
Me.lblCliente.Text =
dsDatos.Tables("Clientes").Rows(Me.cboClientes.SelectedIndex)("CompanyName").To
String

'Crear la tabla con órdenes


daOrdenes = New SqlDataAdapter("select orderid, customerid, orderdate, freight
from orders", cn)
daOrdenes.Fill(dsDatos, "Ordenes")

'Origen del Combo Órdenes


Me.cboOrdenes.DataSource = dsDatos.Tables("Ordenes")
Me.cboOrdenes.DisplayMember =
dsDatos.Tables("Ordenes").Columns("OrderId").ToString
Me.cboOrdenes.SelectedIndex = 0

'Mostrar el otro combo - Filtrar


Me.verOrdenes()
Me.lblCantidad.Text = Me.cboOrdenes.Items.Count.ToString + " órdenes"

Me.StatusBar1.Panels(1).Text = "Fecha: " + CType(Format(Today, "Short Date"),


String)
Me.StatusBar1.Panels(2).Text = "MCSD .Net Ing. Fernando Luque Sánchez"
Me.StatusBar1.Panels(3).Text = "Trujillo - Perú"

End Sub

Private Sub verOrdenes()


'crear una vista para filtrar
Dim dvOrdenes As New DataView(dsDatos.Tables("Ordenes"))
dvOrdenes.RowFilter = "CustomerId = '" & Me.cboClientes.Text & "'"
Me.cboOrdenes.DataSource = dvOrdenes
End Sub

Private Sub SeleccionarCliente(ByVal sender As System.Object, _


ByVal e As System.EventArgs) Handles cboClientes.SelectedIndexChanged

verOrdenes()
Me.lblCliente.Text =
dsDatos.Tables("Clientes").Rows(cboClientes.SelectedIndex)("CompanyName").ToStri
ng
Me.lblCantidad.Text = Me.cboOrdenes.Items.Count.ToString + " órdenes"

End Sub

' Para el contador


Dim vcuenta As Integer
Private Sub AgregarLista(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Me.ListView1.Items.Add(Me.TextBox1.Text)
Me.ListView1.Items(vcuenta).SubItems.Add(Me.TextBox2.Text)
vcuenta += 1
End Sub

End Class

El código completo se encuentra en el archivo adjunto. Bájalo y no te olvides de votar,


tus puntos me alientan a seguir compartiendo.

Suerte a todos y a seguir desarrollando.

Potrebbero piacerti anche