lunes, 4 de abril de 2011

Ejercicio. Implementar el juego del tres en raya (también llamado Tic Tac Toe o "de la vieja")


Programa en C# el juego del tres en raya. Inicialmente vamos a hacerlo para dos jugadores que manejan el ratón, la versión más simple. Ten en cuenta las siguientes consideraciones:

  • Crea una aplicación Windows en Sharp Develop y emplea componentes botón (Button) para representar cada celda del juego.
  • Las celdas tendrán un tamaño de 75x75 pixels.
  • Inicialmente el color de fondo de las celdas será negro.
  • No repitas el código para atender el evento de clic en cada celda. Trata simplemente de recoger una referencia al objeto botón que produjo el evento para manipularlos todos de forma genérica. Esto es, en cada manejador del clic aparecerá: celda =(Button)sender; siendo celda un atributo miembro del formulario de la clase Button.
  • Para poner X o O se cargará la imagen respectiva en el botón. Para cargar una imagen en un botón modifica su atributo Image como en este ejemplo: celda.Image=Image.FromFile("tres_en_raya_O.jpg");

  • Hacer clic sobre una celda en la que ya se ha jugado no debe tener efecto (puedes avisar al jugador mostrando un error en una etiqueta)
  • El juego debe detenerse cuando alguien haya ganado y debe mostrar en una etiqueta quién es el ganador.
  • Debe ser posible reiniciar el juego, una vez acabado o en medio de una partida, mediante un botón de Reset.
  • Debe ser posible elegir el turno inicial.
Una vez que funcione, trata de añadir manejadores de eventos para las teclas, de tal forma que cada jugador pueda jugar indistintamente con el ratón o con el teclado. Para ello puedes suponer la configuración

qwe
asd
zxc

haciendo corresponder a cada celda la letra que ocupa su misma posición. Para recordar cómo manejar eventos de teclado revisa el ejemplo del juego del Pong


Finalmente, habilita una opción para jugar contra la máquina. Para ello, en el turno de la máquina debes simular cierta "inteligencia" que sea capaz de tomar buenas decisiones. Lo ideal sería utilizar el algoritmo del minimax. Haz clic en este enlace y vete a la página 13 del documento para comprobar en qué consiste. Además de una clara explicación de su mecanismo dispones del pseudocódigo para implementarlo recursivamente. Simplemente, trata de adaptarlo a la sintaxis de C#.

Solución con minimax sin heurística: descárgalo aquí


sábado, 2 de abril de 2011

Ejercicio. Extender la aplicación de dibujo

Modifica el código de ejemplo del post anterior para que en el cuadro de lectura de datos de "Figura" se nos pregunte por las coordenadas X e Y de un punto origen y las coordenadas X e Y de un punto destino para dibujar una línea recta.


Haz clic en la imagen para descargar el proyecto con la solución


Ejemplo funcional de aplicación para dibujar gráficos


Haz clic en la imagen para descargar la aplicación de ejemplo que te servirá de base para tus prácticas

viernes, 1 de abril de 2011

Ejemplos. Gráficos

Se puede usar gráficos para mejorar la interface de una aplicación, crear gráficos, reportes y editar imágenes.

Lección 1 - Dibujando gráficos

System.Drawing permite crear gráficos o modificar imágenes. Cambiar de tamaño una imagen, crear círculos, líneas u otras formas, hacer zoom a imágenes, adherir copyright a logos o textos, etc.

