on domingo, 16 de diciembre de 2012

Que tal, buen día,  el día de hoy graficaremos un tablero de ajedrez en WPF.

1.- Crear un proyecto en WPF.


WPFChessProject - Microsoft Visual Studio (Administrador)_2012-12-08_18-24-01


2.- Crear un control de usuario para un tablero de ajedrez.


WPFChessProject - Microsoft Visual Studio (Administrador)_2012-12-08_18-18-59

Aquí les pongo el código en XAML.


<UserControl x:Class="WPFChessProject.ChessBoard"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             mc:Ignorable="d"
             d:DesignHeight="800" d:DesignWidth="800">
    <Grid x:Name="grdPrincipal">
        <StackPanel x:Name="stkBoard">
           
        </StackPanel>
    </Grid>
</UserControl>


Ahora construiremos nuestro tablero.

Primero que nada, lo que necesitamos es definir el color de las piezas blancas y de las piezas negras, por lo que necesitamos dos propiedades de tipo color.

public Color colorOfWhitePiece { get; set; }

public Color ColorOfBlackPiece { get; set; }

También es necesario tener el conjunto de casillas agrupadas.
public List<StackPanel> Boxs { get; set; }

Aquí las agrupamos en una lista de StackPanels que nos permitirán mostrar cualquier objeto derivado de la clase UIElement, esto con el fin de que si el proyecto crece se podrán crear controles como piezas de ajedrez para simular una partida de ajedrez.
El control StackPanel es un contenedor que nos permite tener una serie de controles derivados con el fin de hacer uso de los mismos.

En los controles de WPF, en los contenedores se cuenta con la propiedad Childrens, que es una lista de UIElement que son los objetos que se graficaran en nuestra pantalla.

Una vez que tenemos declaradas nuestras propiedades, es necesario crear e implementar un método que nos permita renderear nuestro tablero de ajedrez.


        public void RenderBoard()
        {
            StackPanel box;
            bool isWhite = true;

            for (int i = 0; i < 8; i++)
            {
                StackPanel rowBoxes = new StackPanel();
                rowBoxes.Orientation = Orientation.Horizontal;

                for (int j = 0; j < 8; j++)
                {
                    box = new StackPanel();
                    box.Width = this.Width / 8;
                    box.Height = this.Height / 8;

                    if (isWhite)
                    {
                        box.Background = new SolidColorBrush(ColorOfWhitePiece);
                        isWhite = false;
                    }
                    else
                    {
                        box.Background = new SolidColorBrush(ColorOfBlackPiece);
                        isWhite = true;
                    }

                    rowBoxes.Children.Add(box);

                    Boxs.Add(box);
                }

                if (isWhite)
                    isWhite = false;
                else
                    isWhite = true;

                this.stkBoard.Children.Add(rowBoxes);
            }
        }

En el método RenderBoard creamos dos variables locales, una variable representa una casilla de nuestro tablero de ajedrez y otra variable booleana   que nos permite saber si la casilla es color blanco o negro según el ajedrez.

StackPanel box;

bool isWhite = true;

