clase


– Ejercicio de Analisis Sustantivo/Verbo –

” Controlar inventario de articulos, entradas y salidas, quien y a que hora sucede el movimiento.  Cuando algun articulo llegue a cierta cantidad de inventario, se dara aviso al encargado.
Tambien se avisara (al encargado) cada dia de los 5 articulos con menor cantidad.
Todos los avisos se haran por correo electronico especificando nombre y cantidad del articulo. ”

[ Entregable (1) Modelo de clases ]

 == Verificacion de Modelo de clases ==

Ejercitar las siguientes peticiones SQL contra el modelo de clases elaborado de la situacion anterior:

SQL–
 
 * mostrar articulos con cantidad menor o igual a su cantidad minima
 * mostrar personas que han utilizado el articulo “Tornillo 1/4”
 * mostrar todos los movimientos de las ultimas 4 horas

[ Entregable (2) Sentencias SQL ]

Codigo para Clase

    Empezar el codigo para una clase identificada completando las declaraciones de miembros privados y propiedades publicas.

[ Entregable (3) Codigo para la clase ]

 

En un post posterior se proporcionaran posibles entregables…

Anuncios

SQL statements – Sentencias SQL

Durante clase estuvimos haciendo ejemplos de consultas a unas tablas ejemplo en internet.  La tabla bbc(name,region,population,gdp) y la tabla nobel(yr,subject,winner).  Ejercitamos el uso de las palabras de SQL ‘SELECT’, ‘FROM’, ‘WHERE’, ‘IN’, ‘LIKE’ y lo que cada una de ellas nos proporciona.  Aqui les muestro ejemplos de lo esperado para el proximo examen del martes

TABLA: Articulo(precio,descripcion,imagen,categoria,nombre)

 * mostrar los articulos que empiecen con “R” y no cuesten mas de 100 pesos
 * mostrar los articulos que pertenezcan a la categoria “Bebidas” que cuesten mas de 20 pesos

TABLA: Cliente(frc,ape_paterno,ape_materno,nombres,telefono)

 * mostrar nombre completo de cliente con apellido paterno “Lopez”
 * mostrar rfc de clientes con area de telefono 656

UrlImage Control 

Como proposito, se intenta tener un control que pueda cargar una imagen en un PictureBox pasandole una direccion de internet (url) de donde tomarla.

Elementos en disenho del control de usuario

 urlImage en disenho

El control consta de 3 PictureBoxes. Dos de ellos se van a usar como ayudas para que guarden una imagen cada uno, en pbxLoading vamos a poner una imagen que represente que el control esta trabajando y en pbxNotFound vamos a poner una imagen para representar un error en el cargado de la imagen solicitada.  Estos controles siempre permaneceran ocultos (Visible = false) y tomaremos de ellos las imagenes para ponerlas en el pictureBox1 cuando las requiramos.

Codigo detras del control

urlImage codigo

Aqui en codigo podemos ver que estamos utilizando el evento Resize del UserControl para hacer que pictureBox1 cubra toda la superficie de nuestro control.  Y ademas agregando un metodo publico llamado GetImage(string url) con el cual podremos pedirle al control que intente cargar la imagen de internet que le proporcionemos con el parametro url

En GetImage(), primero pasamos la imagen que esta en pbxLoading al PictureBox principal, y despues intentamos (por medio de un try) cargar la imagen desde internet a nuestro PictureBox.  Esto lo logramos con la ayuda de la clase HttpWebRequest, donde especificamos la direccion de internet, y obtenemos su ResponseStream para pasarselo al PictureBox e intente mostrarlo a pantalla; en caso de algun error | excepcion, lo indicaremos cargando la imagen que se encuentra en pbxNotFound.

durante esta clase se trabajo con la aplicacion de “imageBrowser” (la acabo de bautizar). Y basicamente lo que hicimos fue pasarla de su fase uno a la fase dos

El principal concepto desarrollado durante esta sesion es:

Eventos,    Eventos,         Eventos

  – delegate
Explicacion ejemplo: [situacion] llamas a un amigo por telefono a su casa pero no esta, dejas tu telefono para que cuando llegue te marque… mientras tu puedes seguir con tus actividades y no quedarte en la linea esperando (tal vez horas) hasta que llegue.  [analogia .net] le haces saber a un metodo (telefono de tu amigo) que vas a requerir que se te notifique (dejas tu telefono) cuando ocurra este cierto metodo (evento), mientras tu aplicacion puede seguir con sus operaciones…  