Clases:
Bitmap Encapsula un mapa de bits de GDI+, formado por los datos de píxel de una imagen de gráficos y sus atributos. Un objeto Bitmap es utilizado para trabajar con imágenes definidas por datos de píxel.
Brush Las clases derivadas de esta clase base abstracta definen objetos utilizados para rellenar el interior de formas gráficas, como rectángulos, elipses, gráficos circulares, polígonos y rutas.
Brushes Pinceles de todos los colores estándar. No se puede heredar esta clase.
ColorConverter Convierte colores de un tipo de datos a otro. Se tiene acceso a esta clase mediante TypeDescriptor.
ColorTranslator Convierte colores a y de estructuras Color GDI+. No se puede heredar esta clase.
Font Define un formato concreto para el texto, incluidos el nombre de fuente, el tamaño y los atributos de estilo. No se puede heredar esta clase.
FontConverter Convierte objetos Font de un tipo de datos en otro. Se tiene acceso a la clase FontConverter mediante el objeto TypeDescriptor.
FontFamily Define un grupo de tipos de letra que tienen un diseño básico parecido y algunas diferencias de estilo. No se puede heredar esta clase.
Graphics Encapsula una superficie de dibujo GDI+. No se puede heredar esta clase.
Icon Representa un icono de Windows, que es una pequeña imagen de mapa de bits utilizada para representar un objeto. Los iconos se pueden considerar como mapas de bits transparentes, aunque su tamaño lo determina el sistema.
IconConverter Convierte objetos Icon de un tipo de datos en otro. Se tiene acceso a esta clase mediante el objeto TypeDescriptor.
Image Clase base abstracta que proporciona funcionalidad para las clases descendentes Bitmap y Metafile.
ImageAnimator Da animación a una imagen que tiene marcos basados en tiempo.
ImageConverter ImageConverter es una clase que se puede utilizar para convertir objetos Image de un tipo de datos a otro. Se tiene acceso a esta clase mediante el objeto TypeDescriptor.
ImageFormatConverter ImageFormatConverter es una clase que se puede utilizar para convertir colores de un tipo de datos a otro. Se tiene acceso a esta clase mediante el objeto TypeDescriptor.
Pen Define un objeto utilizado para dibujar líneas y curvas. No se puede heredar esta clase.
Pens Lápices de todos los colores estándar. No se puede heredar esta clase.
PointConverter Convierte objetos Point de un tipo de datos en otro. Se tiene acceso a esta clase mediante el objeto TypeDescriptor.
RectangleConverter Convierte rectángulos de un tipo en otro tipo. Se tiene acceso a esta clase mediante TypeDescriptor.
Region Describe el interior de una forma gráfica formada por rectángulos y rutas. No se puede heredar esta clase.
SizeConverter SizeConverter es una clase que se utiliza para convertir un tipo de datos en otro. Se tiene acceso a esta clase mediante el objeto TypeDescriptor.
SolidBrush Define un pincel de un solo color. Los pinceles se utilizan para rellenar formas de gráficos, por ejemplo rectángulos, elipses, gráficos circulares y rutas. No se puede heredar esta clase.
StringFormat Encapsula información de diseño del texto (como interlineado y alineación), manipulaciones de presentación (como inserción de puntos suspensivos y sustitución de dígitos nacional) y características de OpenType. No se puede heredar esta clase.
SystemBrushes Cada una de las propiedades de la clase SystemBrushes es un objeto SolidBrush que es el color de un elemento de presentación de Windows.
SystemColors Cada una de las propiedades de la clase SystemColors es una estructura Color que es el color de un elemento de presentación de Windows.
SystemIcons Cada una de las propiedades de la clase SystemIcons es un objeto Icon de los iconos de todo del sistema de Windows. No se puede heredar esta clase.
SystemPens Cada una de las propiedades de la clase SystemPens es un objeto Pen que es el color de un elemento de presentación de Windows y es un ancho de 1.
TextureBrush Cada una de las propiedades de la clase TextureBrush es un objeto Brush que utiliza una imagen para rellenar el interior de una forma. No se puede heredar esta clase.
ToolboxBitmapAttribute Se puede aplicar un objeto. ToolboxBitmapAttribute a un control de manera que los contenedores, como el Diseñador de formularios de Microsoft Visual Studio, puedan recuperar un icono que represente el control. El mapa de bits del icono puede encontrarse en un archivo por sí solo o incrustado en el ensamblado que contiene el control.
El tamaño del mapa de bits que se incrusta en el ensamblado del control (o que se almacena en un archivo independiente) debe ser de 16 por 16. El método GetImage de un objeto ToolboxBitmapAttribute puede devolver la imagen pequeña de 16 por 16 o una imagen grande de 32 por 32 creada mediante un ajuste de escala de la imagen pequeña.

Como especificar el tamaño y ubicación de un control.
El uso más común de System.Drawing es especificar la ubicación de algún control, cuando se está creando de manera dinámica (por código).
Para realizarlo se crea un punto al que se le pasa dos parámetros (distancia desde arriba, distancia desde el lado izquierdo) para setear la propiedad Location del control.
Ejemplo
clip_image001
Una forma alternativa se puede setear directamente las propiedades left y top del control.
clip_image002
También es posible especificar el tamaño:
clip_image003
Como especificar el color de los controles
Para modificar los colores de un control, se puede utilizar la estructura Color de la siguiente forma:
clip_image004
Si es que se necesita especificar un color personalizado, se puede utilizar el método Color.FromArgb():
clip_image005
Como dibujar líneas y formas
Para dibujar en un formulario o en un control, se deben de seguir los siguientes pasos:
1. Crea un objeto Graphics llamando al método system.Windows.Forms.Control.CreateGraphics
2. Crear un objeto Pen
3. Llamar al miembro de Graphics para dibujar en el cotrol, usando el Pen.
Una vez que se ha creado el objeto graphics, se puede utilizar muchos métodos para mejorarlo como
Clear Borra la superficie de dibujo y la rellena con el color de fondo especificado.
DrawEllipse Dibuja una elipse definida por un rectángulo delimitador especificado por un par de coordenadas, un valor de alto y un valor de ancho.
DrawIcon
Dibuja la imagen representada por el Icon especificado en las coordenadas
Señaladas.
DrawIconUnstretched
Dibuja la imagen representada por el Icon especificado sin transformar a escala la imagen.
DrawImage Dibuja la Image especificada en la ubicación que se indique y con el tamaño original.
DrawLine Dibuja una línea que conecta los dos puntos especificados por los pares de coordenadas.
DrawLines Dibuja una serie de segmentos de línea que conectan una matriz de estructuras Point.
DrawPath Dibuja un GraphicsPath.
DrawPie Dibuja una forma circular definida por una elipse determinada por un par de coordenadas, unos valores de ancho y alto y dos líneas radiales.
DrawPolygon Dibuja un polígono definido por una matriz de estructuras Point.
DrawRectangle Dibuja un rectángulo especificado por un par de coordenadas, un valor de ancho y un valor de alto.
Drawrectangles Dibuja una serie de rectángulos especificados por las estructuras Rectangle.
DrawString Dibuja la cadena de texto especificada en la ubicación especificada y con los objetos Brush y Font especificados.
Para especificar cualquiera de esos métodos se debe proveer una instancia de la clase Pen. En el constructor de Pen (lapiz), se especifican el color y width en pixeles:
clip_image006
Métodos como Graphics.DrawLines, Graphics.DrawPolygon, Graphics.DrawRectangles, aceptan arreglos de puntos como parámetros, para crear figuras más complejas.