También tenemos dos ciclos for que nos permiten recorrer el tablero de ajedrez
            for (int i = 0; i < 8; i++)
            {
                StackPanel rowBoxes = new StackPanel();
                rowBoxes.Orientation = Orientation.Horizontal;

                for (int j = 0; j < 8; j++)
                {
                    box = new StackPanel();
                    box.Width = this.Width / 8;
                    box.Height = this.Height / 8;


Las dos primeras lineas representan una fila de un tablero de ajedrez con ocho columnas

StackPanel rowBoxes = new StackPanel();
rowBoxes.Orientation = Orientation.Horizontal;


en las primeras líneas del segundo for tenemos la instancia de una casilla de ajedrez y la asignación de ancho y alto.


                    box = new StackPanel();
                    box.Width = this.Width / 8;
                    box.Height = this.Height / 8;

la condicional nos indica cuando tenemos que graficar una casilla blanca o negra


                                   if (isWhite)
                    {
                        box.Background = new SolidColorBrush(ColorOfWhitePiece);
                        isWhite = false;
                    }
                    else
                    {
                        box.Background = new SolidColorBrush(ColorOfBlackPiece);
                        isWhite = true;
                    }


        


Terminando el for de las columnas, lo que necesitamos es cambiar el color de nuestra bandera booleana que nos indica de qué color es la casilla.

Después de esto, solo basta agregar la fila de casillas a nuestra stack panel stkBoard


  if (isWhite)
                    isWhite = false;
                else
                    isWhite = true;

                this.stkBoard.Children.Add(rowBoxes);

aquí les dejo todo el codigo fuente del user control.







 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Text;  
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Data;  
 using System.Windows.Documents;  
 using System.Windows.Input;  
 using System.Windows.Media;  
 using System.Windows.Media.Imaging;  
 using System.Windows.Navigation;  
 using System.Windows.Shapes;  
 namespace WPFChessProject  
 {  
   /// <summary>  
   /// Lógica de interacción para ChessBoard.xaml  
   /// </summary>  
   public partial class ChessBoard : UserControl  
   {  
     public List<StackPanel> Boxs { get; set; }  
     public Color ColorOfWhitePiece { get; set; }  
     public Color ColorOfBlackPiece { get; set; }  
     public ChessBoard(Color pieceWhiteColor,Color pieceBlackColor,double width, double height)  
     {  
       InitializeComponent();  
       Boxs = new List<StackPanel>();  
       this.Width = width;  
       this.Height = height;  
       stkBoard.Orientation = Orientation.Vertical;  
       this.ColorOfWhitePiece = pieceWhiteColor;  
       this.ColorOfBlackPiece = pieceBlackColor;  
       RenderBoard();  
     }  
     public void RenderBoard()  
     {  
       StackPanel box;  
       bool isWhite = true;  
       for (int i = 0; i < 8; i++)  
       {  
         StackPanel rowBoxes = new StackPanel();  
         rowBoxes.Orientation = Orientation.Horizontal;  
         for (int j = 0; j < 8; j++)  
         {  
           box = new StackPanel();  
           box.Width = this.Width / 8;  
           box.Height = this.Height / 8;  
           if (isWhite)  
           {  
             box.Background = new SolidColorBrush(ColorOfWhitePiece);  
             isWhite = false;  
           }  
           else  
           {  
             box.Background = new SolidColorBrush(ColorOfBlackPiece);  
             isWhite = true;  
           }  
           rowBoxes.Children.Add(box);  
           Boxs.Add(box);  
         }  
         if (isWhite)  
           isWhite = false;  
         else  
           isWhite = true;  
         this.stkBoard.Children.Add(rowBoxes);  
       }  
     }  
   }  
 }  



3.- Consumir el Control de usuario.

ahora en nuestra aplicación principal del proyecto tendremos que instanciar nuestro tablero, les muestro el XAML de la aplicación principal.


 <Window x:Class="WPFChessProject.MainWindow"  
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
     Title="MainWindow" Height="350" Width="525">  
   <Grid x:Name="grdPrincipal">  
   </Grid>  
 </Window>  


Ahora veamos el codebehind:

 using System;  
 using System.Collections.Generic;  
 using System.Linq;  
 using System.Text;  
 using System.Windows;  
 using System.Windows.Controls;  
 using System.Windows.Data;  
 using System.Windows.Documents;  
 using System.Windows.Input;  
 using System.Windows.Media;  
 using System.Windows.Media.Imaging;  
 using System.Windows.Navigation;  
 using System.Windows.Shapes;  
 namespace WPFChessProject  
 {  
   /// <summary>  
   /// Lógica de interacción para MainWindow.xaml  
   /// </summary>  
   public partial class MainWindow : Window  
   {  
     public MainWindow()  
     {  
       InitializeComponent();  
       ChessBoard chessBoard = new ChessBoard(Colors.Green, Colors.Black,400,400);  
       grdPrincipal.Children.Add(chessBoard);  
     }  
   }  
 }  


Básicamente consiste en crear una instancia de ChessBoard y agregarlo al gridPrincipal y listo.



4.- Ejecutar la aplicación.:


MainWindow_2012-12-08_19-57-32


Y así lucirá nuestro tablero de ajedrez ;)

Que pasen buen día, buena vibra 
on domingo, 9 de diciembre de 2012

Buen día, ahora les traigo la programación para el front en esta serie de entradas de programación en capas, como ya les había comentado, para el ejemplo práctico usaremos las pantallas prehistóricas de Windows forms, lo primero que tenemos que hacer, es diseñar nuestra pantalla, a la cual les pondré el código del designer y les pegare una foto de cómo debe lucir nuestra pantalla.


LoginPrueba - Microsoft Visual Studio (Administrador)_2012-12-09_11-18-19

básicamente solo necesitamos ingresar el nombre de usuario y la contraseña a la cual tenemos que presionar el botón para poder autenticarnos.

para poder recrear dicho código  lo que necesitamos es copiar tal cual el código del designer. se los pongo a  continuación.


 namespace LoginPrueba  
 {  
   partial class Form1  
   {  
     /// <summary>  
     /// Variable del diseñador requerida.  
     /// </summary>  
     private System.ComponentModel.IContainer components = null;  
     /// <summary>  
     /// Limpiar los recursos que se estén utilizando.  
     /// </summary>  
     /// <param name="disposing">true si los recursos administrados se deben eliminar; false en caso contrario, false.</param>  
     protected override void Dispose(bool disposing)  
     {  
       if (disposing && (components != null))  
       {  
         components.Dispose();  
       }  
       base.Dispose(disposing);  
     }  
     #region Código generado por el Diseñador de Windows Forms  
     /// <summary>  
     /// Método necesario para admitir el Diseñador. No se puede modificar  
     /// el contenido del método con el editor de código.  
     /// </summary>  
     private void InitializeComponent()  
     {  
       this.btnAcceder = new System.Windows.Forms.Button();  
       this.txtPassword = new System.Windows.Forms.TextBox();  
       this.txtUser = new System.Windows.Forms.TextBox();  
       this.label1 = new System.Windows.Forms.Label();  
       this.label2 = new System.Windows.Forms.Label();  
       this.panel1 = new System.Windows.Forms.Panel();  
       this.panel1.SuspendLayout();  
       this.SuspendLayout();  
       //   
       // btnAcceder  
       //   
       this.btnAcceder.Location = new System.Drawing.Point(49, 136);  
       this.btnAcceder.Name = "btnAcceder";  
       this.btnAcceder.Size = new System.Drawing.Size(75, 23);  
       this.btnAcceder.TabIndex = 0;  
       this.btnAcceder.Text = "Acceder";  
       this.btnAcceder.UseVisualStyleBackColor = true;  
       this.btnAcceder.Click += new System.EventHandler(this.btnAcceder_Click);  
       //   
       // txtPassword  
       //   
       this.txtPassword.Location = new System.Drawing.Point(13, 95);  
       this.txtPassword.Name = "txtPassword";  
       this.txtPassword.Size = new System.Drawing.Size(149, 20);  
       this.txtPassword.TabIndex = 1;  
       //   
       // txtUser  
       //   
       this.txtUser.Location = new System.Drawing.Point(13, 37);  
       this.txtUser.Name = "txtUser";  
       this.txtUser.Size = new System.Drawing.Size(149, 20);  
       this.txtUser.TabIndex = 2;  
       //   
       // label1  
       //   
       this.label1.AutoSize = true;  
       this.label1.Location = new System.Drawing.Point(10, 11);  
       this.label1.Name = "label1";  
       this.label1.Size = new System.Drawing.Size(96, 13);  
       this.label1.TabIndex = 3;  
       this.label1.Text = "Nombre de usuario";  
       //   
       // label2  
       //   
       this.label2.AutoSize = true;  
       this.label2.Location = new System.Drawing.Point(10, 69);  
       this.label2.Name = "label2";  
       this.label2.Size = new System.Drawing.Size(61, 13);  
       this.label2.TabIndex = 4;  
       this.label2.Text = "Contraseña";  
       //   
       // panel1  
       //   
       this.panel1.Controls.Add(this.label1);  
       this.panel1.Controls.Add(this.btnAcceder);  
       this.panel1.Controls.Add(this.txtPassword);  
       this.panel1.Controls.Add(this.label2);  
       this.panel1.Controls.Add(this.txtUser);  
       this.panel1.Location = new System.Drawing.Point(12, 12);  
       this.panel1.Name = "panel1";  
       this.panel1.Size = new System.Drawing.Size(187, 173);  
       this.panel1.TabIndex = 5;  
       //   
       // Form1  
       //   
       this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);  
       this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;  
       this.ClientSize = new System.Drawing.Size(215, 197);  
       this.Controls.Add(this.panel1);  
       this.Name = "Form1";  
       this.Text = "Form1";  
       this.panel1.ResumeLayout(false);  
       this.panel1.PerformLayout();  
       this.ResumeLayout(false);  
     }  
     #endregion  
     private System.Windows.Forms.Button btnAcceder;  
     private System.Windows.Forms.TextBox txtPassword;  
     private System.Windows.Forms.TextBox txtUser;  
     private System.Windows.Forms.Label label1;  
     private System.Windows.Forms.Label label2;  
     private System.Windows.Forms.Panel panel1;  
   }  
 }  


