El presente instructivo tiene como objetivo transmitir los conocimientos necesarios para manipular base de datos con Sql Compact 3.5 SP1, presentando el desarrollo de una aplicación de una agencia de viaje utilizando Visual Studio 2008 (Visual Basic). Pueda que la base de datos no se encuentre completa, pero se tomaron las entidades necesarias para poder ejemplificar las operaciones básicas que son: Inserción de datos, actualizar datos, eliminar datos y consultar datos. Y por último se tomará en cuenta el diseño de un reporte para cumplir con la ley informática de entrada – proceso – salida.
Es un motor de base de datos relacional, de libre descarga y distribución, tanto para dispositivos móviles como para aplicaciones escritorio. Especialmente orientada a sistemas ocasionalmente conectados, ofrece unas características especialmente útiles para clientes ligeros. La versión más reciente es SQL Server Compact 3.5 SP1. Anteriormente era conocida como SQL Server CE o SQL Server Mobile. Desde la versión 2.0, el lanzamiento de SQL Server Compact ha ido ligado al de Microsoft Visual Studio .NET.
Nuevas características de SQL Server Compact 3.5 Service Pack 1 SQL Server Compact 3.5 Service Pack 1 (SP1) está incluido con SQL Server 2008 y Visual Studio 2008 SP1. Para obtener información detallada, vea el tema "Lo nuevo en SQL Server Compact Edition" en los Libros en pantalla de SQL Server Compact 3.5 Service Pack 1. A partir de la versión de SQL Server Compact 3.5 SP1, SQL Server Compact proporciona las siguientes características nuevas para los programadores: SQL Server Compact admite ADO.NET Entity Framework. Entity Framework permite trabajar con datos en forma de objetos y propiedades específicos del dominio, como clientes y direcciones de cliente, sin tener que preocuparse de las tablas y columnas de las bases de datos subyacentes donde se almacenan dichos datos. La compatibilidad para ADO.NET Entity Framework permite a los programadores crear consultas flexibles, con establecimiento inflexible de tipos, contra el contexto del objeto de Entity Framework utilizando directamente expresiones LINQ y operadores de consulta estándar LINQ directamente del entorno de desarrollo. SQL Server Compact admite las intercalaciones con distinción entre mayúsculas y minúsculas en el nivel de base de datos. Puede administrar una base de datos SQL Server Compact que esté almacenada en un Smart Device o en un equipo de escritorio utilizando SQL Server Management Studio (SSMS) en SQL Server 2008.
SQL Server Compact proporciona compatibilidad para la replicación de los nuevos tipos de datos en SQL Server 2008, como date, time, datetime2, datetimeoffset, geography y geometry. Los nuevos tipos de datos en SQL Server 2008 corresponden a nchar, nvarchar, image y otros tipos de datos. Para obtener más información sobre los tipos de datos en SQL Server 2008, vea Tipos de datos en los Libros en pantalla de SQL Server 2008. SQL Server Compact se puede ejecutar de forma nativa en un entorno de 64 bits. Los archivos .msi afectados son Tiempo de ejecución de 64 bits de SQL Server Compact (SSCERuntime-ENU.msi) y Herramientas de servidor de 64 bits de SQL Server Compact (SSCEServerTools-ENU.msi). La compatibilidad para los archivos .msi de 32 bits no ha cambiado. Los programadores que están utilizando la implementación ClickOnce para sus aplicaciones deben especificar las direcciones URL de descarga de 32 bits y de 64 bits. SQL Server Compact admite la replicación de datos con SQL Server 2000, SQL Server 2005 y SQL Server 2008 mediante Microsoft Synchronization Services for ADO.NET. Microsoft Synchronization Services for ADO.Net está disponible para equipos de escritorio y dispositivos móviles. SQL Server Compact admite la replicación de datos con SQL Server 2005 y SQL Server 2008 mediante la replicación de mezcla y el acceso a datos remoto (RDA). SQL Server Compact incluye la compatibilidad de la versión mejorada entre SQL Server Compact y SQL Server para la replicación de mezcla. Se pueden descargar Herramientas de servidor para configurar la replicación de mezcla y RDA mediante SQL Server Compact 3.5 SP1 del Centro del Centro de descarga de Microsoft. No Microsoft. No se pueden instalar Herramientas de servidor de SQL Server Compact 3.5 SP1 lado a lado con versiones anteriores de Herramientas de servidor en el equipo que está actuando como servidor de Internet Information Services (IIS). Herramientas de servidor de SQL Server Compact 3.5 SP1 pueden replicar datos entre SQL Server Compact 3.5 y SQL Server 2005 o SQL Server 2008. Herramientas de servidor de SQL Server Compact 3.5 SP1 también admiten la replicación de datos entre SQL Server 2005 Compact Edition o SQL Server 2005 Mobile Edition y SQL Server 2005 o SQL Server 2008. SQL Server Compact admite Windows Server 2008. Para obtener una lista de todas las versiones de Windows compatibles, vea Requisitos de hardware y software en los Libros en pantalla de SQL Server Compact. SQL Server Compact incluye varias mejoras para registro.
La base de datos está estructurada de la siguiente forma: Tabla Catálogos: Tipo de pago, Categoría, País, Región, Ciudad, Sexo, Atracciones, Clientes. Transaccionales: Viajes con su respectivo detalle. Reportes: Se van a generar los reportes por viajes, informe económico mensual.
SQL Server Compact proporciona compatibilidad para la replicación de los nuevos tipos de datos en SQL Server 2008, como date, time, datetime2, datetimeoffset, geography y geometry. Los nuevos tipos de datos en SQL Server 2008 corresponden a nchar, nvarchar, image y otros tipos de datos. Para obtener más información sobre los tipos de datos en SQL Server 2008, vea Tipos de datos en los Libros en pantalla de SQL Server 2008. SQL Server Compact se puede ejecutar de forma nativa en un entorno de 64 bits. Los archivos .msi afectados son Tiempo de ejecución de 64 bits de SQL Server Compact (SSCERuntime-ENU.msi) y Herramientas de servidor de 64 bits de SQL Server Compact (SSCEServerTools-ENU.msi). La compatibilidad para los archivos .msi de 32 bits no ha cambiado. Los programadores que están utilizando la implementación ClickOnce para sus aplicaciones deben especificar las direcciones URL de descarga de 32 bits y de 64 bits. SQL Server Compact admite la replicación de datos con SQL Server 2000, SQL Server 2005 y SQL Server 2008 mediante Microsoft Synchronization Services for ADO.NET. Microsoft Synchronization Services for ADO.Net está disponible para equipos de escritorio y dispositivos móviles. SQL Server Compact admite la replicación de datos con SQL Server 2005 y SQL Server 2008 mediante la replicación de mezcla y el acceso a datos remoto (RDA). SQL Server Compact incluye la compatibilidad de la versión mejorada entre SQL Server Compact y SQL Server para la replicación de mezcla. Se pueden descargar Herramientas de servidor para configurar la replicación de mezcla y RDA mediante SQL Server Compact 3.5 SP1 del Centro del Centro de descarga de Microsoft. No Microsoft. No se pueden instalar Herramientas de servidor de SQL Server Compact 3.5 SP1 lado a lado con versiones anteriores de Herramientas de servidor en el equipo que está actuando como servidor de Internet Information Services (IIS). Herramientas de servidor de SQL Server Compact 3.5 SP1 pueden replicar datos entre SQL Server Compact 3.5 y SQL Server 2005 o SQL Server 2008. Herramientas de servidor de SQL Server Compact 3.5 SP1 también admiten la replicación de datos entre SQL Server 2005 Compact Edition o SQL Server 2005 Mobile Edition y SQL Server 2005 o SQL Server 2008. SQL Server Compact admite Windows Server 2008. Para obtener una lista de todas las versiones de Windows compatibles, vea Requisitos de hardware y software en los Libros en pantalla de SQL Server Compact. SQL Server Compact incluye varias mejoras para registro.
La base de datos está estructurada de la siguiente forma: Tabla Catálogos: Tipo de pago, Categoría, País, Región, Ciudad, Sexo, Atracciones, Clientes. Transaccionales: Viajes con su respectivo detalle. Reportes: Se van a generar los reportes por viajes, informe económico mensual.
TABLA TIPOPAGO
Ésta tabla la vamos a utilizar para que se pueda llenar un combobox en la interfaz y muestre si el pago el cliente lo va realizar al crédito, contado o con tarjeta de crédito.
TABLA CATEGORIA
Ésta tabla vamos a almacenar la categoría de las atracciones si son: Museo, playa, isla, parques, etc.
TABLA REGION
Ésta tabla se va a utilizar para almacenar la región en la que se encuentra el país (o sea el continente).
TABLA PAIS
Ésta tabla se va a utilizar para almacenar los países por si la atracción turística se encuentra en otro país que no sea Honduras.
TABLA CIUDAD
Ésta tabla se va a utilizar para almacenar las ciudades en las que se encuentran las atracciones turísticas.
TABLA SEXO
Hasta tabla solo va ser utilizada para almacenar Femenino y Masculino, esto con el objetivo de no saturar la base de datos con demasiados caracteres, pero no se le va ser una catálogo ya que sabemos que solo esos dos tipos de sexo existen.
TABLA ATRACCIONES
Esta nos va a servir para ir almacenar las atracciones turísticas así como en que categoría se encuentran si son museo, playa, parques, etc. Y la ciudad en la que está ubicada geográficamente ésta atracción.
TABLA CLIENTES:
En ésta tabla nos interesa almacenar los datos generales de los clientes que van a comprar los paquetes turísticos de las atracciones.
TABLA VIAJES
Esta tabla va a funcionar como una factura es el mismo proceso viajes es el header por ende va a tener una que se llame de tails o detalles ya que en un viaje v iaje que va a un atracción turística turística “x” pueden ir varios clientes. Observaciones: En esta parte la tabla puede llevar más atributos, pero los limitamos a estos ya que
no tenemos una documentación de una empresa turística para así saber con certeza todos los datos que necesitamos almacenar.
TABLA DETALLES DE VIAJES
Ésta tabla detalles se hace necesario porque en un viaje a x atracción turísticas pueden ir varios clientes, y se coloca la casilla de pago por si hay algunos de la tercera edad y se les hace el descuento de la tercera edad que es de 25%.
Esto es en cuanto a la estructura de las tablas. Por si no se acuerdan como realizar un relación les voy a describir los pasos.
Para detallar los pasos se va a crear el Varrel (relación) entre la tabla de país y región. 1. Nos posicionamos en la tabla que contiene la Fk o sea a la que hace referencia en este caso es país a región, entonces nos ubicamos en país.
2. Damos clic derecho sobre país y seleccionamos la opción propiedades.
3. En el menú de las propiedades damos clic donde dice agregar relación.
4. Le escribimos nombre a la relación en este caso sería RegionPais. Y nos queda la siguiente configuración:
5. Ahora le damos clic en agregar columnas. Y nos queda la siguiente pantalla.
6. Ahora le damos clic en agregar relación. Y nos saldrá una ventana de mensaje y le damos aceptar.
7. Para comprobar que la relación se realizó de la forma correcta, nos vamos a la opción administrar relaciones.
Y listo ya tenemos realizada la relación entre la tabla país y región, por varrel RegionID. (Ver Videtutorial Crear relaciones en sql compact 3.5 sp1).
La aplicación la vamos a categorizar desarrollando las interfaces de las tablas catálogos, cabe mencionar que no todas las tablas catálogos necesitan interfaces, únicamente aquellas que en un futuro pueden ir generando más información pero las que ya están establecida no la necesitamos. El orden en que se va a desarrollar la aplicación es: 1. Categoría 2. País 3. Ciudad 4. Atracciones 5. Clientes 6. Viajes 7. Detalles de viajes La tabla catálogo de las regiones no le vamos a diseñar una interfaz ya que sabemos que son 5 continentes y que no se va a crear otro, entonces los agregamos directamente en la base de datos. Antes de iniciar a Diseñar lo primero que tenemos que establecer es la conexión a la base de datos. Vamos a copiar la base de datos viajes en la carpeta bin del proyecto.
Esto se hace con el objetivo de tener una visibilidad de la base de datos y poder trabajarla desde el visual studio sin tener que abrir en administrador de sql server. 1. Nos vamos a la pestaña de server explorer, si usted no ve en su IDE ésta pestaña la puede activar en: View – Server Explorer
2. Dar clic derecho en la opción de data Connections, y seleccionar Add Connections.
3. Nos aparece la siguiente ventana con Microsoft Sql Server como default.
4. Le damos clic en Change, y Seleccionamos Microsoft Server Compact 3.5, y le damos clic en OK.
5. Le indicamos el path de la base de datos que deseamos utilizar, dando clic en Browse.
6. Cuando hayamos seleccionado la base de datos le damos clic en abrir. Y nos queda el path de la base de datos.
7. Damos clic en test connection para saber si la conexión a la base de datos fue satisfactoria.
8. Y con esto ya estamos listos. Nota: Para mayor comprensión remítase al video que se titula agregar una base de datos al proyecto.
Este módulo nos va a permitir llamar la conexión a la base de datos en cualquier parte del código. 1. Dar clic donde dice Add new ítem. Y seleccionamos un módulo.
2. Le damos el nombre que deseamos y le damos aceptar y nos manda a la ventana de código del módulo.
3. Lo primero que hacemos es importar las librerías necesarias para realizar la conexión.
4. Luego realizamos el código para la Conexión.
5. Y con esto estamos listo para abrir la conexión a la base de datos donde lo necesitemos.
Nota importante: Si tienes problemas porque no te aparece el SqlServerCe para importarlo en la
conexión, esto se debe que se encuentran deshabilitados en los controles.
1. Nos ubicamos en la ventana de los controles. Le damos clic derecho y seleccionamos la opción choose ítems.
2.
Nos aparece la siguiente ventana y seleccionamos los siguientes elementos.
3. Luego le damos Ok, y se nos van agregar a la barra de controles.
4. Luego arrastramos la que dice SqlCeConnection al formulario y ya con esto estamos listos para realizar la conexión, y hacer uso de estas referencias.
La interfaz la vamos a diseñar un poco dinámica que no se vea un formulario estático. Por eso el diseño tiene dos fases: Fase 1:
Fase 2:
DESCRIPCION DE LOS CONTROLES:
Como se observa en la interfaz se necesitan 3 Label, 2 textbox, 3 button, 1 panel, 1 checkbox, 1 ListView. Descripción de las propiedades de los controles utilizados Primer Textbox:
Button Nuevo:
CheckBox
Name: TxtIdCategoría Enabled: False
Name: BtnNuevo Text : Nuevo
Name: ChkVer Text : Ver Categorías
Button Guardar:
Panel1 solo para contener la label y el listview.
Segundo TextBox:
Name:
Name: BtnGuardar Text: Guardar
ListView:
Name: LsvCategoria FullRowSelect: True GridLines: True View: Details
TxtNombreCategoría Enabled : Flase Button Actualizar:
Name: BtnActualizar Text: Actualizar Visible: False
Columnas: 1----Name: CategoriaID Text: Id Categoria 2---Name: NombreCategoria Text: Nombre Categoria.
Ahora que ya tenemos la descripción de los controles, vamos a lo emocionante a hacerlo funcional con el código. Lo primero que vamos hacer es que aparezca en el TxtIdCategoria el número correlativo que se va generando en este caso lo dejamos auto numéricos solo nos va a servir como una referencia. Para eso creamos un sub procedimiento para investigar el número correlativo.
' Sub Procedimiento para mostrar el numero correlativo del registro a crear. Public Sub InvestigarCorrelativo() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("Select max(CategoriaID) + 1 CategoriaID from Categoria", con) Dim categoriareader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If categoriareader.Read = True Then If categoriareader("CategoriaID") Is DBNull.Value Then Me.TxtIdCategoria.Text = 1 Else Me.TxtIdCategoria.Text = categoriareader("CategoriaID").ToString End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub Cuando creamos este sub procedimiento desarrollamos la codificación del Button Nuevo. Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Me.BtnGuardar.Enabled = True Call InvestigarCorrelativo() Me.TxtNombreCategoria.Focus() //Para que le de el enfoque para empezar a escribir. End Sub
Luego de haber desarrollado el código para el Button Nuevo, vamos a desarrollar el de guardar, siempre me gusta crear el sub procedimiento para guardar y en el botón hacer el llamado.
' Codigo que se utiliza para guardar los datos generales de la categoría. Sub GuardarCategoria() Try Dim Categoria As String Categoria = " Insert Into categoria " _ & " (NombreCategoria) " _ & " values ( '" & Trim(Me.TxtNombreCategoria.Text) & "') " con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Categoria, con) Command.ExecuteNonQuery() MessageBox.Show("Los datos de la Categoría se ingresaron correctamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Código del button Guardar. Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call GuardarCategoria() Call limpiar() Me.BtnGuardar.Enabled = False End Sub
Notamos que se llama a un sub procedimiento limpiar para que limpie los textbox y no lo hemos declarado, entonces vamos a desarrollar el código para que el sub procedimiento esté listo. Public Sub limpiar() Me.TxtIdCategoria.Text = Nothing Me.TxtNombreCategoria.Text = Nothing End Sub
Ahora que ya estamos almacenando información, es necesario consultarla, para darnos cuenta que la información se está almacenando físicamente en la base de datos. Para esto ya tenemos que tener configurado el ListView anteriormente he detallado las mismas. En primer lugar vamos a desarrollar el código de la consulta que va a poblar de datos al ListView.
'' Sub Procidimiento para consultar los datos de las categorías en la base de datos. Public Sub ConsultarCategorias() Me.LsvCategoria.Items.Clear() Try Dim sql As String = "Select CategoriaID, NombreCategoria from Categoria " con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con) Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader() While Lector.Read With Me.LsvCategoria.Items.Add(Lector.Item("CategoriaID").ToString) .SubItems.Add(Lector.Item("NombreCategoria").ToString) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Ahora que tenemos codificado el sub procedimiento para poblar el listview va a realizar la programación en el CheckBox ya que nuestra interfaz tiene dos fases, que ya las expliqué anteriormente. Cuando ejecutemos el formulario para agregar categoría se tiene que ver de esta forma:
Ahora agregamos el código que va ir en el checkbox porque este nos va a permitir jugar con las dimensiones del formulario, aclaro que éstas son las dimensiones de mi form, usted tendrá que adaptar a las dimensiones de su formulario.
Private Sub ChkVer_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChkVer.CheckedChanged If Me.ChkVer.Checked = True Then Me.Panel1.Visible = True Me.Width = 434 Me.Height = 383 Call ConsultarCategorias() Else Me.Panel1.Visible = False Me.Width = 434 Me.Height = 187 End If End Sub
Con la programación del código de check box cuando le demos clic nos tiene que salir lo siguiente:
Ahora vamos a retomar el asunto de la actualización de registros, en esta interfaz va a seguir el siguiente procedimiento, al darle doble clic en la fila donde se encuentra el registro nos va a pasar
esos valores a las textbox , para que allí podramos hacer la modificación correspondiente, y luego darle clic en el boton actualizar. Un registro listo para ser editado se verá de la siguiente forma:
Como podemos observar al darle doble clic al registro se pone como visible el button actualizar. Ahora vamos a escribir el código que se necesita para realizar esta operación. Lo vamos a realizar en el evento doble clic del control ListView.
Private Sub LsvCategoria_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LsvCategoria.DoubleClick Me.TxtIdCategoria.Text = Me.LsvCategoria.FocusedItem.Text Me.TxtNombreCategoria.Text = Me.LsvCategoria.FocusedItem.SubItems(1).Text Me.BtnActualizar.Visible = True Me.BtnNuevo.Enabled = False End Sub
Ahora vamos a crear el sub procedimiento que va a actualizar el registro seleccionado. ' Codigo que se utiliza para actualizar los datos de las categorías. Sub ActualizarCategoria() Try Dim Categoria As String Categoria = " Update categoria " _ & " set NombreCategoria = '" & Me.TxtNombreCategoria.Text & "' " _ & " where CategoriaID = " & Val(Me.TxtIdCategoria.Text) & ""
con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Categoria, con) Command.ExecuteNonQuery() MessageBox.Show("Los Datos de la categoria se actualizaron satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Vamos ahora a escribir el código que va a tener el button actualizar. Private Sub BtnActualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnActualizar.Click Call ActualizarCategoria() Call limpiar() Call ConsultarCategorias() Me.BtnNuevo.Enabled = True Me.BtnActualizar.visible = false End Sub
Como se había mencionado las interfaces de los formularios de las tablas catálogos llevan dos fases. Nada más que en este formulario se le agrega un control más un combobox, ya que un país pertenece a una región (Continente) en sí (América, Oceanía, Asia, Europa, Africa). Y como ésta es una información que no va a generar un nuevo registro entonces almacenamos los datos de forma manual y la mostramos en el combobox que lo llamaremos CboRegion. Fase 1:
Fase 2:
Descripción de las propiedades de los controles utilizados Primer Textbox:
Button Nuevo:
CheckBox
Name: TxtIdPais Enabled: False
Name: BtnNuevo Text : Nuevo
Name: ChkVer Text : Ver Países
Segundo TextBox:
Button Guardar:
Name: TxtNombrePais. MaxLength: 100
Name: BtnGuardar Text: Guardar Enabled : Flase
Panel1 solo para contener la label y el listview.
Combobox
Button Actualizar:
Name: CboRegion
Name: BtnActualizar Text: Actualizar Visible: False
ListView:
Name: LsvPais FullRowSelect: True GridLines: True View: Details Columnas: 1----Name: PaisID Text: Id Pais 2---Name: NombrePais Text: Nombre Pais 3---Name: Region Text: Región
Lo primero que vamos hacer es que aparezca en el TxtidCiudad el número correlativo que se va generando en este caso lo dejamos auto numéricos solo nos va a servir como una referencia. Para eso creamos un sub procedimiento para investigar el número correlativo.
' Sub Procedimiento para mostrar el numero correlativo del registro a crear. Public Sub InvestigarCorrelativo() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("Select max(PaisID) + 1 PaisID from Pais", con) Dim PaisReader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If PaisReader.Read = True Then If PaisReader ("PaisID") Is DBNull.Value Then Me.TxtIdPais.Text = 1 Else Me. TxtIdPais.Text = PaisReader ("PaisID").ToString End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub
Ahora creamos el sub procedimiento que va a poblar de datos el combobox región ya que lo vamos a llamar en el botón nuevo.
Public Sub LlenarComboRegion() 'Muestra todas las regiones (continentes) disponibles en la base de datos Try Dim Region As String Dim Ds As New DataSet con.Open() Region = "Select RegionID, NombreRegion " _ & " from Region " _ & " Order By RegionID Asc " Dim da As New SqlServerCe.SqlCeDataAdapter(Region, con) Dim dt As New DataTable da.Fill(Ds, "Region") Me.CboRegion.DataSource = Ds.Tables(0) Me.CboRegion.DisplayMember = Ds.Tables(0).Columns("NombreRegion").ToString Me.CboRegion.ValueMember = Ds.Tables(0).Columns("RegionID").ToString Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Ahora si estamos listo para escribir el código del botón nuevo. Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Call InvestigarCorrelativo() Me.TxtNombrePais.Focus() Call LlenarComboRegion() Me.BtnGuardar.Enabled = True End Sub Ahora vamos al boton guardar, tomando en cuenta la seguridad que plantié en el formulario catálogo anterior. El código de la función quedaría de la siguiente forma: ' Código que se utiliza para validar el registro y no se ingrese duplicado. Private Function ExisteRegistro() As Boolean Try Dim Pais As String = "Select Count(NombrePais) from Pais where NombrePais = "
Pais &= " '" & Trim(Me.TxtNombrePais.Text) & "'" con.Open() Dim sql As New SqlServerCe.SqlCeCommand(Pais, con) Dim i As Integer i = CInt(sql.ExecuteScalar()) If i > 0 Then Return True Else Return False End If Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Function
Ahora utilizamos esa función en nuestro sub procedimiento de guardar. Public Sub guardar() If ExisteRegistro() = False Then Try Dim Pais As String Pais = " Insert Into Pais " _ & " (NombrePais, RegionID) " _ & " values ( '" & Trim(Me.TxtNombrePais.Text) & "'," & Me.CboRegion.SelectedValue & ")" con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Ciudad, con) Command.ExecuteNonQuery() MessageBox.Show("Los datos del país se ingresaron correctamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try
Else MessageBox.Show("Ya existe este país en la base de datos" , "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Call Limpiar() Exit Sub End If End Sub
En el sub procedimiento de guardar hacemos referencias al sub procedimiento limpiar y no lo hemos creado, entonces quedaría de la siguiente forma: Public Sub limpiar() Me.TxtIdPais.Text = Nothing Me.TxtNombrePais.Text = Nothing Me.CboRegion.DataSource = Nothing Me.CboRegion.Text = Nothing End Sub Ahora colocamos la codificación que va en el botón guardar. Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call guardar() Call limpiar() Me.BtnGuardar.Enabled = False End Sub Hasta aquí ya estamos almacenando datos en la base de datos, ahora vamos a consultar si esos datos estan fisicamente en la misma, y es cuando vamos a hacer uso del listview, poblandolo con una consulta utilizando un inner join natural. Lo primero que vamos hacer es el diseño de la consulta para que poble de información al listview.
'' Sub Procidimiento para consultar los datos de los países en la base de datos. Public Sub ConsultarPaises() Me.LsvPais.Items.Clear() Try Dim sql As String = "Select a.PaisID, a.NombrePais, b.NombreRegion " _ & "From Pais a inner join Region b on a.RegionId = b.RegionId" con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con) Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader() While Lector.Read
With Me.LsvPais.Items.Add(Lector.Item("PaisID").ToString) .SubItems.Add(Lector.Item("NombrePais").ToString) .SubItems.Add(Lector.Item("NombreRegion").ToString) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Ahora el código del checkbox que va a mostrar el listview. Private Sub ChkVer_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChkVer.CheckedChanged If Me.ChkVer.Checked = True Then Me.Panel1.Visible = True Me.Width = 417 Me.Height = 377 Call ConsultarPaises() Else Me.Panel1.Visible = False Me.Width = 417 Me.Height = 202 End If End Sub Ahora pasamos a la parte de actualizar registros. Primero codificamos que cuando se le de doble clic al registro en el listview pase los datos a las textbox y combobox. Private Sub LsvPais_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LsvPais.DoubleClick Me.TxtIdPais.Text = Me.LsvPais.FocusedItem.Text Me.TxtNombrePais.Text = Me.LsvPais.FocusedItem.SubItems(1).Text Call LlenarComboRegion() Me.CboRegion.Text = Me.LsvPais.FocusedItem.SubItems(2).Text Me.BtnActualizar.Visible = True Me.BtnNuevo.Enabled = False End Sub
Ahora creamos el sub procedimiento para actualizar, los datos en la base de datos. ' Codigo que se utiliza para actualizar los datos de los paises. Sub ActualizarPaises() Try Dim Pais As String Pais = " Update Pais " _ & " set NombrePais = '" & Me.TxtNombrePais.Text & "'," _ & " RegionID = " & Me.CboRegion.SelectedValue & "" _ & " where PaisID = " & Val(Me.TxtIdPais.Text) & "" con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Pais, con) Command.ExecuteNonQuery() MessageBox.Show("Los Datos del país se actualizaron satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Sigue la codificación del botón actualizar. Private Sub BtnActualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnActualizar.Click Call ActualizarPaises() Call limpiar() Call ConsultarPaises() Me.BtnNuevo.Enabled = True Me.BtnActualizar.Visible = False End Sub
Como se había mencionado las interfaces de los formularios de las tablas catálogos llevan dos fases. Nada más que en este formulario se le agrega un control más un combobox, ya que tenemos una dependencia funcional en cuanto a ciudad con país, entonces le vamos asignar a la ciudad el país al cual pertenece entonces decimos que ciudad es funcionalmente dependiente de país. En éste contexto es necesario tomar en cuenta al momento de diseñar las interfaces cual necesitamos primero para crear la otra.
Fase 1:
Fase 2:
Descripción de las propiedades de los controles utilizados Primer Textbox:
Button Nuevo:
CheckBox
Name: TxtIdCiudad Enabled: False
Name: BtnNuevo Text : Nuevo
Name: ChkVer Text : Ver Ciudades
Segundo TextBox:
Button Guardar:
Name: TxtNombreCiudad MaxLength: 200
Name: BtnGuardar Text: Guardar Enabled : Flase
Panel1 solo para contener la label y el listview.
Combobox
Button Actualizar:
Name: CboPais
Name: BtnActualizar Text: Actualizar Visible: False
ListView:
Name: LsvCiudades FullRowSelect: True GridLines: True View: Details Columnas: 1----Name: CiudadID Text: Id Ciudad 2---Name: NombreCiudad Text: Nombre Ciudad 3---Name: Pais Text: País
Lo primero que vamos hacer es que aparezca en el TxtIdCiudad es el número correlativo que se va generando en este caso lo dejamos auto numéricos solo nos va a servir como una referencia. Para eso creamos un sub procedimiento para investigar el número correlativo.
' Sub Procedimiento para mostrar el numero correlativo del registro a crear. Public Sub InvestigarCorrelativo() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("Select max(CiudadID) + 1 CiudadID from Ciudad", con) Dim ciudadreader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If ciudadreader.Read = True Then If ciudadreader("CiudadID") Is DBNull.Value Then Me.TxtIdCiudad.Text = 1 Else Me.TxtIdCiudad.Text = ciudadreader("CiudadID").ToString End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub
Ahora creamos el sub procedimiento que va a poblar de datos el combobox País ya que lo vamos a llamar en el botón nuevo.
Public Sub LlenarComboPais() 'Muestra todas los países disponibles en la base de datos Try Dim pais As String Dim Ds As New DataSet con.Open() pais = "Select PaisID, NombrePais " _ & " From Pais " _ & " Order By PaisID Asc " Dim da As New SqlServerCe.SqlCeDataAdapter(pais, con) Dim dt As New DataTable da.Fill(Ds, "pais") Me.CboPais.DataSource = Ds.Tables(0) Me.CboPais.DisplayMember = Ds.Tables(0).Columns("NombrePais").ToString Me.CboPais.ValueMember = Ds.Tables(0).Columns("PaisID").ToString Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Ahora si estamos listo para escribir el código del botón nuevo. Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Me.BtnGuardar.Enabled = True Call InvestigarCorrelativo() Me.TxtNombreCiudad.Focus() Call LlenarComboPais() End Sub Ahora vamos al boton guardar, pero antes nos vamos a deterner en un punto importante que obvié en la primera catálogo y es en cuanto a la duplicidad de datos, vamos a diseñar una función que me permita verificar si la ciudad que estoy registrando ya existe en la base de datos y si ya existe que no me permita duplicarlo.
El código de la función quedaría de la siguiente forma: ' Código que se utiliza para validar el registro y no se ingrese duplicado. Private Function ExisteRegistro() As Boolean Try Dim Ciudad As String = "Select Count(NombreCiudad) from Ciudad where NombreCiudad = "
Ciudad &= " '" & Trim(Me.TxtNombreCiudad.Text) & "'" con.Open() Dim sql As New SqlServerCe.SqlCeCommand(Ciudad, con) Dim i As Integer i = CInt(sql.ExecuteScalar()) If i > 0 Then Return True Else Return False End If Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Function Ahora utilizamos esa función en nuestro sub procedimiento de guardar. Public Sub guardar() If ExisteRegistro() = False Then Try Dim Ciudad As String Ciudad = " Insert Into Ciudad " _ & " (NombreCiudad, PaisID) " _ & " values ( '" & Trim(Me.TxtNombreCiudad.Text) & "'," & Me.CboPais.SelectedValue & ")" con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Ciudad, con) Command.ExecuteNonQuery() MessageBox.Show("Los datos de la ciudad se ingresaron correctamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information)
Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try Else MessageBox.Show("Ya existe esta ciudad en la base de datos", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Call Limpiar() Exit Sub End If End Sub En el sub procedimiento de guardar hacemos referencias al sub procedimiento limpiar y no lo hemos creado, entonces quedaría de la siguiente forma: Public Sub limpiar() Me.TxtIdCiudad.Text = Nothing Me.TxtNombreCiudad.Text = Nothing Me.CboPais.DataSource = Nothing Me.CboPais.Text = Nothing End Sub Ahora colocamos la codificación que va en el botón guardar. Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call guardar() Call limpiar() Me.BtnGuardar.Enabled = False End Sub
Hasta aquí ya estamos almacenando datos en la base de datos, ahora vamos a consultar si esos datos estan fisicamente en la misma, y es cuando vamos a hacer uso del listview, poblandolo con una consulta utilizando un inner join. Lo primero que vamos hacer es el diseño de la consulta para que poble de información al listview.
'' Sub Procidimiento para consultar los datos de las ciudades en la base de datos. Public Sub ConsultarCiudades() Me.LsvCiudades.Items.Clear() Try
Dim sql As String = "Select a.CiudadID, a.NombreCiudad, b.NombrePais " _ & "From Ciudad a inner join Pais b on a.PaisID = b.PaisID" con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con) Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader() While Lector.Read With Me.LsvCiudades.Items.Add(Lector.Item("CiudadID").ToString) .SubItems.Add(Lector.Item("NombreCiudad").ToString) .SubItems.Add(Lector.Item("NombrePais").ToString) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Ahora el código del checkbox que va a mostrar el listview. Private Sub ChkVer_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChkVer.CheckedChanged If Me.ChkVer.Checked = True Then Me.Panel1.Visible = True Me.Width = 419 Me.Height = 383 Call ConsultarCiudades() Else Me.Panel1.Visible = False Me.Width = 419 Me.Height = 208 End If End Sub Ahora pasamos a la parte de actualizar registros. Primero codificamos que cuando se le de doble clic al registro en el listview pase los datos a las textbox y combobox.
Private Sub LsvCiudades_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LsvCiudades.DoubleClick Me.TxtIdCiudad.Text = Me.LsvCiudades.FocusedItem.Text Me.TxtNombreCiudad.Text = Me.LsvCiudades.FocusedItem.SubItems(1).Text Call LlenarComboPais() Me.CboPais.Text = Me.LsvCiudades.FocusedItem.SubItems(2).Text Me.BtnActualizar.Visible = True Me.BtnNuevo.Enabled = False End Sub Ahora creamos el sub procedimiento para actualizar, los datos en la base de datos. ' Codigo que se utiliza para actualizar los datos de las ciudades
Sub ActualizarCiudades() Try Dim Ciudad As String Ciudad = " Update Ciudad " _ & " set NombreCiudad = '" & Me.TxtNombreCiudad.Text & "'," _ & " PaisID = " & Me.CboPais.SelectedValue & "" _ & " where CiudadId = " & Val(Me.TxtIdCiudad.Text) & "" con.Open() Dim Command As New SqlServerCe.SqlCeCommand(Ciudad, con) Command.ExecuteNonQuery() MessageBox.Show("Los Datos de la ciudad se actualizaron satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Sigue la codificación del botón actualizar. Private Sub BtnActualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnActualizar.Click Call ActualizarCiudades() Call limpiar() Call ConsultarCiudades() Me.BtnNuevo.Enabled = True Me.BtnActualizar.Visible = False End Sub
Como toda la dinámica igual ésta va a tener dos fases, para que se vea algo de interacción. Nos encontramos ante una tabla que tiene dos referencias a tablas distintas por esto ésta lleva un poco más de código, pero básicamente es la misma lógica de las que veníamos haciendo. También se va a notar un poco más de complejidad ya que vamos a implementar más controles. Pero eso lo va hacer interesante, aclarando que ésta fue mi forma de visualizar para dar un ejemplo, usted con los conocimientos básicos puede diseñar la interfaz de su aplicativo empleando toda su creatividad. Es importante mencionar que en ésta interfaz vamos a necesitar importar dos librerías, ya que las fotos le vamos a dar un tratamiento binario para que se puedan almacenar en la base de datos. Las librerías son: Imports System.Data Imports System.IO
Fase 1:
T1
T2
C1
P1
C2
T3 k1
B1
B2
T4
B3
Descripción de las propiedades de los controles utilizados Primer Textbox (T1):
Button Nuevo (B1):
CheckBox (k1):
Name: TxtIdAtraccion Enabled: False
Name: BtnNuevo Text : Nuevo
Name: ChkVer Text : Ver Atracciones
Segundo TextBox (T2):
Button Guardar (B2):
PictureBox (P1):
Name: TxtNombreAtraccion MaxLength: 200
Name: BtnGuardar Text: Guardar Enabled : Flase
Name: PcbAtraccion BorderStyle: FixedSingle SizeMode: StretchImage ToolTip on ToolTip1: "De doble clic para seleccionar una foto"
Tercer TextBox (T3):
Name: TxtDescripcion MaxLength: 200 Cuarto TextBox (T4):
Button Actualizar (B3):
Name: BtnActualizar Text: Actualizar Visible: False
Name: TxtMensaje Segundo ComboBox (C2): Primer Combobox (C1):
Name: CboCategoría
Name: CboPaís
ToolTip1 y un OpenFileDialog1
Fase 2
L1
P1
Lv1
P2 L3
K1
L2
Descripción de las propiedades de los controles utilizados Label (L1):
PictureBox (P1):
Text: Atracciones agregadas al sistemas.
Name: PcbAtraccionVer SizeMode: StretchImage
LinkLabel (L2):
Panel (P2):
Name: LinkLabel1
Name: VerFotoPanel
ListView (Lv1):
3---Name: Descripcion Text: Descripción Width: 200
Columnas. 1---Name: AtraccionID Text: Id Atraccion Width: 70
4---Name: Categoria Text: Categoría Width: 130
Label (L3):
Name: LblAtraccion Text: Cerrar CheckBox (K1):
Name: ChkVerFoto Text: Ver Foto
2---Name: NombreAtraccion Text: Nombre Atracción Width: 200
5---Name: Ciudad Text: Ciudad Width: 130
Espero que haya quedado claro, o que se entienda bien cada uno de los controles, ahora voy a explicar la que contiene todos esos controles, aquí se ha utilizado lo que es el control TabControl, con dos TabPages. La primera TabPage en la propiedad name: TbpAtraccion y en la propiedad text: Atracciones. La segunda TabPage en la propiedad name: TbpVerAtracciones y en la propiedad Text: Ver Atracciones. Ahora sí, después de haber salido de este enrollo de la explicación de los controles vamos a pasar a la parte de la codificación. Lo primero, como en todos los formularios es crear el código de investigar el numero correlativo de la transacción, recuerde que todas las tablas tienen identity true en su atributo Clave por ende están auto numéricos, pero lo visualizamos para que nos sirva de referencia nada más.
' Sub Procedimiento para mostrar el numero correlativo del registro a crear. Public Sub InvestigarCorrelativo() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("Select max(AtraccionID) + 1 AtraccionID from Atraccion", con) Dim atraccionreader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If atraccionreader.Read = True Then If atraccionreader("AtraccionID") Is DBNull.Value Then Me.TxtIdAtraccion.Text = 1 Else Me.TxtIdAtraccion.Text = atraccionreader("AtraccionID").ToString End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub Ahora llenaremos los combobox que vamos a necesitar para que se facilite al usuario la selección de la categoría de la atracción y la ciudad a la que pertenece. Public Sub LlenarComboCategoria() 'Muestra todas categorías disponibles en la base de datos Try Dim Categoria As String Dim Ds As New DataSet con.Open() Categoria = "Select CategoriaID, NombreCategoria " _ & " From Categoria " _ & " Order By CategoriaID Asc " Dim da As New SqlServerCe.SqlCeDataAdapter(Categoria, con) Dim dt As New DataTable da.Fill(Ds, "Categoria") Me.CboCategoria.DataSource = Ds.Tables(0) Me.CboCategoria.DisplayMember = Ds.Tables(0).Columns("NombreCategoria").ToString Me.CboCategoria.ValueMember = Ds.Tables(0).Columns("CategoriaID").ToString Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Public Sub LlenarComboCiudad() 'Muestra todas las ciudades disponibles en la base de datos Try Dim Ciudades As String Dim Ds As New DataSet con.Open() Ciudades = "Select CiudadID, NombreCiudad " _ & " From Ciudad " _ & " Order By CiudadID Asc " Dim da As New SqlServerCe.SqlCeDataAdapter(Ciudades, con) Dim dt As New DataTable da.Fill(Ds, "Ciudades") Me.CboCiudad.DataSource = Ds.Tables(0) Me.CboCiudad.DisplayMember = Ds.Tables(0).Columns("NombreCiudad").ToString Me.CboCiudad.ValueMember = Ds.Tables(0).Columns("CiudadID").ToString Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Seguimos con creando el código que va tener el botón nuevo. Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Me.BtnGuardar.Enabled = True Call InvestigarCorrelativo() Me.TxtNombreAtraccion.Focus() Call LlenarComboCategoria() Call LlenarComboCiudad() Me.CboCategoria.Text = "Seleccione" Me.CboCiudad.Text = "Seleccione" End Sub Ya estamos preparados para agregar un nuevo registro a nuestra base de datos, entonces se prosigue con la creación del sub procedimiento que va almacenar los datos en la base de datos. Tomando en cuenta que usted puede desarrollar el código dentro del botón guardar, pero a mí me gusta la opción de crear el sub procedimiento porque así me deja con más libertad de realizar otras transacciones en el botón guardar. Hay que tomar en cuenta que tenemos en este formulario una picturebox que va a capturar la foto de la atracción turísticas por ende necesitamos agregar el control ir el en doble clic de la picturebox.
y el código va
Private Sub PcbAtraccion_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles PcbAtraccion.DoubleClick If Me.OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then Try
Me.PcbAtraccion.Image = Image.FromFile(OpenFileDialog1.FileName) Catch ex As BadImageFormatException MessageBox.Show("Formato incorrecto", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) Catch ex As Exception MessageBox.Show("Error al intentar abrir el archivo de imagen " & ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error) End Try End If End Sub Ya con éste código podemos desarrollar el código para el sub procedimiento guardar(). ' Sub Procedimiento que nos permitirá ingresar datos en la base de datos. Public Sub Guardar() Try '' Manejo de la foto Dim oStream As New MemoryStream() Me.PcbAtraccion.Image.Save(oStream, System.Drawing.Imaging.ImageFormat.Jpeg) Dim oBytes(oStream.Length - 1) As Byte oStream.Position = 0 oStream.Read(oBytes, 0, Convert.ToInt32(oStream.Length)) oStream.Close() '________________________________________________________________ Dim sql As String sql = "Insert into Atraccion " sql &= "(NombreAtraccion, Descripcion, CategoriaID, CiudadID, Imagen) " sql &= "values ('" & Trim(Me.TxtNombreAtraccion.Text) & "', " sql &= "'" & Trim(Me.TxtDescripcion.Text) & "'," & Me.CboCategoria.SelectedValue & ", " sql &= "" & Me.CboCiudad.SelectedValue & ", @imagen)" Dim comando As New SqlServerCe.SqlCeCommand(sql, con) ' Le pasamos la conversion de la imagen a binario por medio de un parámetro. comando.Parameters.Add("@imagen", SqlDbType.Image, oBytes.Length).Value = oBytes con.Open() comando.ExecuteNonQuery() MessageBox.Show("Atracción registrada satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) con.Close() Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub En Este sub procedimiento guardar sucede algo peculiar y es que tenemos que insertar la imagen de la atracción que estamos registrando, y no queremos guardar el path de un directorio donde se
encuentre la foto, ya que esto conlleva una desventaja porque si se borra la foto por error no nos va a mostrar la foto, si la guardamos en la base de datos, siempre va a estar allí, recuerde que una base de datos es precisamente eso, un conjunto de datos persistente, ya que ellos permanecen hasta que el usuario decide eliminarlos en este caso sería el DBA de la base de datos. Al tipo de consulta que hice para realizar el insert yo le llamo híbrida ya que utilizo, una string normal, pero en la foto le agrego un parámetro, ya que con la string normal es bien difícil hacer que se almacenen los binarios que ha producido la librería oStream. Entonces para guardar la imagen se lo paso por medio parámetro sql. Ahora creamos el código del sub procedimiento limpiar. Public Sub limpiar() Me.TxtIdAtraccion.Text = Nothing Me.TxtNombreAtraccion.Text = Nothing Me.TxtDescripcion.Text = Nothing Me.CboCategoria.DataSource = Nothing Me.CboCategoria.Text = Nothing Me.CboCiudad.DataSource = Nothing Me.CboCiudad.Text = Nothing Me.PcbAtraccion.Image = Nothing End Sub Ahora nos llega el tiempo de crear el código que va ir en el botón guardar. Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call guardar() Call limpiar() Me.BtnGuardar.Enabled = False End Sub Ya hemos creado el respectivo sub procedimiento para guardar los registros en la base de datos, y hemos creado el código del botón guardar, ahora vamos a crear el código del sub procidimiento que nos va a permitir consultar esos registros guardados. '' Sub Procidimiento para consultar los datos de las atracciones en la base de datos. Public Sub ConsultarAtracciones() Me.LsvAtraccion.Items.Clear() Try Dim sql As String = "Select a.AtraccionID, a.NombreAtraccion, a.Descripcion, b.NombreCategoria, c.NombreCiudad " _ & "From Atraccion a inner join Categoria b on a.CategoriaID = b.CategoriaID " _ & "inner join Ciudad c on a.CiudadID = c.CiudadID " _ & "Order by a.AtraccionID Asc" con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con)
Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader() While Lector.Read With Me.LsvAtraccion.Items.Add(Lector.Item("AtraccionID").ToString) .SubItems.Add(Lector.Item("NombreAtraccion").ToString) .SubItems.Add(Lector.Item("Descripcion").ToString) .SubItems.Add(Lector.Item("NombreCategoria").ToString) .SubItems.Add(Lector.Item("NombreCiudad").ToString) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Ahora escribimos el código del checkbox responsable de detonar el sub procedimiento para realizar la consulta a la base de datos. Private Sub ChkVer_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChkVer.CheckedChanged Call ConsultarAtracciones() Me.TabControl1.SelectedTab = TbpVerAtracciones End Sub Algo muy importante de explicar es que en la consulta no mostramos la foto de la atracción turística, y es por el hecho que la foto la vamos a mostrar por separado, primero vamos a seleccionar en el registro (en el listview) que foto deseamos ver y para poderla visualizar le vamos a dar clic en el checkbox Ver Foto, pero antes vamos a crear el sub procedimiento que va ir a consultar la foto que le corresponde al registro seleccionado por el usuario.
Sub MostrarFoto() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("SELECT NombreAtraccion, Imagen " _ & " From Atraccion" _ & " where AtraccionID = " & Val(Me.LsvAtraccion.FocusedItem.Text) & "", con) Dim atraccionreader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If atraccionreader.Read = True Then If atraccionreader("NombreAtraccion") Is DBNull.Value Then
Else Me.LblAtraccion.Text = atraccionreader("NombreAtraccion").ToString Dim msStream As New System.IO.MemoryStream(DirectCast(atraccionreader("Imagen"), [Byte]())) Dim objImagen As Image = Image.FromStream(msStream) Me.PcbAtraccionVer.Image = objImagen End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub Ahora escribimos el código de la checkbox que va a llamar el sub procedimiento de mostrar la foto. Private Sub ChkVerFoto_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ChkVerFoto.CheckedChanged If Me.ChkVerFoto.Checked = True Then Me.VerFotoPanel.Visible = True Call MostrarFoto() Else Me.VerFotoPanel.Visible = False Me.PcbAtraccionVer.Image = Nothing End If End Sub A continuación le muestro una secuencia de imágenes para que tengan una idea de como se va ver ya el codigo implementado en los controles correspondiente.
Ahora explico la secuencia de imágenes: 1. Le damos clic en el checkbox que dice ver atracciones. 2. Esto detona el sub procedimiento consultaratracciones y nos activa la tbpveratracciones, en donde se encuentra el listview con los datos de la consulta. 3. Seleccionamos el registro del cual queremos ver la foto. 4. Le damos clic en ver foto y nos aparecerá la foto. Como podemos observar aparece el nombre de la atracción Montañas Marron eso se lo enviamos a una label desde el código mostrar foto. También debajo de la foto tiene una linklabel que tiene como texto cerrar, esa lleva el siguiente código. Private Sub LinkLabel1_LinkClicked(ByVal sender As System.Object, ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) Handles LinkLabel1.LinkClicked Me.ChkVerFoto.Checked = False Me.VerFotoPanel.Visible = False Me.PcbAtraccionVer.Image = Nothing End Sub Ya hemos guardado, realizado consultas a la base de datos y que se muestran en un listview, ahora vamos a actualizar (modificar) registros. Recuerden que la opción de eliminar no es muy conveniente en los programas en donde los usuarios son los que manipulan los datos normalmente esta función la realiza el DBA mediante petición firmada, pero si su programa tiene privilegios de usuarios bien pueden crear la opción de eliminar tomando como base la consulta del insert o update. Antes de crear el sub procedimiento para actualizar, vamos a crear el código donde le demos doble clic al registro de la listview y nos pase esos valores a las textbox de tbpatracciones para que podamos realizar el cambio correspondiente. Private Sub LsvAtraccion_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LsvAtraccion.DoubleClick Me.TxtIdAtraccion.Text = Me.LsvAtraccion.FocusedItem.Text Me.TxtNombreAtraccion.Text = Me.LsvAtraccion.FocusedItem.SubItems(1).Text Me.TxtDescripcion.Text = Me.LsvAtraccion.FocusedItem.SubItems(2).Text Call LlenarComboCategoria() Call LlenarComboCiudad() Me.CboCategoria.Text = Me.LsvAtraccion.FocusedItem.SubItems(3).Text Me.CboCiudad.Text = Me.LsvAtraccion.FocusedItem.SubItems(4).Text Call MostrarFotoEdition() 'Para mostrar la foto en el PcbAtraccion Me.BtnActualizar.Visible = True Me.BtnNuevo.Enabled = False Me.TabControl1.SelectedTab = TbpAtraccion Me.TxtNombreAtraccion.Focus() End Sub Pueden notar que nos aparece el llamado a otro sub procedimiento que es mostrarfotoedition esto para llenar el PcbAtraccion con la foto correspondiente por si la quieren actualizar.
Ese sub procedimiento quedaría de la siguiente forma: ' Este sub procedimiento se necesita para mostrar la foto al momento de querer ' Editar un registro. Sub MostrarFotoEdition() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("SELECT NombreAtraccion, Imagen " _ & " From Atraccion" _ & " where AtraccionID = " & Val(Me.LsvAtraccion.FocusedItem.Text) & "", con) Dim atraccionreader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If atraccionreader.Read = True Then If atraccionreader("NombreAtraccion") Is DBNull.Value Then Else Me.LblAtraccion.Text = atraccionreader("NombreAtraccion").ToString Dim msStream As New System.IO.MemoryStream(DirectCast(atraccionreader("Imagen"), [Byte]())) Dim objImagen As Image = Image.FromStream(msStream) Me.PcbAtraccion.Image = objImagen End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "SkyManagment") Finally con.Close() End Try End Sub Ahora si ya estamos listos para desarrollar el código para actualizar los datos, algo muy importante que voy a explicar en la implementación de este sub procedimiento es que lo voy a hacer enviandole parámetros sql, en realidad toda la codificación debería llevar ésta forma ya que es la mas segura, en cuanto a las consultas dañinas. Con esto aseguramos que no nos puedan enviar un sql injection. ' Sub Procedimiento que nos permitirá ingresar datos en la base de datos. Public Sub ActualizarAtraccion() Try '' Manejo de la foto Dim oStream As New MemoryStream() Me.PcbAtraccion.Image.Save(oStream, System.Drawing.Imaging.ImageFormat.Jpeg) Dim oBytes(oStream.Length - 1) As Byte oStream.Position = 0 oStream.Read(oBytes, 0, Convert.ToInt32(oStream.Length)) oStream.Close() '________________________________________________________________ Dim actualizar As String actualizar = "Update Atraccion " actualizar &= "set NombreAtraccion = @NombreAtraccion, Descripcion = @Descripcion, " actualizar &= "Imagen = @Imagen, CategoriaID = @CategoriaID, CiudadID = @CiudadID "
Dim ComandoActualizar As New SqlServerCe.SqlCeCommand(actualizar, con) ' Le pasamos la conversion de la imagen a binario por medio de un parámetro. ComandoActualizar.Parameters.Add("@NombreAtraccion", SqlDbType.NVarChar).Value = Trim(Me.TxtNombreAtraccion.Text) ComandoActualizar.Parameters.Add("@Descripcion", SqlDbType.NVarChar).Value = Trim(Me.TxtDescripcion.Text) ComandoActualizar.Parameters.Add("@imagen", SqlDbType.Image, oBytes.Length).Value = oBytes ComandoActualizar.Parameters.Add("@CategoriaID", SqlDbType.Int).Value = Me.CboCategoria.SelectedValue ComandoActualizar.Parameters.Add("@CiudadID", SqlDbType.Int).Value = Me.CboCiudad.SelectedValue con.Open() ComandoActualizar.ExecuteNonQuery() MessageBox.Show("Atracción actualizada satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) con.Close() Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub
Aquí viene el paso final para tener concluido nuestro formulario que tanto dilema dio en la dinámica que está diseñado. El ultimo código que tenemos que crear es el que va en el botón actualizar. Private Sub BtnActualizar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnActualizar.Click Call ActualizarAtraccion() Call limpiar() Call ConsultarAtracciones() Me.BtnNuevo.Enabled = True Me.BtnActualizar.Visible = False Me.TabControl1.SelectedTab = TbpVerAtracciones End Sub
En ésta interfaz voy a diseñarla más simple ya que el manejo de fotografías ya lo hice en la interfaz anterior. Con esto quiero decir que es conveniente que se guarde la foto del cliente, pero ya hice todo el código que pueden utilizar para tratar las imágenes. En este caso solo voy a diseñar el formulario para realizar la inserción de un nuevo registro, y lo del listview lo voy a dejar para la categoría de consultas. Entonces solo va a tener una sola fase.
Los controles se listan en el orden en que se utilizaron de arriba hacia abajo. Descripción de las propiedades de los controles utilizados MaskedTextBox
ComboBox1
Button Nuevo:
Name: MtbRnp Mask: 0000-000000000
Name: CboSexo
Name: BtnNuevo Text : Nuevo
ComboBox2
Name: CboCiudad
Button Guardar:
MaskedTextBox
Name: BtnGuardar Text: Guardar Enabled : Flase
TextBox1
Name: TxtNombreCliente MaxLenght: 50
Name: MtbTelefono Mask: (999)000-0000
Button Actualizar: TextBox2
Texbox3
Name: TxtApellidoCliente MaxLenght: 50
Name: TxtDireccion MaxLenght: 200
Name: BtnActualizar Text: Actualizar Visible: False
Todos los controles, excluyendo los botones, se encuentran contenidas dentro de un panel, el cual tiene la propiedad enabled = false, para que solo puedan escribir en los controles cuando se dé clic en el botón nuevo.
En este caso que no tenemos un Id correlativo sino que es el Rnp del cliente, entonces no necesitamos crear un sub procedimiento que investigue cual es el número correlativo, entonces vamos a proceder a desarrollar el código de los dos combobox que se van a necesitar.
Public Sub LlenarComboCiudad() 'Muestra todas las ciudades disponibles en la base de datos Try Dim Ciudades As String Dim Ds As New DataSet con.Open() Ciudades = "Select CiudadID, NombreCiudad " _ & " From Ciudad " _ & " Order By CiudadID Asc " Dim da As New SqlServerCe.SqlCeDataAdapter(Ciudades, con) Dim dt As New DataTable da.Fill(Ds, "Ciudades") Me.CboCiudad.DataSource = Ds.Tables(0) Me.CboCiudad.DisplayMember = Ds.Tables(0).Columns("NombreCiudad").ToString Me.CboCiudad.ValueMember = Ds.Tables(0).Columns("CiudadID").ToString Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Ahora vamos a escribir el código de crear el código que va ir en el boton nuevo. Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Call LlenarComboCiudad() Call LlenarComboSexo() Me.CboCiudad.Text = "Seleccione" Me.CboSexo.Text = "Seleccione" Me.Panel1.Enabled = True Me.MtbRNP.Focus() Me.BtnGuardar.Enabled = True End Sub
Ahora que ya estamos listo habilitando los controles para poder generar un nuevo registro lo vamos a almacenar en la base de datos, es bueno mencionar que aquí nos vamos a detener en desarrollar el código de una función que me permita ir a buscar el rnp de un cliente y si este ya existe que no me permita ingresarlo en la base de datos.
' Código que se utiliza para validar el registro y no se ingrese duplicado. Private Function ExisteRegistro() As Boolean Try Dim cliente As String = "Select Count(Rnp) from Clientes where RNP = " cliente &= " '" & Trim(Me.MtbRNP.Text) & "'" con.Open() Dim sql As New SqlServerCe.SqlCeCommand(cliente, con) Dim i As Integer i = CInt(sql.ExecuteScalar()) If i > 0 Then Return True Else Return False End If Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Function
Public Sub guardar() If ExisteRegistro() = False Then Try Dim cliente As String cliente = " Insert Into Clientes " _ & " (Rnp, NombreCliente, ApellidosCliente, Telefono, CiudadID, SexoId, Direccion) " _ & " values ( '" & Trim(Me.MtbRNP.Text) & "','" & Trim(Me.TxtNombreCliente.Text) & "', " _ & " '" & Trim(Me.TxtApellidoCliente.Text) & "','" & Me.MtbTelefono.Text & "'," & Me.CboSexo.SelectedValue & ", " _ & " " & Me.CboCiudad.SelectedValue & ",'" & Trim(Me.TxtDireccion.Text) & "')" con.Open() Dim Command As New SqlServerCe.SqlCeCommand(cliente, con)
Command.ExecuteNonQuery() MessageBox.Show("Los datos del cliente se han ingresaron correctamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try Else MessageBox.Show("Ya existe este numero de identidad en la base de datos", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) Call Limpiar() Exit Sub End If End Sub
Ahora escribimos el código que va a llevar el sub procedimiento limpiar. Sub limpiar() Me.MtbRNP.Text = Nothing Me.TxtNombreCliente.Text = Nothing Me.TxtApellidoCliente.Text = Nothing Me.CboSexo.DataSource = Nothing Me.CboCiudad.DataSource = Nothing Me.MtbTelefono.Text = Nothing Me.TxtDireccion.Text = Nothing Me.Panel1.Enabled = False End Sub Ahora escribimos el código que va a llevar en el botón guardar. Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call guardar() Call limpiar() End Sub
Ahora vamos a diseñar la interfaz de los viajes o paquetes de viajes que estarán disponibles para que los clientes puedan seleccionar el paquete que mejor les parece. Hay que aclarar que en la base de datos la clave primaria de viajes no tiene identity true por ende vamos a crear el sub procedimiento que nos permita ir mostrando el numero correlativo de cada transacción y así poderlo almacenar en la base de datos.
Descripción de las propiedades de los controles utilizados GroupBox1
Textbox1:
Button Nuevo:
Text:Datos del Viaje Enabled: False
Name: TxtIdViaje Enabled: false
Name: BtnNuevo Text : Nuevo
Label1:
Textbox2:
Button Guardar:
Text: Id Viaje
Name: TxtIdAtraccion Visible: False
Name: BtnGuardar Text: Guardar Enabled : Flase
Label2:
Text: Atracción
Textbox3:
Name: TxtAtraccion
Button …
DateTimePicker
Name: BtnBuscar FlatStyle: Flat
Label3:
Text: Fecha del Viaje
Name: DtpFechaViaje Label4:
Text: Costo
Textbox4:
Name: TxtCosto TextAlign: Right
Esta otra ventana la vamos a necesitar para que cuando demos clic en el botón de buscar las atracciones turísticas nos permita ver el listado de las atracciones disponibles en el sistema. En cuanto a los controles lo único que tiene es una label con el mensaje Atracciones disponisbles en el sistema:
Y un listview que tiene 4 columnas: el nombre del listview es LsvListaAtracciones, y las columnas van con las siguientes propiedades: GridLines: true, FullRowSelected = true 1---
2---
3---
4---
Name: AtraccionID Text: Id Atraccion Width: 70
Name: NombreAtraccion Text: Nombre Atraccion Width: 150
Name: NombreCategoria Text: Categoría Width: 100
Name: NombreCiudad Text: Ciudad Width: 100
El primer sub procedimiento a diseñar es el de investigar el número correlativo de la transacción: ' Sub Procedimiento para mostrar el numero correlativo del registro a crear. Public Sub InvestigarCorrelativo() Try con.Open() Dim sql As New SqlServerCe.SqlCeCommand("Select max(IdViajes) + 1 IdViajes from Viajes", con) Dim viajereader As SqlServerCe.SqlCeDataReader = sql.ExecuteReader() If viajereader.Read = True Then If viajereader("IdViajes") Is DBNull.Value Then Me.TxtIdViaje.Text = 1 Else Me.TxtIdViaje.Text = viajereader("IdViajes").ToString End If End If Catch ex As Exception MessageBox.Show("Error" & vbCrLf & ex.Message, "Agencia de Viajes") Finally con.Close() End Try End Sub
Ahora vamos a diseñar el código para el botón nuevo: Private Sub BtnNuevo_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnNuevo.Click Me.GroupBox1.Enabled = True Call InvestigarCorrelativo() Me.TxtAtraccion.Focus() End Sub Compete que le asignemos el formato moneda al costo en el texbox txtcosto. Private Sub TxtCosto_LostFocus(ByVal sender As Object, ByVal e As System.EventArgs) Handles TxtCosto.LostFocus If Me.TxtCosto.TextLength > 0 Then Me.TxtCosto.Text = FormatCurrency(Me.TxtCosto.Text, 2) Else Me.TxtCosto.Text = FormatCurrency(0, 2) End If End Sub Ahora vamos a escribir el codigo en el botón buscar que va a mandar a llamar al formulario que nos permitirá seleccionar las atracciones turísticas. Private Sub BtnBuscar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnBuscar.Click FrmBuscarAtraccion.Show() End Sub Cuando se nos aparece el formulario para seleccionar las atracciones disponibles ahora vamos a crear el sub procedimiento que hace la consulta a la base de datos. '' Sub Procidimiento para consultar los datos de las atracciones en la base de datos. Public Sub ConsultarAtracciones() Me.LsvListaAtracciones.Items.Clear() Try Dim sql As String = "Select a.AtraccionID, a.NombreAtraccion, b.NombreCategoria, c.NombreCiudad " _ & "From Atraccion a inner join Categoria b on a.CategoriaID = b.CategoriaID " _ & "inner join Ciudad c on a.CiudadID = c.CiudadID " _ & "Order by a.AtraccionID Asc" con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con) Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader()
While Lector.Read With Me.LsvListaAtracciones.Items.Add(Lector.Item("AtraccionID").ToString) .SubItems.Add(Lector.Item("NombreAtraccion").ToString) .SubItems.Add(Lector.Item("NombreCategoria").ToString) .SubItems.Add(Lector.Item("NombreCiudad").ToString) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Ahora vamos a crear el código donde se va a llamar al formulario que es en el evento load del formulario frmbusquedaatracciones. Private Sub FrmBuscarAtraccion_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load Call ConsultarAtracciones() End Sub Continuamos con el código donde damos doble clic en el registro del listview para que pase los datos seleccionados al formularios donde estamos armando los paquetes turísticos. Private Sub LsvListaAtracciones_DoubleClick(ByVal sender As Object, ByVal e As System.EventArgs) Handles LsvListaAtracciones.DoubleClick FrmViajes.TxtIdAtraccion.Text = Me.LsvListaAtracciones.FocusedItem.Text FrmViajes.TxtAtraccion.Text = Me.LsvListaAtracciones.FocusedItem.SubItems(1).Text Me.Close() End Sub Ahora proseguimos con el desarrollo del código del sub procedimiento de GuardarViajes. ' Sub Procedimiento que nos permitirá ingresar datos en la base de datos. Public Sub GuardarViajes() Try Dim Guardar As String Guardar = "Insert into Viajes (IdViajes, AtraccionID, FechaViaje, Costo) " Guardar &= "Values (@IdViajes, @AtraccionID, @FechaViaje, @Costo) "
Dim ComandoGuardar As New SqlServerCe.SqlCeCommand(Guardar, con) ComandoGuardar.Parameters.Add("@IdViajes", SqlDbType.Int).Value = Val(Me.TxtIdViaje.Text) ComandoGuardar.Parameters.Add("@AtraccionID", SqlDbType.Int).Value = Val(Me.TxtIdAtraccion.Text) ComandoGuardar.Parameters.Add("@FechaViaje", SqlDbType.DateTime).Value = Me.DtpFechaViaje.Value.Date ComandoGuardar.Parameters.Add("@Costo", SqlDbType.Money).Value = CDbl(Me.TxtCosto.Text) con.Open() ComandoGuardar.ExecuteNonQuery() MessageBox.Show("Paquete turistico almacenado satisfactoriamente", "Agencia de Viajes", MessageBoxButtons.OK, MessageBoxIcon.Information) con.Close() Call limpiar()
Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Creamos el código del botón guardar. Sub limpiar() Me.TxtIdViaje.Text = Nothing Me.TxtIdAtraccion.Text = Nothing Me.TxtAtraccion.Text = Nothing Me.TxtCosto.Text = Nothing Me.GroupBox1.Enabled = False Me.BtnGuardar.Enabled = False End Sub Y Ahora para terminar la codificación de ésta interfaz creamos el código que va en el botón guardar.
Private Sub BtnGuardar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnGuardar.Click Call GuardarViajes() End Sub
Ahora vamos a diseñar la interfaz de lo que va ser la pantalla de agregar turistas (clientes) a los paquetes turísticos. Hay que aclarar que en la base de datos la clave primaria de detalles de viaje no tiene identity true por ende vamos a crear el sub procedimiento que nos permita ir mostrando el numero correlativo de cada transacción y así poderlo almacenar en la base de datos. El proceso que vamos a realizar para llegar a registrar clientes para “x” paquete turísticos, primero
vamos a ejecutar una consulta que nos muestra los paquetes turísticos disponibles, de esta forma vamos a obtener los datos del paquete turístico. La interfaz de la consulta es la siguiente:
Descripción de las propiedades de los controles utilizados Label 1: Text: Listado de Paquetes Turísticos disponibles en el sistema: ListView (Lv1):
Columnas. 1---Name: IdViajes Text: Id Viajes Width: 60
2---Name: AtraccionID Text: Id Atraccion Width: 100 3---Name: NombreAtraccion Text: Nombre Atraccion Width: 200
4---Name: FechaViaje Text: Fecha Viaje Width: 80
5---Name: Costo Text: Costo Viaje Width: 80
En primer lugar vamos a crear el código para que realice la consulta de los viajes disponibles.
'' Sub Procidimiento para consultar los datos de los paquetes turisticos disponibles. Public Sub ConsultarViajes() Me.LsvPaquetesTuristicos.Items.Clear() Try Dim sql As String = "Select a.IdViajes, b.AtraccionID, b.NombreAtraccion,convert(nchar(13), a.FechaViaje, 103) as FechaViaje, a.Costo " _ & "From viajes a inner join atraccion b on a.atraccionID = b.atraccionID " _ & "Order by a.Idviajes asc" con.Open() Dim ConsultaC As New SqlServerCe.SqlCeCommand(sql, con) Dim Lector As SqlServerCe.SqlCeDataReader = ConsultaC.ExecuteReader() While Lector.Read With Me.LsvPaquetesTuristicos.Items.Add(Lector.Item("IdViajes").ToString) .SubItems.Add(Lector.Item("AtraccionID").ToString) .SubItems.Add(Lector.Item("NombreAtraccion").ToString) .SubItems.Add(Lector.Item("FechaViaje").ToString) .SubItems.Add(FormatCurrency(Lector.Item("Costo").ToString, 2)) End With End While Catch ex As Exception MessageBox.Show(ex.Message) Finally con.Close() End Try End Sub Si es un poquito curioso ha de notar que ésta consulta sql no se diseñó de forma sencilla, sino que se utilizó la función convert, ya que en la base de datos almacena un datetime y yo solo quería la fecha entonces la modifico con el convert para que me de el formato que yo deseo convert(nchar(13), a.FechaViaje, 103). El formato lo decide el numero 103. Teniendo ya funcional la consulta que nos listas los viajes, ahora vamos a crear el código que va llevar el evento doble clic del listview para llevar los datos que necesitamos al formulario de agregar clientes (turistas) a los paquetes. Vuelvo a recordar que ésta fue una forma rápida de analizar para proveerles una material que les sirviera como una herramienta de apoyo, para el desarrollo de su proyecto de clase.