Como personalizar Pens?
Además de controlar el color y el tamaño del pen (lapiz), que se especifican en el contructor, también se puede controlar el patrón y su endcap. Endcap es el final de una línea, pueden ser utilizados para crear flechas.
Para crear un lapiz que dibuje líneas punteadas, se debería de setear la propiedad de Pen.DashStyle a uno de los siguientes valores:
  • · DashStyle.Dash (guion)
  • · DashStyle.DashDot (guion punto)
  • · DashStyle.DashDotDot (guion punto punto)
  • · DashStyle.Dot (punto)
  • · DashStyle.Solid. (solido)
Ejemplo
clip_image007
Tambien es posible utilizar Pen.DashOffset y Pen.DashPattern para definir patrones dash(guion).
Para crear flechas, uno debe de modificar las propiedade Pen.StartCap y Pen.EndCap, utilizando el enumerador LineCap, que tiene valores como:
  • · LineCap.ArrowAnchor
  • · LineCap.DiamonAnchor
  • · LineCap.SquareAnchor
  • · LineCap.Triangle
  • · LineCap.Flat
  • · LineCap.Round
  • · LineCap.RoundAnchor
  • · LineCap.Square
Ejemplo:
clip_image008

Como llenar formas?
La mayoría de los métodos de la clase grafics tiene también un método llamado fill que dibuja una forma (shape) y la rellena. Estos métodos requieren una instancia de la clase Brush, la cual es abstracta, entonces se debe de instanciar una clase hija:

System.Drawing.Drawing2D.HatchBrush define un rectangular brush con un estilo hatch
System.Drawig.Drawing2D.LinearGradientBrush encapsula un brush con un gradiente lineal.
System.Drawing.Drawing2D.PathGradientBrush igual que el anterior, solo que provee un llenado más complejo
System.Drawing.SolidBrush Define un Brush de un color simple.
System.Drawing.TextureBrush define un Brush desde una imagen
Ejemplo:
clip_image009


Lección 2 – trabajando con imágenes

System.Drawing.Image es una clase abstracta que permite crear, cargar, modificar y grabar imágenes, como BMP, jpg o tif.
La clase Image es abstracta, por lo tanto se debe de crear una instancia usando Image.FromFile, el cual recibe como parámetro un path a la imagen, y Image.FromStream, que recibe un System.IO.Stream como parámetro.
También se pueden utilizar dos clases que heredan de la clase Image:
System.Drawing.Bitmap (para imágenes) y System.Drawing.Imaging.Metafile (para imágenes animadas).
Bitmap es la clase mas usada comúnmente para trabajar con imágenes. Los diferentes constructores de Bitmap, permiten crear un Bitmap a partir de una Imagen, archivo o stream, o sino crear un bitmap en blanco con un height (alto) y width(ancho) especificado. Bitmap contiene 2 metodos importantes que la clase Image carece:
  • GetPixel, el cual devuelve un objeto Color, con los colores de ese pixel.
  • SetPixel, setea el color de un pixel.

Como mostrar imágenes?
Para mostrar una imagen guardada en el disco, se debe utilizar Image.FromFile, crear un control PictureBox y usar la imagen para definir PictureBox.Background:
Por ejemplo, para mostrar una image:
clip_image010
Para colocar una imagen como el fondo de un form:
clip_image011

Como crear y guardas imagines?
Para crear una imagen nueva, se debe generar una intancia de la clase Bitmap (uno de los constructores que no requiere una imagen existente, con el método Bitmap.SetPixel o editar una existente usando Graphics.FromImage).
Para grabar una imagen, el Bitmap usa su método Bitmap.Save, ( que recibe como primer parámetro el nombre del archivo y como segundo el formato en que se desea almacenar la imagen).
Ejemplo:
clip_image013

Como usar Iconos?
Los iconos son bitmaps transparentes, de un tamaño especifico, para expresar el estado en Windows. Una forma simple de agregar iconos a un form es con los métodos Graphics.DrawIcon o Graphics.DrawIconUnstretched:
clip_image014
O
clip_image015
Se puede editar un Icono, llamando al método Icon.ToBitmap para crear un bitmap que puede ser editado.

Lección 3 – Formateando texto


Como adherir texto a gráficos?
Para agregar texto a una imagen, debemos:
1. Crear un objeto graphics
2. Crear un objeto Font
3. crear un objeto Brush (opcional)
4. Utilizar el método Graphics.DrawString y especificar la ubicación del texto.


Como crear un objeto Font?
La clase fonts tiene 13 sobrecargas de su contructor, el más simple es pasarle la familia de la fuente(string) ej: “arial”, el tamaño (float/int)y el estilo (fontStyle).
Ejemplo:
clip_image016
O pasándole un FontFamily
clip_image017
Y si necesitamos leer el tipo de fuente desde un string, se puede usar la clase FontConverter (no es muy recomendada porque puede generar errores)
clip_image018


Como escribir texto?
Después de crear un objeto font, se debe crear un brush para definir cómo se va a rellenar el texto. Para agregar el texto a una imagen se llama a Graphics.DrawString:
clip_image019


Como controlar el formateo de texto?
.Net framework brinda control sobre la alineación y dirección del texto usando la clase StringFormat.
Los miembros más importantes de StringFormat son:
image
Ejemplo de utilización de StringFormat:

clip_image020

jueves, 31 de marzo de 2011

Ejercicio. Servicio web que calcula la letra del DNI


Crea un servicio web y una interfaz que lo use en la que, introduciendo el DNI de una persona, obtenemos su letra correspondiente.

NOTA: Puedes consultar el algoritmo necesario y servirte del código de este link

