Formulario Splash 2,
(en VB.NET)

[Una agenda realizada en VB.NET]

Fecha: 06 de julio de 2004
Autor: Antonio Cuesta Garcia ACUESTA@terra.es

 

.

Introducción:
Este articulo, es una segunda parte del articulo "Formulario Splash", publicado en este mismo sitio, donde se realiza la misma agenda, pero esta vez en VB.NET, ya que hay gente interesada en tener el código fuente de la misma en dicho leguaje de programación.

Como en el articulo anterior me centre mas en explicar la creación del formulario "Splash", y el resto de la agenda lo deje para la observación de los interesados en el código, en este aprovecho para dejar un poco de lado la creación del formulario Splash (que ya se trato muy extensamente en el citado articulo y el interesado puede consultar el código fuente en VB que se adjunta al articulo), y en este me centrare de lleno en la agenda en si.

Desarrollo de una agenda aplicando "programación en tres capas" (Interfaz de usuario, Capa de negocios, Capa de acceso a datos).



Antes de nada me gustaría explicar la idea lo mas detalladamente posible sobre que es lo que se pretende, así se entenderá mejor el código y el por que se utiliza la programación en tres capas en esta solución.

Lo primero que hay que tener claro es que una agenda es un programa que nos servirá para guardar información relevante sobre personas, siendo lo primero que nos tenemos que plantear cuales son los datos "relevantes" o "importantes" para nosotros de una persona, y como guardaremos esta información (es decir el tipo de soporte físico, fichero de texto plano, SQL Server, fichero de ACCESS, etc.)

Los datos que yo utilizare serán los siguientes:

Dato Tipo Long.
Nombre String 40
Dirección String 40
Población String 40
Provincia String 35
Cód. Postal String 5
Teléfono String 12
EMail String 60

El soporte físico será un fichero XML, que se llamara "datos.xml", y aquí es donde la aplicación de la "programación en tres capas" es interesante, ya que en la capa de datos, pondremos todo el código relativo al trabajo con el soporte físico, pudiendo cambiar esta clase por otra que implemente los mismos datos en un fichero ACCESS, o en una base de datos SQL Server, por ejemplo.

Solo me falta indicar que de estos campos, yo utilizare el Nombre como campo clave, si el soporte fuera otro, como un fichero ACCESS, pudiera optar por incluir un campo autonumerico como clave, pero como para este ejemplo no se guardan datos como el D.N.I., u otros que pudieran resultar mas identificativos utilizo este, ya que si hay dos Pepe, nos interesaría poderles diferenciar de alguna forma poniendo sus apellidos, o añadiendo números: "Pepe 1", "Pepe 2", etc. (Como la agenda de un teléfono móvil).

Con las ideas claras, ya se puede dividir el programa, en la capa de acceso a datos he creado una clase llamada "FichAgenda", que contiene la funcionalidad relativa al trabajo con el fichero datos.xml, después la Lógica de negocio, solo tiene una clase que es "Persona" y que contiene tanto los datos de la persona como la utilidad básica de crear modificar, borrar, etc. y llama a la clase FichAgenda para independizarla del soporte físico, después el Interfaz de usuario que utiliza la clase Persona, que en este caso es un Windows Form.

La capa de acceso a datos.

Primero definimos como funcionara nuestra aplicación, y en base a lo que queremos así, crearemos nuestra clase FichAgenda.

Para que nuestra agenda sea mas rápida, la idea es la siguiente, cuando comience nuestra aplicación cargara todos los datos del fichero "datos.xml" en un DataSet, y después para guardar los mismos en dicho fichero lo mejor es sobrescribir dicho fichero con los datos que tenemos en el DataSet, que serán los correctos, para eso se crean los métodos "CargarDatos" y "GuardarDatos", en esta clase también se incluye el formato del fichero y de esto se encarga un método privado al que llamo "Estructura", y que retorna como resultado el DataTable "Contactos".

