Archivo del Autor: Pedro Ávila Núñez

Comunicar Formularios usando Easy.MessageHub

Easy.MessageHub es un framework que por dentro viene implementado el patrón Event Aggregator, que justamente basandose en eventos permite una comunicación desacoplada entre formularios sin relación directa en nuestra aplicación.

EventAggregator: Por el nombre es fácil decir que los agregados de eventos un Publisher/Subscriber trabajan con EventAggregator como un centro cuya tarea consiste en agregar todos los mensajes publicados y enviar el mensaje a los suscriptores interesados.

EventAggregator

Antes de comenzar hay que instalar Easy.MessageHub ejecutar el siguiente comando en la consola de administación de paquetes.

Install-Package Easy.MessageHub

Una vez instalado pasamos a crear una clase como contrato para dichos eventos.

public class VariableSelected
     {
         public int Codigo { get; set; }
         public string StrValor { get; set; }
     }

Desde el formulario hijo implementamos MessageHub

public partial class FrmBusqueda : Form
     {
        
         private readonly IMessageHub _eventHub;
         public FrmBusqueda(string title, EnumAsignacionTablas t)
         {
             _titulo = title;
             _table = t;
             CompleteEvent.Complete += CompleteEvent_Complete;
             InitializeComponent();
         }

        public FrmBusqueda(string title, EnumAsignacionTablas t, IMessageHub evenHub) : this(title, t)
         {
             _eventHub = evenHub;
         }

private void ObtenerId()
         {
             if (dgvBusqueda.Rows.Count > 0)
             {
                 if (dgvBusqueda.CurrentRow != null)
                 {
                     _idRow = Convert.ToInt32(dgvBusqueda.CurrentRow.Cells[0].Value);
                     _desRow = Convert.ToString(dgvBusqueda.CurrentRow.Cells[1].Value);
                 }
                 _eventHub.Publish(new VariableSelected {Codigo = _idRow, StrValor = _desRow});
             }
         }

El padre recibe los datos y los procesa

private void btnBuscarColor_Click(object sender, EventArgs e)
         {
             var argNombreEntidad = new ConstructorArgument(“title”, StrColour.NameEntity);
             var argT = new ConstructorArgument(“t”, EnumAsignacionTablas.Colour);
             var frm = CompositionRoot.Resolve<FrmBusqueda>(argNombreEntidad, argT); 
             _eventHub.Subscribe<VariableSelected>(OnColorSelected);
             frm.ShowDialog();
         }

        private void OnColorSelected(VariableSelected colorEvent)
         {
             if (colorEvent.Codigo != 0 && !string.IsNullOrEmpty(colorEvent.StrValor))
             {
                 if (DetalleItemColour.Count != 1)
                 {
                     var entity = new Colour()
                     {
                         ColourId = colorEvent.Codigo,
                         Nombre = colorEvent.StrValor
                     };
                     _detalleColour.Add(entity);
                     dgvColor.AutoGenerateColumns = false;
                     dgvColor.DataSource = DetalleItemColour;
                    
                     //De suscribir
                     _eventHub.ClearSubscriptions();
                 }
                 else
                 {
                     MessageBoxEx.EnableGlass = false;
                     MessageBoxEx.Show(this, “Solo se permite un solo Color”, StrColour.NameEntity,
                         MessageBoxButtons.OK, MessageBoxIcon.Information);
                     vBool = false;
                     colorEvent.Codigo = 0;
                     colorEvent.StrValor = String.Empty;
                 }
             }
         }

Cargar combobox vinculado a una tabla

 

Hola, en esta oportunidad voy a mostrar como cargar un ComboBox vinculado a una tabla, en el cual nos conectaremos a una base de datos para poder obtener los registros almacenados en dicha tabla.

Estoy usando Visual Studio 2013 y SQL Server 2014, pero voy a poner el script para crear la base de datos y la tabla en el script estoy usando un INSERT multiple el cual se puede realizar desde SQL Server 2008 hacia delante.

CREATE DATABASE Prueba
GO
USE Prueba
GO
CREATE TABLE Usuario
(
Id VARCHAR(6) NOT NULL PRIMARY KEY,
Descripcion VARCHAR(80)
)
GO
INSERT INTO Usuario(Id, Descripcion)
VALUES('000001', 'MIGUEL'), ('000002', 'JOSE'), ('000003', 'PABLO'),
('000004', 'MARTIN'), ('000005', 'JOSTIN'), ('000006', 'ISMAEL')

GO

Teniendo la base de datos con los registros, pasamos a crear nuestro proyecto y codificar para poder cargar el ComboBox con datos vinculados a una tabla.

Lo primero que tenemos que hacer es crear la conexión a la base de datos para eso usaremos el archivo App.conf el cual es un xml.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<connectionStrings>
<add name="default" connectionString="Data Source=.;Initial Catalog=Prueba;User ID=sa;Password=xxx"/>
</connectionStrings>
</configuration>

Paso siguiente Creamos la conexión a la base de datos, en el cual tenemos que agregarle una referencia System.Configuration

Referencia

Configuracion

C#

using System.Configuration; // Se agrega esta referencia para trabajar con ConfigurationManager.
using System.Data.SqlClient; // Se agrega esta referencia para trabajar con SQL Server.

namespace WindowsFormsUI
{
public class Conexion
{
public static SqlConnection Conectar(string con)
{
try
{
string strCon = ConfigurationManager.ConnectionStrings["default"].ToString();
SqlConnection cn = new SqlConnection(strCon);
return cn;
}
catch (Exception ex)
{
throw new ArgumentException("Error de Conexión", ex);
}
}
}
}

VB.NET

Imports System.Data.SqlClient
Imports System.Configuration
Public Class Conexion
Public Shared Function Conectar(con As String) As SqlConnection
Try
Dim strCon As String = ConfigurationManager.ConnectionStrings("default").ConnectionString()
Dim cn As New SqlConnection(strCon)
Return cn
Catch ex As Exception
Throw New ArgumentException("Error de Conexion", ex)
End Try
End Function
End Class

Pasamos a hacer el mapping tal cual esta en la tabla creando las entidades.

C#

namespace WindowsFormsUI
{
public class UsuarioEntity
{
public string Id { get; set; }
public string Descripcion { get; set; }
}
}

VB.NET

Public Class UsuarioEntity
Public Property Id As String
Public Property Descripcion As String

End Class

Pasamos a trabajar con el repositorio de datos para persistir contra la base de datos y obtener los datos que vamos a cargar en nuestro ComboBox.

C#

namespace WindowsFormsUI
{
public class UsuarioRepository
{
public static List<UsuarioEntity> listUsu()
{
using(SqlConnection cn = Conexion.Conectar("default"))
{
cn.Open();
using(SqlCommand cmd = cn.CreateCommand())
{
cmd.CommandText = "SELECT Id, Descripcion FROM Usuario";
List<UsuarioEntity> usuario = new List<UsuarioEntity>();
using(SqlDataReader reader = cmd.ExecuteReader())
{
while(reader.Read())
{
UsuarioEntity u = new UsuarioEntity()
{
Id = Convert.ToString(reader["Id"]),
Descripcion = Convert.ToString(reader["Descripcion"])
};
usuario.Add(u);
}
}
return usuario;
}

}
}

public static List<UsuarioEntity> listUsuario()
{
List<UsuarioEntity> listaItem = listUsu();
listaItem.Insert(0, new UsuarioEntity() { Id = Convert.ToString(0), Descripcion = "<Seleccionar>" });
return listaItem;
}

}
}

VB.NET

Imports System.Data
Imports System.Data.SqlClient
Public Class UsuarioRepository
Public Shared Function listUsu() As List(Of UsuarioEntity)
Using cn As SqlConnection = Conexion.Conectar("default")
cn.Open()
Using cmd As SqlCommand = cn.CreateCommand
cmd.CommandText = "SELECT Id, Descripcion FROM Usuario"
Dim usuario As New List(Of UsuarioEntity)
Using reader As SqlDataReader = cmd.ExecuteReader
While reader.Read
Dim u As New UsuarioEntity
u.Id = Convert.ToString(reader("Id"))
u.Descripcion = Convert.ToString(reader("Descripcion"))
usuario.Add(u)
End While
End Using
Return usuario
End Using
End Using
End Function

Public Shared Function listUsuario() As List(Of UsuarioEntity)
Dim listaItem As List(Of UsuarioEntity) = listUsu()
listaItem.Insert(0, New UsuarioEntity() With {
.Id = Convert.ToString(0), _
.Descripcion = "<Seleccionar>" _
})
Return listaItem
End Function
End Class

Pasamos a llamar los métodos desde el formulario que contiene nuestro ComboBox.

C#

namespace WindowsFormsUI
{
public partial class frmUsuario : Form
{
public frmUsuario()
{
InitializeComponent();
}

private void frmUsuario_Load(object sender, EventArgs e)
{
LOADComboUsuario();
}

void LOADComboUsuario()
{
List<UsuarioEntity> list = Usuario.listUsuario();
cboUsuario.DataSource = list;
cboUsuario.ValueMember = "Id";
cboUsuario.DisplayMember = "Descripcion";
}
}
}

VB.NET

Public Class frmUsuario

Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
LOADComboUsuario()
End Sub

Sub LOADComboUsuario()
Dim list As List(Of UsuarioEntity) = Usuario.listUsuario
cboUsuario.DataSource = list
cboUsuario.ValueMember = "Id"
cboUsuario.DisplayMember = "Descripcion"
End Sub
End Class

Al ejecutar nuestro proyecto tendremos cargado nuestro ComboBox así como muestra la imagen.

Combo

Proyecto C#               Proyecto VB.NET

Entity Framework 6 operaciones CRUD

 

Entity Framework es un potente ORM creado por Microsoft que facilita el trabajo del mapeo a las entidades y facilita la implementación de la capa de datos usando Linq to Entities. Entity Framework tiene varios enfoques como, Code First, Model First, Database First.

Code First, es un enfoque mas de Entity Framework que permite crear una base de datos a partir de código(C#, VB.NET), por defecto se utiliza el nombre de nuestras clases y correspondientes propiedades para crear nombres de tablas y campos.

Model First, le da la posibilidad de diseñar toda la lógica del negocio, le permite crear un modelo nuevo mediante Entity Framework Designer y después genera un esquema de la base de datos a partir del modelo.

Database First, el modelo conceptual se crea a partir de una base de datos existente, el cual se almacena en una archivo .edmx y este se podrá ver y editar en un diseñador, para actualizar nuevos cambios que surjan en nuestra base de datos.

En esta ocasión voy a usar DataBase First pero antes se debe crear una base de datos de prueba.

CREATE DATABASE PruebaEF
GO
USE PruebaEF
GO
CREATE TABLE [dbo].[Personal](
 [Id] [varchar](6) NOT NULL,
 [Nombre] [varchar](80) NULL,
 [Direccion] [varchar](100) NULL,
 [Telefono] [varchar](9) NULL,
 [lEstado] [smallint] NULL,
 CONSTRAINT [PK_Personal] PRIMARY KEY CLUSTERED
(
 [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

Para este ejemplo estoy usando Visual Studio 2013 y SQL 2014.

Una vez teniendo la base de datos creada pasamos a crear una solución distribuida en una arquitectura de 3 capas, Presentación(Proyecto Windows Forms),  Dominio(Proyecto Class Library), Persistencia Datos(Proyecto Class Library), se hace las referencia entre capas Persistencia en Dominio, Persistencia y Dominio en Presentación, referencio Persistencia en Presentación por que el mapeo a la infraestructura de la DB esta en esa capa solo por eso, pero la lógica de la aplicación va en el Dominio.

Se instala en la capa de Persistencia y Presentación Entity Framework desde Nuguet, hecho eso se agrega un nuevo elemento desde el proyecto de Persistencia, ADO.NET Entity Data Model.

entity data model

Ahora nos conectamos a la base de datos para obtener el modelo.

conectando a la db

Seleccionamos las tablas que se requieren para el modelo.

escojer las tablas

Escogemos el Framework a trabajar en mi caso lo dejo como esta.

escoger el EF

Obtenemos el modelo.

modelo

Y también tenemos el mapping de la infraestuctura de la DB.

//------------------------------------------------------------------------------
// <auto-generated>
// Este código se generó a partir de una plantilla.
//
// Los cambios manuales en este archivo pueden causar un comportamiento inesperado de la aplicación.
// Los cambios manuales en este archivo se sobrescribirán si se regenera el código.
// </auto-generated>
//------------------------------------------------------------------------------

namespace Prueba.PersistenciaDatos.Modelo
{
 using System;
 using System.Collections.Generic;

 public partial class Personal
 {
 public string Id { get; set; }
 public string Nombre { get; set; }
 public string Direccion { get; set; }
 public string Telefono { get; set; }
 public Nullable<short> lEstado { get; set; }
 }
}

Ya podemos comenzar a trabajar comenzando con la implementación vamos a ubicar el context que es el que se conecta a la base de datos para poder persistir contra ella.

context

Esto se encuentra ubicado en el Model1.Context, voy a implementar la capa de persistencia usando linq to entities, me olvidaba agregar la referencia System.Data.Entity

using Prueba.PersistenciaDatos.Modelo;
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;

namespace Prueba.PersistenciaDatos
{
 public class PersonalRepository
 {

 public List<ModeloMinimo.PersonalMinimalModel> GetPersonal()
 {
 using(var context = new PruebaEFEntities())
 {
 return (from p in context.Personal
 select new ModeloMinimo.PersonalMinimalModel
 {
 Id = p.Id,
 Nombre = p.Nombre
 }).ToList();
 }
 }

 public string GenerarCodigo()
 {
 using(var context = new PruebaEFEntities())
 {
 int codigo;
 var ultimoId = Convert.ToInt32(context.Personal.Max(x => x.Id)) + Convert.ToInt32(1);
 codigo = ultimoId;
 return string.Format("{0:000000}", codigo);
 }
 }

 public bool Existe(string codigo)
 {
 using(var context = new PruebaEFEntities())
 {
 int resultado = context.Personal.Where(x => x.Id == codigo).Count();
 if (resultado == 0)
 return false;
 else
 return true;
 }
 }
 public Personal Buscar(string codigo)
 {
 using(var context = new PruebaEFEntities())
 {
 var strSQL = from p in context.Personal
 where p.Id == codigo
 select p;
 return strSQL.First();
 }
 }

 public void Guardar(Personal model)
 {
 try
 {
 using(var context = new PruebaEFEntities())
 {
 context.Personal.Add(model);
 context.SaveChanges();
 }
 }
 catch (Exception ex)
 {
 throw new Exception("No se puede guardar el registro", ex);
 }
 }

 public void Actualizar(Personal model)
 {
 try
 {
 using(var context = new PruebaEFEntities())
 {
 context.Entry(model).State = EntityState.Modified;
 context.SaveChanges();
 }
 }
 catch (Exception ex)
 {
 throw new Exception("No se puede actualizar el registro", ex);
 }
 }

 public void Eliminar(string codigo)
 {
 using(var context = new PruebaEFEntities())
 {
 var entities = (from p in context.Personal
 where p.Id == codigo
 select p).Single();
 context.Personal.Remove(entities);
 context.SaveChanges();
 }

 }

 }
}

Implementando el dominio en el cual uso una técnica para desacoplar la capa de Presentación con la capa de Dominio.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Prueba.PersistenciaDatos;
using System.Linq.Expressions;

namespace Prueba.Dominio
{
 public class Personal
 {
 public string MensajeLogica;
 public string MensajeError;

 PersonalRepository personal = new PersonalRepository();

 public List<PersistenciaDatos.ModeloMinimo.PersonalMinimalModel> GetPersonal()
 {
 return personal.GetPersonal();
 }

 public PersistenciaDatos.Modelo.Personal Buscar(string codigo)
 {
 return personal.Buscar(codigo);
 }

 public void Guardar(PersistenciaDatos.Modelo.Personal model)
 {
 BusinessException.Clear();
 if (string.IsNullOrEmpty(model.Nombre)) BusinessException.Add("Debe ingresar el nombre");

 if(BusinessException.Count() == 0)
 {
 if(string.IsNullOrEmpty(model.Id))
 model.Id = personal.GenerarCodigo();

 try
 {
 if(personal.Existe(model.Id))
 {
 personal.Actualizar(model);
 MensajeLogica = "Registro actualizado";
 }
 else
 {
 personal.Guardar(model);
 MensajeLogica = "Registro guardado";
 }
 }
 catch (Exception ex)
 {
 BusinessException.Add(ex.Message);
 }

 }
 }

 public void Eliminar(string codigo)
 {
 personal.Eliminar(codigo);
 }

 }
}

Implementando la capa de Presentación, se debe copiar el app.config de la capa de Persistencia a la Presentación.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Prueba.PersistenciaDatos;
using Prueba.Dominio;

namespace Prueba.WindowsUI
{
 public partial class frmPersonal : Form
 {
 private string strCodigo;

 Dominio.Personal personal = new Dominio.Personal();

 public frmPersonal()
 {
 InitializeComponent();
 }

 private void frmPersonal_Load(object sender, EventArgs e)
 {
 LoadDGVPersonal();

 }

 private void btnGuardar_Click(object sender, EventArgs e)
 {
 PersistenciaDatos.Modelo.Personal model = new PersistenciaDatos.Modelo.Personal();
 model.Id = lblCodigo.Text;
 model.Nombre = txtNombre.Text;
 model.Direccion = txtDireccion.Text;
 model.Telefono = txtTelefono.Text;
 model.lEstado = Convert.ToInt16(chkEstado.Checked ? "1" : "0");
 personal.Guardar(model);
 LoadDGVPersonal();
 }

 void LoadDGVPersonal()
 {
 List<PersistenciaDatos.ModeloMinimo.PersonalMinimalModel> list = personal.GetPersonal();
 dgvPersonal.AutoGenerateColumns = false;
 dgvPersonal.DataSource = list;
 }

 void ObtenerId()
 {
 strCodigo = Convert.ToString(dgvPersonal.CurrentRow.Cells[0].Value);
 }

 void Buscar()
 {
 if(strCodigo != string.Empty)
 {
 PersistenciaDatos.Modelo.Personal model = personal.Buscar(strCodigo);
 lblCodigo.Text = model.Id;
 txtNombre.Text = model.Nombre;
 txtDireccion.Text = model.Direccion;
 txtTelefono.Text = model.Telefono;
 chkEstado.Checked = Convert.ToBoolean(model.lEstado);
 }
 }

 void Eliminar()
 {
 ObtenerId();
 string msg = string.Format("Se va a ELIMINAR el registro: {0} {1} {0} Código: {2} {0} Nombre: {3}",
 Environment.NewLine,
 new string('-', 50), dgvPersonal.CurrentRow.Cells[0].Value,
 dgvPersonal.CurrentRow.Cells[1].Value);

 if (MessageBox.Show(msg, "Personal", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == System.Windows.Forms.DialogResult.Yes)
 {
 personal.Eliminar(strCodigo);
 LoadDGVPersonal();
 }
 }

 private void dgvPersonal_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
 {
 ObtenerId();
 Buscar();
 tabControl1.SelectedTab = tabPage2;
 }

 private void frmPersonal_KeyDown(object sender, KeyEventArgs e)
 {
 if(e.KeyCode == Keys.F7)
 {
 Eliminar();
 }
 }

 }
}

Al ejecutar la aplicación queda de esta manera.

frmPersonal datos

lista

Adjunto el proyecto para que lo puedan descargar, el próximo post será Inversión de Control IoC con Ninject.

Proyecto C#

 

 

 

 

 

 

 

Crystal Reports con Store Procedure

 

Hola en esta ocasión mostrare como implementar un reporte con store procedure, pero con un reporte creado con crystal reports 8 y teniendo una ruta de ubicación, que permite tener el reporte fuera del IDE de visual studio, esto nos da la facilidad de darle mantenimiento al reporte sin necesidad de crear un nuevo ejecutable.

En esta ocasión solo pondré código, ya que en anteriores entradas se ha hablado de como implementarlo.

Para persistir contra la base de datos se tiene un método en el cual se llama a un store procedure que se le pasa un parámetro para obtener un registro especifico.

[C#]

public static List<PersonalEntity> ReporteBuscarPersonal(string codigo)
        {
            using (SqlConnection cn = Conexion.Conectar(“default”))
            {
                cn.Open();
                using (SqlCommand cmd = cn.CreateCommand())
                {
                    cmd.CommandText = “SP_Personal”;
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.Parameters.AddWithValue(“@PersonalId”, codigo);
                    List<PersonalEntity> personal = new List<PersonalEntity>();
                    using (SqlDataReader reader = cmd.ExecuteReader())
                    {
                        PersonalEntity p = new PersonalEntity();
                        if (reader.Read())
                        {
                            p.Nombre = Convert.ToString(reader[“Nombre”]);
                            p.Direccion = Convert.ToString(reader[“Direccion”]);
                        };
                        personal.Add(p);
                    }
                    return personal;
                }
            }
        }

[C#] 

Se llama al método desde la capa de dominio.

[C#]

public static DataTable crBuscarPersonal(string id)
        {
            return PersonalRepository.crBuscarPersonal(id);
        }

[C#]

Por ultimo la implementación desde la presentación, el método SetDBLogonForReport el cual se encarga de pasarle los datos de conexión a la base de datos.

[C#]

private void button1_Click(object sender, EventArgs e)
        {
            string FilePath = @”G:\Reportes\PersonalParametro.rpt”;
            ReportDocument rptListaPersonal = new ReportDocument();
           
            rptListaPersonal.Load(FilePath);
            DataTable tablaDatos = Personal.crBuscarPersonal(txtId.Text);

            rptListaPersonal.SetDataSource(tablaDatos);

            frmParametro frm = new frmParametro();
           
            frm.CrystalReportViewer.ReportSource = rptListaPersonal;
            frm.CrystalReportViewer.Dock = DockStyle.Fill;
           
            ConnectionInfo cn = new ConnectionInfo();
            cn.ServerName = “.”;
            cn.DatabaseName = “Prisma”;
            cn.UserID = “sa”;
            cn.Password = “lim@01”;
            cn.Type = ConnectionInfoType.SQL;
            SetDBLogonForReport(cn, rptListaPersonal);
          
            frm.CrystalReportViewer.Refresh();
            frm.Text = “Probando”;
            frm.Show();
        }

[C#]

Crystal Reports con DataSet tipado

 

Vamos a crear un reporte con DataSet tipado, en su interior un DataTable, se usara una base de datos Access adjuntada al proyecto.

Una vez que tienen creado su proyecto y su conexión a la DB, pasaremos a crear el DataSet. Para esto se hace click derecho en el proyecto/Agregar/Nuevo elemento/Datos/Conjunto de datos. Ponen el nombre de su DataSet y listo.

Luego al DataSet le agrega un DataTable en el cual tiene que poner el nombre de la tabla que va obtener los datos, el nombre tiene que ser igual al nombre de la tabla que tiene en la DB, luego le agrega las columnas que va a consultar mediante la query.

dataset

Una vez obtenido nuestro DataSet, procedemos a crear el reporte, hacemos click derecho en el proyecto/Agregar/Nuevo elemento/Reporting/Crystal Reports. Ponen el nombre del reporte y tocaría darle la ruta donde se encuentra nuestro DataSet creado en el paso anterior.

Crystal

Crystal2

Ahora pasamos a armar el reporte de la siguiente manera se arrastra los campos que queremos mostrar en el reporte se colaca en la pate de detalles.

rpt

Ahora pasamos a codificar vamos a hacer la consulta SQL contra la DB.

using System.Text;
using System.Data;
using System.Data.OleDb;
using CristalReports.AccesoDatos;

namespace CristalReports.Reportes
{
    public class ClienteRepository
    {
        internal static dsClientes ObtenerClientes()
        {
            dsClientes _dsClientes = new dsClientes();
            using (OleDbConnection cn = Conexion.Conectar("NorthwindConnectionString"))
            {
                cn.Open();
                using (OleDbCommand cmd = cn.CreateCommand())
                {
                    cmd.CommandText = "SELECT Id, Nombre, Apellidos FROM Clientes";
                    OleDbDataAdapter da = new OleDbDataAdapter(cmd);
                    da.Fill(_dsClientes, "Clientes");
                }
            }
            return _dsClientes;
        }
    }
}

Imports System.Data
Imports System.Data.OleDb

Public Class ClienteRepository

    Friend Shared Function ObtenerClientes() As dsCliente
        Dim _DsClientes As New dsCliente()
        Using cn As OleDbConnection = Conexion.Conectar("NorthwindConnectionString")
            cn.Open()
            Using cmd As OleDbCommand = cn.CreateCommand()
                cmd.CommandText = "SELECT Id, Nombre, Apellidos FROM Clientes"
                Dim da As New OleDbDataAdapter(cmd)
                da.Fill(_DsClientes, "Clientes")
            End Using
        End Using
        Return _DsClientes
    End Function

End Class

Ahora implementamos al método ObtenerReporteCliente.

public class ClienteReporte
    {
        public static ReporteClientes ObtenerReporteCliente()
        {
            ReporteClientes reporte = new ReporteClientes();
            dsClientes cliente = ClienteRepository.ObtenerClientes();
            reporte.SetDataSource(cliente);
            return reporte;
        }
    }

Public Class ClienteReporte

    Public Shared Function ObtenerReporteCliente() As ReporteClientes
        Dim reporte As New ReporteClientes
        Dim cliente As dsCliente = ClienteRepository.ObtenerClientes()
        reporte.SetDataSource(cliente)
        Return reporte
    End Function
End Class

Ahora se agrega un formulario para colocar el CrystalReportViewer, que lo encuentra en el Toolbox en la sección Creación de informe. Preparamos el formulario.

using System.Text;
using System.Windows.Forms;
using CrystalDecisions.CrystalReports.Engine;

namespace CristalReports
{
    public partial class frmReporte : Form
    {
        private ReportClass report;
        public frmReporte()
        {
            InitializeComponent();
        }

        public frmReporte(ReportClass _report)
        {
            InitializeComponent();
            report = _report;
        }

        private void frmReporte_Load(object sender, EventArgs e)
        {
            this.crystalReportViewer1.ReportSource = report;
        }
    }
}

Imports CrystalDecisions.CrystalReports.Engine

Public Class frmReporte
    Dim report As ReportClass

    Public Sub New(_report As ReportClass)
        InitializeComponent()
        report = _report
    End Sub
    Private Sub frmReporte_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        Me.CrystalReportViewer1.ReportSource = report
    End Sub
End Class

Por ultimo llamamos al reporte para su impresión.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using CristalReports.Reportes;

namespace CristalReports
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnImprimir_Click(object sender, EventArgs e)
        {
            ReporteClientes _reporte = ClienteReporte.ObtenerReporteCliente();
            frmReporte frm = new frmReporte(_reporte);
            frm.Show();
        }
    }
}

Public Class Form1

    Private Sub btnImprimir_Click(sender As System.Object, e As System.EventArgs) Handles btnImprimir.Click
        Dim _reporte As ReporteClientes = ClienteReporte.ObtenerReporteCliente()
        Dim frm As New frmReporte(_reporte)
        frm.Show()
    End Sub
End Class

 

El resultado sería el siguiente.

reporte

Descargar App C#   Descargar App VB

NOTA : Los proyectos están desarrollados en VS 2010, les aconsejo descargar la versión Express de VS 2012 Visual Studio 2012 Express ya que uso la versión 2012.

Filtrar datos en DataGridView

Vamos a filtrar datos en un DataGrigView, pero antes de eso se ha debido cargar los registros al DGV, previa búsqueda de por ejemplo, Clientes que su nombre o apellido comience con M, una vez cargada la data, se procede a filtrar los datos, hacer la búsqueda en el DGV, más no en la DB.

Sería una mala practica tener los datos cargados en el DGV y hacer el filtro en la DB, lo que se pretende con esta técnica es liberar recursos en el servidor de datos y pretender una mejor performance de la aplicación.

Vamos a crear un método con DataTable en el cual le vamos asignar los datos que recuperamos de la DB.

public class ClienteRepository
    {
        public static DataTable GetCliente()
        {
            using (SqlCeConnection cn = Conexion.Conectar("NorthwindConnectionString"))
            {
                cn.Open();
                using (SqlCeCommand cmd = cn.CreateCommand())
                {
                    cmd.CommandText = "SELECT [Customer ID], [Company Name] FROM Customers";

                    using (SqlCeDataAdapter da = new SqlCeDataAdapter(cmd))
                    {
                       DataTable dt = new DataTable();
                        da.Fill(dt);
                        return dt;
                    }
                }
            } 
        }

Ahora vamos a llamar el método GetCliente desde el evento Load del formulario para cargar el DataGridView.

public partial class frmCliente : Form
    {
        private DataTable dt = new DataTable();
        private DataSet ds = new DataSet();
        public frmCliente()
        {
            InitializeComponent();
        }

        private void frmCliente_Load(object sender, EventArgs e)
        {
            dt = ClienteRepository.GetCliente();
            ds.Tables.Add(dt);
            dgvCliente.DataSource = dt;
            FormatoGrilla();
        }

Ya esta cargado el objeto DGV con los datos ahora pasamos a hacer la búsqueda en los datos que tiene cargado el DGV, mas no en la DB. Como decía líneas arriba hemos utilizado un objeto DataTable, para poder usar el DataView.

El DataView representa una vista personalizada que puede enlazar datos de un DataTable para ordenación, filtrado, búsqueda, edición y navegación. El DataView no almacena datos, si no que representa una vista conectada de su correspondiente DataTable.

private void txtDescripcion_TextChanged(object sender, EventArgs e)
        {
            string fieldName = string.Concat("[", dt.Columns[1].ColumnName,"]");
            dt.DefaultView.Sort = fieldName;
            DataView view = dt.DefaultView;
            view.RowFilter = string.Empty;
            if (txtDescripcion.Text != string.Empty)
                view.RowFilter = fieldName + " LIKE '%" + txtDescripcion.Text + "%'";
            dgvCliente.DataSource = view;
        }

El filtro lo realizamos en el evento txtDescripcion_TextChanged de la caja de texto que vamos usar para ingresar los datos que queremos filtrar o buscar. Quedaría de esta manera.

DGV

Descargar Proyecto C#