Ejercicio. Consultar información de códigos IANA


Utiliza el siguiente servicio web, http://xmethods.com/ve2/ViewListing.po;jsessionid=eNKpjiPDB3WDG5g4ePRdh4uL?key=467143, para crear una interfaz web en la que dado el dominio primario de internet de un país (código IANA) nos muestre su nombre, latitud y longitud.

Ejercicio. Habilitar acceso por login.


A la aplicación web del último ejemplo posteado ("Consulta de notas de un alumno") vamos a incluirle un control de acceso de manera que sólo el usuario que nosotros registremos pueda utilizarla. Sigue los pasos:

Primero vamos a crear el formulario para loguearnos:
  1. Abre la solución de consulta de notas de un alumno.
  2. En el explorador de soluciones haz clic con el botón derecho del ratón sobre la raíz del árbol de exploración que representa el proyecto y selecciona la opción "Agregar nuevo elemento"
  3. En el cuadro de diálogo selecciona "Web Forms" y ponle como nombre "Login.aspx". Recuerda marcar C# como lenguaje de nuestro nuevo Web Form.
  4. Accede a la vista diseño de Login.aspx e inserta un objeto "Login". Lo encontrarás en el cuadro de herramientas, en el subgrupo "Inicio de sesión"
Ahora, para proteger el conjunto de nuestra aplicación la meteremos en una subcarpeta dentro del sitio:
  1. En el explorador de soluciones haz clic con el botón derecho del ratón sobre la raíz del árbol de exploración que representa el proyecto y selecciona la opción "Nueva carpeta". Ponle de nombre "Aplicacion".
  2. Arrastra los archivos que forman parte de la aplicación a la nueva subcarpeta, esto es, "ConsultarNotas.aspx" y "ResultadoForm.aspx". No obstante, no arrastres el archivo "web.config"
Nos queda crear un usuario y darle los permisos apropiados:

  1. Vuelve a la vista diseño de Login.aspx, selecciona el control Login y haz clic en la fecha de la parte superior derecha para abrir sus opciones. Selecciona "Administrar sitio web"
  2. Se abrirá una ventana de configuración en el navegador.
  3. En la pestaña "Página principal" haz clic en "Seguridad".
  4. Ahora, haz clic en "Utilice el Asistente para la configuración de seguridad para configurar la seguridad paso a paso" y se iniciará un asistente de configuración.
  5. El paso 1 es la bienvenida. Simplemente haz clic en "Siguiente"
  6. En el paso 2, "Seleccionar método de acceso", marca la opción "Desde Internet". Haz clic en "Siguiente"
  7. Ignora los pasos 3 y 4 pulsando en "Siguiente"
  8. En el paso 5, "Agregar nuevos usuarios", te aparecerá un formulario para crear un nuevo usuario. Rellena todos los campos y haz clic en "Siguiente"
  9. El paso 6 te permite añadir reglas de acceso. Tenemos que centrarnos en la subcarpeta que queremos proteger, esto es, la subcarpeta "Aplicacion". Así que selecciónala en el árbol de la izquierda expandiendo primero el nodo principal (clic en el símbolo [+]).
  10. Debes añadir dos reglas: la primera que deniegue el permiso a los usuarios anónimos y la segunda que permita el acceso al usuario que creaste en el paso 5. No olvides pulsar el botón "Agregar esta regla" una vez configuradas las opciones para que quede guardada.
  11. Al hacer clic en "Siguiente" habrás terminado la configuración.
Finalmente, añadimos unos pequeños ajustes al archivo "web.config". En realidad, ahora tendrás dos "web.config". Si haces clic con el botón derecho en la carpeta "Aplicación" en el explorador de soluciones y seleccionas la opción "Actualizar carpeta" verás que el asistente te ha añadido un archivo "web.config" en la subcarpeta. Si lo abres verás las reglas de acceso definidas:

Aclarado esto, vamos a abrir el otro "web.config", el que está en la raíz del sitio web y busca la etiqueta . Como puedes observar, está cerrada, no se ha incluido nada en ella. Simplemente ábrela y añade las siguientes etiquetas para indicar la página de login a la que debe redirigirnos la aplicación en caso de que intentemos acceder a un recurso protegido sin habernos logueado así como la página por defecto a la que se redirigirá el flujo una vez que el login ha tenido éxito.



Ya puedes ejecutar la aplicación y comprobar que funciona. Es importante que limpies las cookies del navegador entre prueba y prueba porque puede suceder que pienses que la aplicación te está dejando acceder directamente a la página protegida sin haber hecho login cuando quizás no haya expirado el tiempo máximo de login de un acceso correcto anterior.

Debes verificar que:

  1. Si escribes la URL de la página "ConsultarNotas.aspx" en el navegador, te redirige a la página de login.
  2. Si ingresas correctamente el usuario y la contraseña te redirige a la aplicación para consultar las notas.
  3. Puedes seguir accediendo a "ConsultarNotas.aspx" aunque cierres la pestaña del navegador y vuelvas a entrar, pero siempre dentro del límite de tiempo establecido en el archivo de configuración.


miércoles, 30 de marzo de 2011

Ejemplo. Consulta de notas de un alumno




En esta aplicación de ejemplo, veremos cómo incorporar accesos a bases de datos desde formularios web usando los controles de Visual Web Developer. Además revisaremos otros aspectos como las cookies y la interacción entre varios formularios web. Consiste en una página de consulta donde un alumno introduciendo su clave o número de control podrá consultar las notas de las distintas materias en las que está matriculado.