A continuación vemos los tres métodos, que son Shared (static en C#), como todos los métodos y propiedades de esta clase, para que no tengamos que crear una instancia de dicha clase.


Private Shared _dtCargados As Boolean = False
Private Shared _ds As DataSet

.
.

Public Shared Sub CargarDatos()
    _ds = New DataSet                ' Creamos una nueva instancia de un DataSet
    _ds.Tables.Add(Estructura())     ' Le añadimos la estructura


    Try
        _ds.ReadXml("datos.xml")     ' Leemos los datos del fichero datos.xml
    Catch
        Console.WriteLine("Error al leer el fichero de datos.")
    Try
    _dtCargados = True

End Sub

Public Shared Sub GuardarDatos()
    Dim miFS As New FileStream("datos.xml",FileMode.Create)
    Dim XmlW As New XmlTextWriter(miFS, System.Text.Encodign.Unicode)
    _ds.WriteXml(XmlW)     ' Guardamos los datos
    XmlW.Close()
End Sub

.
.

Private Shared Function CargarDatos() As DataTable
    Dim dt As New DataTable("Contactos")
    Dim dc As DataColumn

    cd = New DataColumn("Nombre",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("Direccion",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("Poblacion",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("Provincia",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("CodPostal",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("Telefono",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)
    cd = New DataColumn("EMail",System.Type.GetType("System.String"))
    dt.Columns.Add(dc)

    Return dt
End Function

Estos dos métodos y la función "Estructura" son lo mas destacado en lo que respecta a la funcionalidad del fichero "datos.xml", pero esta clase añade, las funciones BorrarReg, Datos (que devuelve un DataTable con todos los registros), MirarPersona, ModificarReg y NuevoReg, que tanto por sus nombres como por lo sencillo de los mismos aconsejo consultar en el programa.

Solo añadiré a esta explicación sobre la capa de acceso a datos que es importante la propiedad de solo lectura DatosCargados, que sirve para controlar (como su nombre indica), si ya están los datos cargados en el DataSet privado "_ds", ya que en caso contrario la clase no funcionaria correctamente hasta que se llame al método "CargarDatos".

La Lógica de negocio.

Como ya he indicado esta capa solo tendrá una clase que será "Persona", y que será la clase que proporcionara toda la utilidad sobre las personas de nuestra agenda al Interfaz de usuario, ya que esta ultima capa (el Interfaz de usuario), no puede tener acceso a la capa de acceso a datos.

Lo primero que tenemos que tener claro sobre la clase Persona es que depende de la clase FichAgenda, para su buen funcionamiento, por lo tanto una idea que hay que tener clara es que lo primero que ha de realizar es una llamada al método CargarDatos de la misma, una buena idea seria llamarlo desde el constructor de la clase, ya que esto nos aseguraría que al crear una instancia de la misma se llamase a dicho método, pero como la idea inicial era que al iniciar el programa un subproceso se encargara de realizar la carga de los datos, cree un método Shared llamado "MirarContactos", que se encarga de esto.

Hay otra propiedad Shared, que devuelve un DataTable, con los datos y que yo uso para asignar la propiedad DataSource del DataGrid1 que hay en el Interfaz de usuario, que comprueba si se han cargado los datos, y en caso contrario llama al citado método "CargarDatos" de FichAgenda, a continuación vemos el código.

Public Shared Sub MirarContactos()
    FichAgenda.CargarDatos()
End Sub

Public Shared ReadOnly Property Contactos()As DataTable
    Get
        If Not FichAgenda.DatosCargados Then
            FichAgenda.CargarDatos()
        End If
        Return FichAgenda.Datos
    End Get
End Sub

Además de estos métodos, esta clase implementa las Funciones Añadir, Borrar, Mirar y Modificar, que sirven para trabajar con la persona activa, excepto Añadir (de ahí que la haya declarado como Shared) que crea una nueva persona, Mirar es la función que carga en la instancia los datos de la persona con la que queremos trabajar.

Public Function Mirar(ByVal Nombre As String) As Boolean
    If Nombre <> String.Empty Then
        Dim dr As DataRow = FichAgenda.MirarPersona(Nombre)

        If Not IsNothing(dr) Then
            _nombre = dr("Nombre").ToString()
            _direccion = dr("Direccion").ToString()
            _poblacion = dr("Poblacion").ToString()
            _provincia = dr("Provincia").ToString()
            _codPostal = dr("CodPostal").ToString()
            _telefono = dr("Telefono").ToString()
            _eMail = dr("EMail").ToString()

            _modificado = False
            Return True
        Else
            If _nombre <> String.Empty Then
                _nombre=String.Empty
            End If
            Return False
        End If
    Else
        Return False
    End If
End Function

Public Function Modificar() As Boolean
    If (_modificado) And (_nombre <> String.Empty) Then
        Dim los_datos(7) As String

        los_datos(0) = _nombre
        los_datos(1) = _direccion
        los_datos(2) = _poblacion
        los_datos(3) = _provincia
        los_datos(4) = _codPostal
        los_datos(5) = _telefono
        los_datos(6) = _eMail

        If FichAgenda.ModificarReg(los_datos) = Then
            _modificado = False
            Return True
        Else
            Return False
        End If
    Else
        Return False
    End If
End Function

Public Shared Function Añadir(ByVal Nombre As String) As Boolean
    Return FichaAgenda.NuevoReg(Nombre)
End Function

Public Function Borrar() As Boolean
    If _nombre <> String.Empty Then
        If (FichAgenda.BorrarReg(_nombre)) Then
            _nombre = String.Empty
            Return True
        Else
            Return False
        End If
    Else
        Return False
    End If
End Function

Después tenemos como propiedades todos los datos de la persona, además de DatosModificados, que nos indica si se ha realizado alguna modificación en algún campo; para saber si tenemos cargada una persona correctamente en nuestra instancia yo utilizo el campo Nombre, ya que al ser el campo clave no puede estar vacío, por eso su propiedad es de solo lectura (a diferencia de los demás), así, solo con ver si dicho campo esta vacío (String.Empty) podemos saber si nuestra instancia contiene los datos de una persona.

Private _nombre As String = String.Empty
Private _direccion As String = String.Empty
Private _poblacion As String = String.Empty
Private _provincia As String = String.Empty
Private _codPostal As String = String.Empty
Private _telefono As String = String.Empty
Private _eMail As String = String.Empty

Private _modificado As Boolean = False

.
.

Public ReadOnly Property Nombre() As String
    Get
        Return _nombre
    End Get
End Property

Public Property Direccion() As String
    Get
        Return _direccion
    End Get
    Set(ByVal Value As String)
        _direccion = Value
        _modificado = True
    End Set
End Property

Public Property Poblacion() As String
    Get
        Return _poblacion
    End Get
    Set(ByVal Value As String)
        _poblacion = Value
        _modificado = True
    End Set
End Property

Public Property Provincia() As String
    Get
        Return _provincia
    End Get
    Set(ByVal Value As String)
        _provincia = Value
        _modificado = True
    End Set
End Property

Public Property CodPostal() As String
    Get
        Return _codPostal
    End Get
    Set(ByVal Value As String)
        _codPostal = Value
        _modificado = True
    End Set
End Property

Public Property Telefono() As String
    Get
        Return _telefono
    End Get
    Set(ByVal Value As String)
        _telefono = Value
        _modificado = True
    End Set
End Property

Public Property EMail() As String
    Get
        Return _eMail
    End Get
    Set(ByVal Value As String)
        _eMail = Value
        _modificado = True
    End Set
End Property

Public ReadOnly Property DatosModificados() As Boolean
    Get
        Return _modificado
    End Get
End Property

Con esto creo que esta suficientemente explicada la clase Persona.

El interfaz de usuario.

El interfaz de usuario ya lo dejo para la observación de los interesados, directamente en el código fuente del articulo.

Bueno, pues esta es una pequeña explicación, y el código fuente en VB.NET para los interesados que lo pidieron (el de C# esta en el articulo anterior), un saludo a todos y espero que haya sido útil.



ir al índice

Fichero con el código de ejemplo: ACUESTA_FormularioSplashVB.zip - Tamaño 94,7 KB

Índice de la sección dedicada a punto NET (en el Guille)