La situacion explicada puede concretarse debido a los delegates | delegados que podemos crear en punto NET.   Un delegado | delegate tiene las siguientes caracteristicas:   

  • verifican los tipos de parametros que se les pasan; o bien, verifican que el numero de telefono que dejas para que tu amigo llame este en el formato correcto.
  • se aseguran que siempre se apunte a un metodo existente; o bien, se asegura que el numero de telefono exista.
  • soportan “multicasting”; o bien, puedes dejar un listado de telefonos para que tu amigo haga notificaciones de que ya llego a todos ellos.

 Ahora bien, pasando esto a nuestra aplicacion, enfocandonos a nuestros usercontrols DriveList y FolderList, queremos que cuando el usuario seleccione una nueva unidad de disco, el listado de FolderList se actualice para mostrar las carpetas correctas.

Para esto necesitamos poner en nuestro DriveList, un evento para que otros objetos puedan “suscribirse” y ser notificados cuando el evento ocurra.

create event/deleg

en este codigo, podemos ver que se declara un delegado para validar metodos que no regresan resultado (void), y aceptan un parametro tipo string, este delegado se llamara SelectionChangedHandler.  En la siguiente linea se declara un evento llamado SelectionChanged y acepta subscripciones de metodos validados por el delegado SelectionChangedHandler.  Aparte se esta agregando la linea de codigo que “dispara” el evento desde nuestro control hacia los objetos interesados en reaccionar a dicho evento.  Esta linea esta dentro del metodo comboBox1_SelectedIndexChanged, el cual a su vez se corre cada vez que se selecciona un elemento diferente de nuestro ComboBox.

Cuando se corre SelectionChanged(comboBox1.Text), nuestro evento se esta disparando y se lleva con el el texto desplegado en el ComboBox para proporcionarselo a quien se haya suscrito al evento, y le interese ser notificado cada vez que se cambia de unidad de disco. 

 Vamos haciendo unas observaciones de lo que esta ocurriendo… busquemos en el codigo del control la llamada al metodo ComponentInitialize(), seleccionalo y dale click-derecho y “Goto Definition”; ahora busca por alli y veras la linea

this.comboBox1.SelectedIndexChanged +=
   
new System.EventHandler(this.comboBox1_SelectedIndexChanged);

esto suscribe el metodo comboBox1_SelectedIndexChanged al evento SelectedIndexChanged del objeto comboBox1, y aparte se esta validando que el metodo cumpla con las especificaciones del delegado EventHandler.  Ahora selecciona EventHandler y dale click-derecho y “Goto Definition”, veras la declaracion:

public delegate void EventHandler(object sender, EventArgs e);

Esto nos muestra que las especificaciones del delegado validan metodos que no regresan resultado (void) y requieren dos parametros, uno object, y otro EventArgs.  …volviendo a nuestra declaracion de delegado, nosotros validaremos que el metodo que se suscribe no regrese valor y acepte una cadena.

Nuestro control ya cuenta con el evento SelectionChanged.

Suscribiendome al evento del DriveList ;            Subscripcion

El siguiente paso sera suscribir un metodo al evento de tal manera que nuestro FolderList se actualice con la ruta correspondiente cada vez que se cambie de unidad de disco en DriveList

Necesitamos un metodo que cumpla con los requisitos de nuestro delegado SelectionChangedHandler: no regresa resultado, y acepte una cadena… Lo llamare CambioDrive. [, se validan estos requisitos ya que este tipo de delegado fue el que escogi para declarar el evento SelectionChanged]  En este metodo esta la logica para desplegar en FolderList la ruta que se selecciono en DriveList; recordemos que el evento trae consigo lo que obtuvo de comboBox1.Text al momento de ser disparado, y nos lo va a proporcionar con la variable string newDrive que tiene el metodo CambioDrive.

implement event

…ya que tenemos nuestro metodo que se apega a los requisitos de nuestro delegado, vamos suscribiendonos al evento.  Esto lo estoy poniendo en el Form1_Load:

link method to event

..de esta manera cada vez que el usuario cambia de unidad de disco, se dispara el evento SelectionChanged de driveList1, con esto, se notifica a los suscritos (CambioDrive) y por lo tanto, folderList1.DisplayFolders() con la ruta de driveList1. 😀

En esta sesion, continuamos con la elaboracion de nuestros propios controles (UserControls).  La sesion pasada fue crear un control para validar correos electronicos (EmailInput).