Trata de realizar algo similar con esta base de datos de Libros. Simplemente utiliza la tabla BOOKS para realizar consultas por género (campo DETCAT).

martes, 29 de marzo de 2011

Ejemplo de control de usuario personalizado

Examina este ejemplo de control de usuario personalizado. En él se implementa un cuadro de texto que nos avisa de que el dato introducido debe ser numérico en caso de que hayamos introducido caracteres no numéricos.

Puedes seguir el ejemplo paso a paso en este tutorial. La única diferencia es que en él en vez de colocar en el cuadro de texto un aviso simplemente se vacía.

Ejercicio. Conversor de moneda

Crea un sencillo conversor de moneda que sea capaz de pasar valores a Euros, Dólares americanos y Rublos sabiendo que a día de hoy 1 € = 1.4083 USD y 1€= 39.9563 RUB. No obstante, y para poder modificar dichos valores en un futuro, inclúyelos como parámetros en web.config.

Asimismo, utilizando cookies o sesiones, haz que en la etiqueta del resultado siempre se muestre la última conversión aunque se cierre la ventana del navegador y se vuelva a entrar, siempre que no expire el tiempo de la sesión.

Por otra parte, convierte el campo de texto donde se introduce la cantidad en un campo obligatorio utilizando un objeto de validación.

Haz clic aquí para descargar una posible solución

Ejemplo del uso de sesiones en ASP.NET


En este ejemplo se emplea una variable de sesión BackgroundColor para mantener el color de fondo elegido por el usuario en el primer acceso al servidor en solicitudes posteriores, no pudiéndose variar mientras no expire el tiempo máximo de la sesion.

Solución al ejercicio propuesto de Threads "pang-ping-pong-pung"


using System;
using System.Threading;

namespace PangPingPongPung
{


public class Contador
{
const int NUM_HILOS=4;
private int Turno;
private string[] Mensajes={"pang", "ping", "pong", "pung"};

public Contador(int Turno)
{
this.Turno=Turno;
}

public void Incrementar()
{
Turno++;
}

public string ValorActual()
{
return (Turno%NUM_HILOS).ToString();
}

public string MensajeActual()
{
return Mensajes[Turno%NUM_HILOS];
}

}

class Program

{
private Contador c;
const int NUM_HILOS=4;
public Program(int turnoInicial)
{
Thread [] vThreads=new Thread[4];
c=new Contador(turnoInicial);
for (int I=0; I<NUM_HILOS; I++) {
vThreads[I]=new Thread(new ThreadStart(pangpingpongpung));
vThreads[I].Name=I.ToString();
vThreads[I].Start();
if (I<NUM_HILOS-1)
vThreads[I].Join(20);
else
vThreads[I].Join(10000);
}
for (int I=0; I<NUM_HILOS; I++)
vThreads[I].Abort();

Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}

public static void Main(string[] args)
{
Program p=new Program(0);
}




public void pangpingpongpung()
{
while (true) {
Monitor.Enter(c);
try{
if (Thread.CurrentThread.Name==c.ValorActual()) {
Console.WriteLine(c.MensajeActual());
c.Incrementar();
int esperaAleatoria=new Random(
DateTime.Now.Millisecond).Next()%500;
Thread.Sleep(esperaAleatoria);
}
}
finally {
Monitor.Exit(c);
}
}
}
}
}

lunes, 28 de marzo de 2011

Ejemplo. Visto en clase: Iniciación a ASP .NET

Archivo default.aspx.cs

using System;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Xml.Linq;
using System.Collections;
using System.Collections.Specialized;