ahora tenemos que darle funcionalidad a nuestra pantalla, que en teoría, el código debiera ser más compacto, más limpio, y sin la funcionalidad de la lógica de negocios, que como el post lo indica, estamos programando en capas y esa lógica debe de estar encapsulada en el controller de nuestra aplicació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 BusinessLogicLayer;  
 namespace LoginPrueba  
 {  
   public partial class Form1 : Form  
   {  
     public Form1()  
     {  
       InitializeComponent();  
     }  
     private void btnAcceder_Click(object sender, EventArgs e)  
     {  
       //posible mejora aplicando un singleton al controller... proximamente  
       SecurityController controller = new SecurityController();  
       if (!string.IsNullOrEmpty(txtPassword.Text) && !string.IsNullOrEmpty(txtUser.Text))  
       {  
         if (controller.Autenticate(txtUser.Text, txtPassword.Text))  
           MessageBox.Show("welcome to the system");  
         else  
           MessageBox.Show("username or password is incorrect");  
       }  
     }  
   }  
 }  


Y ahora analicemos un poco el código, el botón que autentica  no es más que una condicional, que nos indica si el usuario esta autenticado o no, para esto tenemos que hacer una instancia de nuestro controller para poder acceder a la gama de métodos disponibles en el, en este caso obviamente solo hay un método, que es el de ejemplo.