Esta vez empezamos por definir algunos requerimientos para una nueva aplicacion.  Esta aplicacion nos permitira visualizar imagenes que podamos accesar desde nuestro sistema de archivos (lease unidades de disco tales como: discos duros, lectores cd o dvd, floppies, unidades de red mapeadas), basicamente como las que encontramos en windows explorer.  Hasta cierto punto vamos a “copiar” la funcionalidad del windows explorer en cuanto a que podremos seleccionar una unidad de disco, navegar por las carpetas/folders disponibles, y ver los archivos que estan dentro de las carpetas.  Finalmente, para seleccionar un archivo con extension de imagen y desplegarlo en nuestra forma…

Para esto vamos a empezar por desarrollar varios UserControls, especificamente:
DriveList, – FolderList, – FileList.

La funcionalidad principal para DriveList seria poder seleccionar una unidad de disco de la computadora; la funcionalidad principal para FolderList seria desplegar y navegar por los folders presentes; y la funcionalidad de FileList seria desplegar una lista de archivos para determinada carpeta.

DriveList UserControl

Este control sera un ComboBox para poder seleccionar alguna de las unidades de disco existentes en la computadora. En su evento Load, vamos a utilizar el metodo estatico GetDrives() de la clase DriveInfo del namespace System.IO; este metodo nos regresa un arreglo DriveInfo[] con cada uno de sus elementos representando una unidad de disco existente.

//(agregar la namespace System.IO al principio de nuestro codigo)

DriveInfo[] unidades = System.IO.DriveInfo.GetDrives();

..ya con esto, vamos a iterar el arreglo con un for, y agregar el nombre (letra asignada) de la unidad a nuestra lista ComboBox.  Aparte vamos a exponer la unidad seleccionada a manera de propiedad, esta propiedad la estoy llamando SelectedDrive:

drivelist01

por lo pronto, ya tenemos un UserControl para desplegar las unidades de disco existentes en la computadora !!

DriveList in action

FolderList UserControl

Ahora empecemos con nuestro segundo UserControl para navegar carpetas.  Para este, vamos a implementar un metodo que nos pida como parametro una ruta, entonces el metodo enlistara las subcarpetas de esta ruta en un ListBox.  Aparte vamos a exponer la ruta actual de nuestro control (como propiedad).

Vamos a ayudarnos del metodo estatico GetDirectories() de la clase Directory, iteramos el resultado y vamos agregando a nuestro ListBox.  En este punto, vamos a agregar una carpeta especial, para facilidad la vamos a nombrar “..” para simular un cambio de directorio hacia “afuera/arriba” en nuestro arbol de directorios/carpetas.

FolderList01

Ya tenemos nuestro metodo para captar una ruta, y desplegar las sub-carpetas de esa ruta, ahora vamos a extender un poco mas la funcionalidad de nuestro UserControl poniendo logica en el DobleClick / DoubleClick del listado de carpetas.  Esto para que podamos “entrar” a la carpeta que se da doble click, y ver las carpetas que estan dentro…

FolderList02

..con esto ya tenemos un “explorador” de carpetas; con la ayuda de un Label, y asignandole nuestra propiedad Path
label1.Text = folderList1.Path;
podemos desplegar la ruta actual de las carpetas que estan desplegadas…

FolderList in action
[tuve que recurrir a un Timer para sincronizar el label con el folderList, despues vamos a implementar eventos para que otros controles/objetos puedan ser notificados de acciones en nuestros controles…]

Hasta aqui llegamos durante la sesion… el martes despues del pequenho y facil examen le seguimos…

Descarga del proyecto fase uno (incompleto): Proyecto fase uno
nota obligatoria, renombrar el archivo a .zip

En esta clase vimos introduccion a controles “customizados” (custom controls), y nos enfocamos a la tecnica de extender (agregar funcionalidad a) controles ya existentes…  El ejemplo desarrollado en clase fue extender un TextBox de tal manera que nos validara si el texto contenido en el es un correo electronico (email) valido. 

Determinamos algunas reglas que una cadena debe cumplir para considerarla un email valido, siendo estas:

i. que solo contenga una arroba (@).
ii. que exista un punto (.) despues de la posicion de la arroba.
iii. que la cadena tuviera al menos una letra despues del ultimo punto; o bien, que la cadena no termine en punto.

Vimos como podemos notificarle al usuario en caso de que el “email” proporcionado no cumpliera con todas las reglas que determinamos.  Podemos implementar notificaciones intrusivas y no-intrusivas.

Las intrusivas de las que platicamos fueron: – desplegar un MessageBox, – atrapar el foco de la aplicacion en nuestro control hasta que se proporcione un correo valido.

Y la no-intrusiva (y por la que optamos implementar): – cambiar la visualizacion del control.

Cuando se proporcione una cadena que no cumple con las reglas determinadas, nuestro control cambiara a fondo rojo, y letras amarillas, cuando la entrada sea valida, cambiara a fondo blanco con letras negras.