public partial class _Default : System.Web.UI.Page
{

protected void BtnEnviar_Click(object sender, EventArgs e)
{
EtiRespuesta.Visible = true;
EtiRespuesta.Text = "Hola " + TxtNombre.Text;

Response.Write("Estoy escribiendo con el objeto Response
");
Response.Write("Información del objeto Request " +
Request.Browser.Browser+"
);


// Visualizando la colección de parámetros
// del archivo web.config
NameValueCollection Coleccion;

Coleccion=(NameValueCollection)Context.GetConfig("appSettings");
for (int iCtr = 0; iCtr < Coleccion.Count; iCtr++)
{
String s = Coleccion.Keys[iCtr];
Response.Write(s+" "+Coleccion[s]+"
");
}

}
protected void Page_Load(object sender, EventArgs e)
{
if (Request.Cookies["ultimaVisita"] == null)
Response.Write("Es tu primera visita");
else
Response.Write("Tu última visita fue: "+
Request.Cookies["ultimaVisita"].Value);

Response.Cookies["UltimaVisita"].Value=DateTime.Now.ToString();
Response.Cookies["UltimaVisita"].Expires=DateTime.Now.AddMinutes(2);
}
}

Desarrollo de aplicaciones Web con Microsoft ASP.NET utilizando Visual Studio .NET

Si utilizas un navegador distinto a Microsoft Explorer puede que no visualices adecuadamente el curso. Haz clic en la imagen para iniciarlo



Haz clic en la imagen para bajar el contenido del curso en PDF

sábado, 26 de marzo de 2011

Ejercicio. Ping Pong concurrente.

Sincroniza dos threads de manera que uno escriba Ping por pantalla sólo cuando el anterior allá escrito Pong, alternando de forma perfecta las dos escrituras. Emplea los métodos Enter() y Exit() de la clase Monitor.

NOTA: debido al boxing y unboxing (conversión de los tipos primitivos a su respectivo objeto del CTS y viceversa), bloquear tipos primitivos puede hacer que no funcionen los bloqueos. Envuelve dichos tipos en una clase creada por ti para evitarlo.

Haz clic en la imagen para descargar la solución al problema de Ping Pong con monitores.


PROBLEMA PROPUESTO. Realiza el mismo ejercicio pero con cuantro hilos que escriban de forma alterna Pang-Ping-Pong-Pung

Dudas alumnos. Qué diferencia hay entre Monitor.Try() y Monitor.TryEnter()

Con TryEnter si el recurso está libre se bloquea, si no, se espera el tiempo especificado. En caso de que el tiempo expire y el recurso siga bloquedo se devuelve False para poder continuar con otros procesos si es preferible a esperar por conseguir el recurso compartido.


public bool WaitToAddElement(object qValue, int waitTime)
{
if(!Monitor.TryEnter(m_inputQueue,waitTime))
return false;
m_inputQueue.Enqueue(qValue);
Monitor.Exit(m_inputQueue);

return true;
}




En cambio, con Enter, el hilo se bloquearía sin condiciones si el recurso está siendo usado por otro hilo.

public void AddElement(object qValue)

{
Monitor.Enter(m_inputQueue);
m_inputQueue.Enqueue(qValue);
Monitor.Exit(m_inputQueue);
}

Suspend y Resume obsoletos. Cómo resolver el problema

ANTES:

private Thread myThread;

private void WorkerThread()
{
myThread
= Thread.CurrentThread;
while (true)
{
myThread
.Suspend();
//Ejecutar tareas
}
}

public void StartWorking()
{
myThread
.Resume();
}


***************************************

AHORA:



...

private static EventWaitHandle wh;

...

wh = new EventWaitHandle(false,EventResetMode.AutoReset);

...

private
void WorkerThread()
{


while(true)
{
wh.WaitOne();

//Ejecutar tareas
}
}

public void StartWorking()
{
wh.Set();

}

jueves, 24 de marzo de 2011

Ejercicio. Repaso


A partir de los pasos vistos en los ejercicios anteriores de ADO.NET trata de realizar el ejercicio planteado (Haz clic en la imagen para verlo). El único cambio a adoptar es utilizar una base de datos Access en lugar de una base de datos SQL Server. Trata de guiarte por los conocimientos adquiridos más que por las propuestas del ejemplo, en caso de duda.

Ejercicio. Cargar el archivo de Base de Datos .mdb al arrancar la aplicación




Si quisiésemos que la aplicación diese la oportunidad de cargar un archivo de Access específico al abrir el formulario principal, sólo tendríamos que añadir un objeto OpenFileDialog para cargar la ruta del archivo:


public MainForm()
{

OpenFileDialog of = new OpenFileDialog();
of.ShowDialog();
string direccion = of.FileName;

con = new OleDbConnection(

"Provider=Microsoft.Jet.OLEDB.4.0;
Data Source="+direccion+";
Persist Security Info=True");

con.Open();
InitializeComponent();


}

Libros. Para saber más... ADO .NET step by step

[Haz clic en la portada del libro para descargarlo]


  • Conectarse a orígenes de datos externos, incluyendo bases de datos y otras formas de almacenamiento.
  • Uso del framework ADO.NET para interactuar con almacenes de datos subyacentes.
  • Crear modelos de entidad con herramientas de diseño gráfico en Visual Studio 2010
  • Vincular datos directamente a tus formularios Windows y Web para proporcionar información a los usuarios.
  • Manejar datos e información aislada sin estar conectado directamente a una base de datos.

Ejercicio. Habilitar un cuadro de búsqueda


Añade un cuadro de búsqueda simple de tal modo que al introducir el nombre de la persona buscada se marque el registro correspondiente a la misma. En caso contrario, se visualizará una ventana de alerta advirtiéndonos de que el nombre no existe. Para ello, inserta mediante el diseñador de formularios un cuadro de texto (llámale txtBusquedaNombre) y un botón (llámale btnBusqueda) En el método que atienda el evento de clic incluye un código como este adaptándolo a los nombres de objetos de tu proyecto (aquí bs es el objeto BindingSource)

  int elementoEncontrado =
bs.Find("Nombre",textBusquedaNombre.Text );
if (elementoEncontrado>=0)
bs.Position = elementoEncontrado;
else MessageBox.Show("Nombre no encontrado");

Ejercicio. Insertar controles de navegación


Partiendo de tu proyecto del ejercicio anterior o de este proyecto ya resuelto, añade una barra de navegación que permita moverse por los registros de la tabla. Para ello, inserta utilizando el IDE de Sharp Develop un control de tipo BindingNavigator. Para mayor claridad del código, llámale Navegador. El navegador ya implementa toda la funcionalidad necesaria; lo único que tienes que hacer es asociarlo al objeto BindingSource vinculado a los datos. Es decir añade el código marcado en rojo:


ds=new DataSet();
OleDbCommand cmd = new OleDbCommand(
"Select Id, Nombre, Edad from Persona",con);
da=new OleDbDataAdapter(cmd);
cb = new OleDbCommandBuilder(da);
da.Fill(ds);
bs=new BindingSource();
bs.DataSource=ds.Tables[0];
dgPersona.DataSource=bs;
Navegador.BindingSource=bs;


Si haces clic sobre el objeto BindingNavigator en el diseñador de formularios aparecerá una flecha negra en la esquina superior derecha del control desde la que puedes acceder a la opción Dock (anclar). Selecciona Button para colocar el navegador en la parte inferior de la ventana tal y como se muestra en la figura, de manera que no se solape con los controles ya dispuestos sobre el formulario principal.

*************************************


Ahora imagina que no dispusieses del objeto BindingNavigator y tuvieses que conseguir la misma funcionalidad de desplazamiento con botones y una etiqueta que muestre en qué registro nos encontramos del total. Descarga el siguiente proyecto de codeproject.com en el que se implementa este aspecto para una base de datos SQL Server. Aunque no lo podrás ejecutar directamente sí se representa en el diseñador de formularios, lo que te permitirá rastrear los métodos asociados a los eventos de clic de cada botón. En realidad, el proceso resulta tan simple como invocar a los métodos moveFirst(), moveLast(), moveNext() y movePrevious() del objeto BindingSource con alguna lógica adicional. Haz lo mismo sobre tu proyecto.

miércoles, 23 de marzo de 2011

Ejercicio. Vincular campos de texto a un BindingSource.


Sobre el proyecto del ejercicio anterior, vamos a hacer que cada vez que haga clic en un registro del DataGridView, automáticamente se visualice el nombre y la edad de la persona seleccionada en los cuadros de texto correspondientes. Para ello modifica el método que trata la carga del formulario de la siguiente manera:


void MainFormLoad(object sender, EventArgs e)
{
this.ActualizarGrid();
this.txtNombre.DataBindings.Add(
new Binding("Text",bs,"Nombre",true));
this.mstxtEdad.DataBindings.Add(
new Binding("Text",bs,"Edad",true));
}

Aquí, this.txtNombre y this.mstxtEdad son los campos de texto del Nombre y la Edad de la persona respectivamente; bs es nuestro objeto BindingSource y "Nombre" y "Edad" son los campos de la tabla Persona en la base de datos. Text es la propiedad de los controles en la que almacenamos los valores y el valor booleano true me indica que dejo habilitado el formateo de datos.

Ejercicio. Guardar cambios de un DataGridView en la Base de Datos


Partiendo de este proyecto, similar al que ya usamos para agregar personas a una tabla pero usando un DataSet en lugar de un DataReader, trata de incluir un objeto BindingSource que permita guardar las modificaciones o eliminaciones que hagamos sobre el DataGridView. Para ello, añade a la interfaz un botón para guardar los cambios y ten en cuenta los pasos necesarios que se indican a continuación. Añade los que no están implementados para dotar a la aplicación de la nueva funcionalidad.

// necesitamos una cadena de conexión que variará según el tipo de base de datos a la que nos conectemos.

string connString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\\miBaseDeDatos.mdb";

La cadena de conexión está formada por dos partes: un proveedor y un origen de datos. El proveedor es el motor de base de datos que estamos usando, en este caso un motor Jet de Microsoft. El origen de datos para una base de datos Access es simplemente la trayectoria del fichero .mdb

Ahora usaremos la cadena de conexión para conectarnos y conseguir los datos que queremos.

//crear la conexion
string conn = new OleDbConnection(connString);

//crear la consulta a la base de datos
string query = "SELECT * FROM MiTabla";

//crear un adaptador para ejecutar la consulta
OleDbDataAdapter dAdapter = new OleDbDataAdapter(query, conn);

//crear un constructor de sentencias
OleDbCommandBuilder cBuilder = new OleDbCommandBuilder(dAdapter);

//crear un DataTable que almacene el resultado de la consulta
DataSet dSet = new DataSet();

//rellenar el DataSet con la información que le pasa el adaptador
dAdapter.Fill(dSet);

*******

Ahora veremos como se sincroniza el DataSet con la información de la base de datos a traves del DataGridView:

//creamos el DataGridView
DataGridView dgView = new DataGridView();

//creamos un BindingSource para sincronizar la información del DataSet y la del DataGridView
BindingSource bSource = new BindingSource();

//el origen de datos del BindingSource es la única tabla de datos que contiene el DataSet,
// la primera de la colección Table
bSource.DataSource = dSet.Table[0];

//y el origen de datos del DataGridView es el BindingSource
dgView.DataSource = bSource;

*********


Finalmente, podemos habilitar un botón que al hacer clic sobre él actualice los cambios del DataGridView pasándolos al DataSet y finalmente a la base de datos. Para ello en el método que trate el evento de clic sólo hay que añadir:


dAdapter.Update(dSet);


*********

NOTA: la solución a este probrema sería prácticamente idéntica si en lugar de un DataSet, utilizamos un DataTable, con la única diferencia de que cuando se le asigna el origen de datos al DataBinding éste sería directamente el DataTable.

Solución...al problema planteado de listar los tipos de películas en un ComboBox.


  1. Incluir en el formulario un ComboBox. Le llamaremos, por ejemplo, ComboTipo. También una etiqueta que identifique el campo tipo de película.
  2. Al método que trata el evento de clic de dicho ComboBox le añadimos el siguiente código:

    String sql = "SELECT typeID, Type FROM movietype";
    Conexion.Open();
    OleDbDataAdapter da = new OleDbDataAdapter(sql, Conexion);
    DataTable dt = new DataTable("TiposPeliculas");
    da.Fill(dt);

    this.ComboTipo.DataSource = dt;
    this.ComboTipo.DisplayMember = "Type";
    this.ComboTipo.ValueMember = "typeID";
    Conexion.Close();

    Observa que aprovechamos el objeto "Conexion" que ya teníamos. En cambio, necesitamos modificar la consulta del adaptador. Lo mejor es crear un adaptador nuevo, como se indica aquí. Con esto, aparecerá la lista desplegable de tipos de películas cada vez que hagamos clic en el cuadro combinado. No obstante, el valor que nos interesa recoger es el identificador del tipo de película. Ya solo queda pasar dicho valor a la sentencia de inserción.
  3. En el método que atiende el evento de clic del botón Insertar, modificamos la sentencia de inserción. A los dos campos de prueba que ya introducíamos (en este ejemplo: título de la película y distribuidora) le añadimos el valor del cuadro Combinado referido al tipo de la película.

    void BtnInsertarClick(object sender, System.EventArgs e)
    {
    string strTitulo = "";
    string strDistribuidor = "";

    strTitulo = TextTitulo.Text;
    strDistribuidor = TextDistribuidor.Text;
    OleDbConnection con = new OleDbConnection
    ("Provider=Microsoft.Jet.OLEDB.4.0;
    Data Source=moviedb.mdb");
    con.Open();
    OleDbCommand Comando2 = new OleDbCommand(
    "Insert into movie (Title, Publisher, typeID)
    Values ('" + strTitulo + "', '" + strDistribuidor
    + "',"+ComboTipo.SelectedValue.ToString()+")",con);
    Comando2.ExecuteNonQuery();
    con.Close();
    mostrarDatos();
    }

  4. Ahora, cada vez que incluyes una nueva película, aparecerá correctamente insertado su tipo.

martes, 22 de marzo de 2011

Ejemplo. Enlazar un DataTable con un ComboBox

En este caso, queremos mostrar el nombre de los bancos en la lista desplegable y almacenar como valor del ComboBox su ID.


Puedes enlazar un control ComboBox con un objeto DataTable:

using System.Data.SqlClient;

try
{
// Construimos la consulta SQL de selección
String sql = "SELECT IdBanco, Nombre FROM Bancos";

// Creamos un adaptador de datos

OleDbDataAdapter da = new OleDbDataAdapter(sql, cnn);

// Creamos un nuevo objeto DataTable

DataTable dt = new DataTable("Bancos");

// Rellenamos el objeto DataTable

da.Fill(dt);

// Configuramos el control ComboBox

this.comboBox1.DataSource = dt;
this.comboBox1.DisplayMember = "Nombre";
this.comboBox1.ValueMember = "IdBanco";
}

catch (Exception ex) {
MessageBox.Show (ex.Message);
}
}

Ejemplos ADO.NET - Familiarizarse con objetos de acceso a bases de datos y herramientas del IDE

1.- Crea una nueva aplicación Windows en Sharp Develop.
2.- Añade en el panel de Herramientas del diseñador de interfaz (pestaña Data) los objetos OleDb para poder conectarnos a una Base de Datos Access.
3.- Descarga esta base de datos Access de ejemplo y guárdala en la subcarpeta bin/debug de la carpeta del proyecto para que sea directamente accesible desde la aplicación.
4.- Inserta los siguientes objetos OleDb:

  • un objeto OleDbConnection (llámale Conexion) y en la propiedad ConnectionString introduce la cadena "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=moviedb.mdb"
  • un objeto OleDbCommand (llámale Comando) con la propiedad CommandText "SELECT movieID, Title, Publisher, Previewed, MovieYear, Type FROM movie, movieType WHERE movietype.typeID = movie.typeID", en la propiedad Connection selecciona el objeto Conexion.
  • un objeto OleDbDataAdapter (llámale Adaptador) ; en el apartado de SelectCommand selecciona Comando y asegúrate de que la propiedad Connection del subgrupo toma el valor del objeto Conexion.
5.- Inserta un objeto de tipo DataGridView en el formulario y llámale Cuadricula.

6.- Añade el siguiente método a la clase MainForm en el archivo MainForm.Designer.cs e invócalo desde el constructor de MainForm en MainForm.cs después de la inicialización de componentes.

public void mostrarDatos()
{
Conexion.Open();
Cuadricula.Columns.Clear();
DataTable TablaDatos=new DataTable();
Adaptador.Fill(TablaDatos);
Cuadricula.DataSource=TablaDatos;

Conexion.Close();
}
7.- Ejecuta el proyecto y deberás ver un listado con todas las películas que incluye la base de datos, incluyendo el género.


8.- Descarga este otro proyecto con una base de datos Access. Hazlo funcionar y fíjate en las diferencias que supone emplear un objeto OleDbDataReader. Descarga aquí la base de datos en formato mdb

9.- Aquí tienes un ejemplo más completo de empleo de bases de datos en C# que hace uso de la misma base de datos que el ejemplo inicial. Escudríñalo e intenta agregar alguna de sus características al ejemplo inicial (borrado o edición de datos, por ejemplo)

10. Puedes consultar este tutorial de manejo de los objetos ADO .NET

lunes, 21 de marzo de 2011

Ejercicio. Cálculo del interesés y capital acumulado


Crea una aplicación sencilla que dado el capital y la tasa de interés calcule el interés conseguido y el capital final. La fórmula para el cálculo del interés es I=(C*t)/100 siendo C el capital inicial y r la tasa de interés nominal anual en tanto por ciento. El capital acumulado será el capital inicial más el interés.


La lógica principal de acuerdo a esta fórmula sería la siguiente:


Decimal cap, tp, res;
String formato = "{0:#,###,###,##0.00}";
try
{
cap = Convert.ToDecimal(Capital.Text);
tp = Convert.ToDecimal(TpInterés.Text);
}
catch (FormatException exc)
{
cap = 0; tp = 0;
}

// Cálculos de los resultados
res = Convert.ToDecimal(cap * tp / 100);
InterésPro.Text = String.Format(formato, res);
res += cap;
CapitalAc.Text = String.Format(formato, res);