Espero que les haya sido de utilidad esta serie de post que ejemplifican el trabajo en capas, obviamente esta forma de trabajar no es ley ya que se esta trabajando con una tecnología ORM de LinqToSql y ademas el diseño arquitectónico de este ejemplo puede ser mejorado y optimizado.

el objetivo de estos post fue brindar una idea clara y sobre todo dar una introducción al desarrollo en capas.

de antemano gracias por su atención.

su humilde servidor


Fernando Hoyos.
on jueves, 6 de diciembre de 2012
Ahora si por fin se vera algo de código  tanta asignación de referencias como que era aburrida pero vaya que es necesario comprenderla para conocer el manejo de dll's

primero vamos a comenzar a codificar nuestra clase SecurityController, esta clase nos permitirá autenticarnos con nuestra tabla de usuarios de la base de datos de ejemplo.

  using System;  
   using System.Collections.Generic;  
   using System.Linq;  
   using System.Text;  
   using DataLayer;  
   using System.Configuration;  
   namespace BusinessLogicLayer  
   {  
     public class SecurityController  
     {  
       public bool Autenticate(string userName, string password)  
       {  
         using (DataAccesLoginDataContext dataContext = new DataAccesLoginDataContext())  
         {  
           Users userAutenticated = (from u in dataContext.Users  
                                        where u.userName == userName && u.password == password  
                                            select u).FirstOrDefault();  
           if (userAutenticated != null)  
             return true;  
           else  
             return false;  
         }  
       }  
     }  
   }  

ahora describiremos lo que hace el metodo Autenticate


en primera instancia recibe dos parámetros, userName y password, dichos parámetros nos servirán para autenticarnos ante la base de datos.

Hecho esto tenemos que hacer una instancia de un contexto de LinqToSql

Después lo que hacemos es una consulta lambda con la entidad Users dentro del contexto creado.

preguntamos si realmente ese usuario y password trajo algún objeto autenticado.