Desarrollo en Visual Studio

Empezamos por crear un proyecto de aplicacion para windows, seguido por agregar otro proyecto a la solucion de biblioteca de controles.  Por defecto, la aplicacion de windows cuenta con el archivo Form1, y la biblioteca de controles con el archivo UserControl1.  Renombramos el UserControl1 a EmailInput.

a continuacion el codigo para EmailInput: (agregar un TextBox en la posicion 0,0)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
namespace MisControles
{
  public partial class EmailInput : UserControl
  {
  private bool _isValid = false;
  public bool IsValid {
  get { return _isValid; }
  //set { _isValid = value; }
  }
public EmailInput()
  {
  InitializeComponent();
  }
private void UserControl1_Load(object sender, EventArgs e)
  {
  //se dispara cuando se agrega este control
  // a una forma
  UserControl1_Resize(this, new EventArgs());
  }
private void UserControl1_Resize(object sender, EventArgs e)
  {
  textBox1.Width = this.Width;
  this.Height = textBox1.Height;
  }
private void textBox1_Leave(object sender, EventArgs e)
  {
  //comprobar que existe arroba
  if (textBox1.Text.Contains("@") == false) {
  //el texto no contiene arroba
  textBox1.BackColor = Color.FromArgb(255,0,0); //Color.Red
  textBox1.ForeColor = Color.Yellow;
  _isValid = false;
  return;
  }
  //comprobar que solo existe una arroba
  string[] pedazos = textBox1.Text.Split('@');
  if (pedazos.Length != 2) {
  textBox1.BackColor = Color.FromArgb(255, 0, 0); //Color.Red
  textBox1.ForeColor = Color.Yellow;
  _isValid = false;
  return;
  }
  //comprobar que existe un punto despues de la arroba
  int pos_arroba = textBox1.Text.IndexOf("@");
  int pos_ultimo_punto = textBox1.Text.LastIndexOf(".");
  if (pos_ultimo_punto < pos_arroba) {
  textBox1.BackColor = Color.FromArgb(255, 0, 0); //Color.Red
  textBox1.ForeColor = Color.Yellow;
  _isValid = false;
  return;
  }
  //comprobar que existen al menos 1 letra despues del ultimo punto
  if(textBox1.Text.EndsWith(".")){
  textBox1.BackColor = Color.FromArgb(255, 0, 0); //Color.Red
  textBox1.ForeColor = Color.Yellow;
  _isValid = false;
  return;
  }
  if (textBox1.Text.Contains(" ")) {
  textBox1.BackColor = Color.FromArgb(255, 0, 0); //Color.Red
  textBox1.ForeColor = Color.Yellow;
  _isValid = false;
  return;
  }
  textBox1.BackColor = Color.FromArgb(255, 255, 255); //Color.White
  textBox1.ForeColor = Color.Black;
  _isValid = true;
  }
  }
}
La logica de las reglas establecidas se corre cada vez que el usuario sale de nuestro control, con el metodo textBox1_Leave que esta asociado al evento Leave del TextBox.  Otra opcion pudo ser que la logica se corriera con cada tecla que el usuario presione, para esto el metodo se puede asociar al evento KeyPress del Textbox: textBox1.KeyPress += new EventHandler(textBox1_Leave).

La logica de las reglas incluye el manejo de una variable privada _isValid, donde guardamos si el control contiene un email valido o no.  Esta propiedad privada la exponemos como propiedad publica pero ReadOnly (solo lectura) para que el programador que utilice nuestro validador de correos pueda determinar si contiene uno valido o no.

     if ( emailInput1.IsValid ) // mandar el correo !!

descarga del proyecto completo: Proyecto Completo
nota obligatoria, renombrar el archivo a .rar

Otros conceptos vistos la clase:
String.Contains, String.StartsWith, String.EndsWith, Color.Black, Color.Red, Color.FromArgb, String.IndexOf, String.LastIndexOf, TextBox.ForeColor, TextBox.BackColor, UserControl.Width, UserControl.Height, ..

Screen..

Les presento a Form1 corriendo, contiene dos EmailInput‘s (control desarrollado en clase) y un Button donde podemos preguntarle a los emailInputs si contienen emails validos…

emailInputs in action

Administrador de Contactos> en esta sesion, agregamos un boton mas a nuestra aplicacion de contactos, con la finalidad de poder editar un contacto existente.

Ventana de Aplicacion

…con esto, se agregaron dos metodos al codigo de la forma:

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)

con este metodo manejamos el evento click del ListBox, y hacemos varias cosas:

– activamos el boton “actualizar”, deshabilitamos el boton “agregar”, y el TextBox para “email” (esto porque email es nuestro identificador unico y no permitiremos que se modifique).

el segundo metodo es:

private void button6_Click(object sender, EventArgs e)

en este metodo manejamos el click para el boton “actualizar”, y hacemos lo sig>:

– actualizamos en tabla los datos del contacto seleccionado; regresamos a los botones a su estado de “agregar”

—–

A continuacion el codigo completo:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Data.OleDb;
namespace uacj_Contactos
{
  public partial class Form1 : Form
  {
  public Form1()
  {
  InitializeComponent();
  }
private void Form1_Load(object sender, EventArgs e)
  {
  displayContacts("1=1");
  }
private void displayContacts(string filtro) {
  listBox1.Items.Clear();
  OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=C:\\contactos.mdb");
  OleDbCommand cmd = new OleDbCommand("SELECT * FROM contactos WHERE ("+filtro+") ORDER BY nombre ASC");
  cmd.Connection = conn;
  cmd.Connection.Open();
  OleDbDataReader reader = cmd.ExecuteReader();
  while (reader.Read()) {
  listBox1.Items.Add(reader["nombre"].ToString() + " - " + reader["email"].ToString());
  }
  reader.Dispose();
  cmd.Dispose();
  conn.Dispose();
  }
private void button3_Click(object sender, EventArgs e)
  {
  displayContacts("email LIKE '%yahoo.com%'");
  }
private void button4_Click(object sender, EventArgs e)
  {
  displayContacts("email LIKE '%hotmail.com%'");
  }

private void button5_Click(object sender, EventArgs e)
  {
  displayContacts("email LIKE '%"+textBox3.Text+"%'");
  }

private void button1_Click(object sender, EventArgs e)
  {
  OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=C:\\contactos.mdb");
  OleDbCommand cmd = new OleDbCommand("INSERT INTO contactos (email,nombre) VALUES ('"+textBox1.Text+"','"+textBox2.Text+"')");
  cmd.Connection = conn;
  cmd.Connection.Open();
  cmd.ExecuteNonQuery();
  cmd.Dispose();
  conn.Dispose();
  displayContacts("1=1");
  }

private void button2_Click(object sender, EventArgs e)
  {
  string[] valores = listBox1.Text.Split('-');
  string email = valores[valores.Length-1].Trim();
  OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=C:\\contactos.mdb");
  OleDbCommand cmd = new OleDbCommand("DELETE FROM contactos WHERE (email = '"+email+"')");
  cmd.Connection = conn;
  cmd.Connection.Open();
  cmd.ExecuteNonQuery();
  cmd.Dispose();
  conn.Dispose();
  displayContacts("1=1");
  }

private void button6_Click(object sender, EventArgs e)
  {
  OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=C:\\contactos.mdb");
  OleDbCommand cmd = new OleDbCommand(
  "UPDATE contactos SET nombre = '" +
  textBox2.Text + "' WHERE (email = '" + textBox1.Text + "')");
  cmd.Connection = conn;
  cmd.Connection.Open();
  cmd.ExecuteNonQuery();
  cmd.Dispose();
  conn.Dispose();
  displayContacts("1=1");
  textBox1.Enabled = true;
  button6.Enabled = false;
  button1.Enabled = true;
  textBox1.Text = "";
  textBox2.Text = "";

}

private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
  {
  button1.Enabled = false;
  button6.Enabled = true;
  textBox1.Enabled = false;
  string[] valores = listBox1.Text.Split('-');
  OleDbConnection conn = new OleDbConnection("Provider=Microsoft.Jet.OleDb.4.0;Data Source=C:\\contactos.mdb");
  OleDbCommand cmd = new OleDbCommand("SELECT * FROM contactos WHERE (email = '"+valores[1].Trim()+"')");
  cmd.Connection = conn;
  cmd.Connection.Open();
  OleDbDataReader reader = cmd.ExecuteReader();
  while (reader.Read())
  {
  textBox1.Text = reader["email"].ToString();
  textBox2.Text = reader["nombre"].ToString();
  // asi con cada columna de nuestro contacto...
  }
  reader.Dispose();
  cmd.Dispose();
  conn.Dispose();
  }
  }
}

descargar el proyecto: Proyecto Completo
Nota del archivo: es un .zip pero el blog no me lo acepto asi que lo renombre a .zip.gif; fovor de renombrarlo a .zip para poder extraer su contenido;
Nota 2: copiar la base de datos a C:, o bien, actualizar la ruta en el connectionString del OleDbConnection.

Disculpas por la tardanza... :P

Página siguiente »