¡Bienvenid@ a La bloguera.net! Iniciar sesión | ÚNETE a la web | Ayuda

Una de las novedades que trae Silverlight 3 es que nos permite ejecutar aplicaciones Silverlight como aplicaciones de escritorio fuera del navegador.

Esto nos da el potencial de ejecutar nuestras aplicaciones Silverlight en modo offline.

Los pasos que debemos seguir conseguir esto son los siguientes:

  1. Creamos un nuevo proyecto de tipo Silverlight. Asumiremos que tenemos instalado todo lo necesario para el desarrollo de aplicaciones Silverlight 3. Ver página oficial.image_thumb7
  2. Una vez creado el proyecto llamado en nuestro caso “FueraBrowser”, desarrollamos nuestra aplicación tal y como queremos. Para este ejemplo simplemente añadiremos un botón que lanza un mensaje cuando hacemos click sobre él.image12
  3. Abrimos el fichero AppManifest.xml e insertamos el código que se muestra a continuación. El elemento EntryPointAssembly indica el nombre del assembly que coincide con el nombre de la aplicación, el elemento EntryPointType es la clase que carga la aplicación. A parte podemos configurar el ShortName que será el nombre que se muestra en el icono del escritorio, el Title que se corresponde con el titulo de la ventana que mostrará la aplicación y finalmente del Blurb testo que se verá en la sección de “Comments”:
    <Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      EntryPointAssembly="FueraBrowser"
      EntryPointType="FueraBrowser.App">
      <Deployment.Parts>
      </Deployment.Parts>
      <Deployment.OutOfBrowserSettings>
        <OutOfBrowserSettings
          ShortName="Fuera del browser">
          <OutOfBrowserSettings.WindowSettings>
            <WindowSettings Title="Offline Fuera del browser" />
          </OutOfBrowserSettings.WindowSettings>
          <OutOfBrowserSettings.Blurb>
            Permite guardar tus tareas cuando estas offline
          </OutOfBrowserSettings.Blurb>
        </OutOfBrowserSettings>
      </Deployment.OutOfBrowserSettings>
    </Deployment>
  4. Ejecutamos la aplicación y sobre la misma, al pulsar el botón derecho del ratón nos aparecerá un menú contextual como el siguiente, que nos permite instalar la aplicación en nuestro ordenador:image_thumb34
  5. Si pulsamos “Instalar Fuera del browser en este equipo…” nos aparecerá un cuadro de instalación en que se nos da la opción de colocar el acceso directo en el Menú Inicio o en el Escritorio.image_thumb33
  6. Si pulsamos “Aceptar” finalizará la instalación y aparecerá nuestra aplicación desarrollada en Silverlight 3 pero ejecutada como una aplicación de escritorio:               image_thumb31
  7. En el menú inicio tendremos un acceso directo a la aplicación:image_thumb38
  8. Para desinstalar nuestra aplicación simplemente debemos pulsar el botón derecho del ratón sobre la aplicación y pulsar “Quitar esta aplicación…” en el menú contextual que aparecerá como se muestra a continuación:                                      image_thumb37  .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

En la cabecera de mi blog, he insertado un Marquee que he desarrollado en Silverlight. Dicho Marquee muestra los titulares de los post publicados en el blog para facilitar el acceso a ellos.

Os habréis dado cuenta que el pasado lunes 24 de Agosto desapareció el lector RSS de noticias del portal de Geeks que habíamos situado en la portada de LaBloguera. Esto ha sido debido a que el lector que le propuse poner a Cesar Reneses en portada, lo desarrollé con el servicio de Popfly. Y dicho servicio fué retirado el pasado lunes. Para más información ver este blog.

Tras todo esto hemos pensamos desarrollar otro lector en Silverlight para sustituir al anterior, el cual estoy desarrollando ahora mismo.

Os hago un adelanto de cómo será el lector de RSS que insertaremos en la portada de LaBloguera.

El viernes pasado día 17/07/2009 aprovechando el viaje a la Party Quijote impartí un taller junto a mi compañero César Reneses titulado “Silverlight: Las aplicaciones en la Web”.

Tras una pequeña introducción a la tecnología Silverlight, mostramos cómo crear una aplicación web Silverlight. Para ello decidimos realizar el juego del Reversi o también conocido como Othello.

Dejo un enlace donde podemos encontrar el juego desarrollado con capacidad de jugar contra la máquina. Ver Reversi Silverlight.

image

Esta gente de Google está preparando lo que puede ser la revolución de las aplicaciones en la web, aplicaciones 3D en el browser.

O3D es una API open-source en JavaScript para la creación de aplicaciones graficas 3D interactivas que se ejecutan sobre nuestro navegador. Haciendo uso de todos los recursos de nuestras tarjetas graficas.

Os dejo  un enlace a la página del proyecto O3D Google.

Algunos ejemplos:

http://o3d.googlecode.com/svn/trunk/samples/beachdemo/beachdemo.html

http://o3d.googlecode.com/svn/trunk/samples/pingpong/o3dPingPong.html

http://o3d.googlecode.com/svn/trunk/samples/io/io.html

Y muchos más…

0 comentarios
Archivado en: ,,

En los últimos días se me ha planteado la necesidad de trabajar con el navegador web pero no incrustado dentro de nuestra aplicación sino de forma externa a ella. Además me interesaba trabajar con una única instancia del navegador de forma que cada vez que se quisiese visualizar una página nueva se recargase la instancia activa en ese momento.

El primer planteamiento que hice fue el siguiente:

using System;
using System.Windows.Forms;
using System.Diagnostics;

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

        private void buttonGo_Click(object sender, EventArgs e)
        {
            Process.Start("IEXPLORE.EXE", textBoxURL.Text);
        }

     }

}

Con esta solución cada vez que se visualizaba una página se lanzaba una nueva instancia del navegador, por lo tanto fue descartada.

Una segunda solución planteada es la que se muestra a continuación:

using System;
using System.Windows.Forms;
using System.Diagnostics;

namespace ManejandoNavegador
{
    public partial class Form1 : Form
    {
        Process navegador;
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonGo_Click(object sender, EventArgs e)
        {
            if (navegador!=null)
            {
                navegador.Kill();
            }
            navegador= Process.Start("IEXPLORE.EXE", textBoxURL.Text);
        }

     }

}

Con esta solución conseguimos que solo haya una instancia del navegador gracias a que cada vez que lanzamos una instancia nueva se cierra la instancia anterior. Esto provoca cierto parpadeo al cerrar una instancia y lanzar otra nueva. Esto hizo que se descartara también esta ultima solución.

Finalmente decidí utilizar la siguiente solución añadiendo la referencia al COM Microsoft Internet Controls y añadiendo el “using SHDocVw”:

using System;
using System.Windows.Forms;
using System.Diagnostics;
using SHDocVw;

namespace ManejandoNavegador
{
    public partial class Form1 : Form
    {
        InternetExplorer explorer;
        public Form1()
        {
            InitializeComponent();
        }

        private void buttonGo_Click(object sender, EventArgs e)
        {
            if (explorer==null)
            {
                explorer= new InternetExplorer();
                explorer.Visible = true;
            }
            object Emtry = 0;
            explorer.Navigate(textBoxURL.Text, ref Emtry, ref Emtry, ref Emtry, ref Emtry);
        }
    }
}

De este modo se consiguió visualizar las páginas deseadas sobre una misma instancia del navegador. El usuario simplemente apreciará que la página se recarga con cada página nueva.

Últimamente ando liado con una aplicación cliente-servidor que requiere una comunicación en tiempo real del cliente con el servidor. Para agilizar esta comunicación pensé en utilizar sockets y aquí os paso un ejemplo de una simple aplicación tanto del lado del cliente como del lado del servidor.

Del lado del servidor necesitamos quedar a la espera, en un puerto libre que no esté reservado por el sistema, de una petición de conexión del cliente. Una vez que el cliente realice una conexión con el servidor, se estable un socket entre ambos por el cual se puede transferir la información que sea necesaria.

Código del lado del servidor:

using System;
using System.Net.Sockets;
using System.IO;

namespace ConsoleApplicationSocketServer
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //Puerto donde escuchará la aplicación servidora
            int puerto=10;

            Console.WriteLine("Servidor lanzado. Esperando conexión del cliente...");

            //Se abre un puerto de escucha.
            TcpListener tcpListener = new TcpListener(puerto);
            tcpListener.Start();

            //El Servidor espera a que se conecte el cliente.
            Socket socketForClient = tcpListener.AcceptSocket();

            if (socketForClient.Connected)
            {
                Console.WriteLine("Cliente conectado correctamente.");

                //Stream por donde se recibirá y enviará información al cliente.
                NetworkStream networkstream = new NetworkStream(socketForClient);

                StreamWriter streamWriter = new StreamWriter(networkstream);

                StreamReader streamReader = new StreamReader(networkstream);

                string dato = "Dato enviado desde el servidor";

                //Enviamos información al cliente.
                streamWriter.WriteLine(dato);
                Console.WriteLine("Dato enviado al cliente");
                streamWriter.Flush();

                //Recibimos información del cliente.
                dato = streamReader.ReadLine();
                Console.WriteLine(dato);

                //Cerramos los recursos abiertos.
                streamWriter.Close();
                streamReader.Close();
                networkstream.Close();
            }

            //Cerramos el socket con el cliente.
            socketForClient.Close();
            Console.WriteLine("Cerrando aplicación. Pulse una tecla para finalizar");
            Console.ReadKey();
        }
    }
}

En la parte del cliente simplemente necesitamos realizar una conexión con el servidor estableciendo el host y puerto donde está hospedada la aplicación servidora. A partir de ahí simplemente utilizaremos el socket creado para enviar y recibir información del servidor.

Código del lado del cliente:

using System;
using System.Net.Sockets;
using System.IO;

namespace ConsoleApplicationSocketCliente
{
    public class Program
    {
        public static void Main(string[] args)
        {
            //Puerto del servidor.
            int puerto = 10;
            //Host del servidor.
            string host = "localhost";

            TcpClient socketForServer;

            try
            {
                //Establecemos socket con el servidor.
                socketForServer = new TcpClient(host, puerto);
            }
            catch
            {

                Console.WriteLine("Error conectando con el servidor {0}. Pulse una tecla para finalizar...",host);
                Console.ReadKey();
                return;
            }

            //Flujo de envio y recepción de datos al servidor
            NetworkStream networkStream = socketForServer.GetStream();
            //Para escribir datos en el flujo.
            StreamWriter streamWriter = new StreamWriter(networkStream);
            //Para leer datos del flujo.
            StreamReader streamReader = new StreamReader(networkStream);

            try
            {
                string dato;
                //Recibimos damos del servidor.
                dato = streamReader.ReadLine();
                Console.WriteLine(dato);
                //Enviamos datos al servidor
                streamWriter.WriteLine("Mensaje recibido en el cliente");
                streamWriter.Flush();
            }
            catch
            {
                Console.WriteLine("Error recibiendo del servidor. Pulse una tecla para finalizar...");
                Console.ReadKey();
            }

            //Cerramos los recursos abiertos.
            streamReader.Close();
            streamWriter.Close();
            networkStream.Close();

            Console.ReadKey();

        }
    }
}

La consola de salida de la aplicación servidora sería la siguiente:

image

La consola de salida de la aplicación cliente sería la siguiente:

image

De casualidad me encontré por ahi una nueva forma de sacarle partido a los correos electrónicos.

A más de uno nos habrá pasado que tenemos un fichero y queremos convertirlo en formato PDF y no tenemos a mano ninguna herramienta que nos los convierta.

Pues simplemente necesitas tener en tu lista de contactos estas direcciones que te sacaran de algun que otro apuro }:-)
  1. pdf@koolwire.com: Si envías un correo a esta dirección, te devuelve el adjunto convertido en pdf.
  2. pdf2txt@adobe.com: El archivo pdf ajunto enviado a esta dirección se te devuelve como texto plano.

    La mayoria de ocasiones sabremos qué métodos invocar antes de la compilación, por lo tanto, podemos invocar directamente al método con sus parámetros, pero habrá ocasiones en las que esto no sea así y necesitemos invocarlos dinámicamente en tiempo de ejecuación.

    Por ejemplo, imaginemos que tenemos una clase llamada Calculadora que contiene un método para cada tipo de operación (Suma, Resta, Multiplicacion y Division) y solo sabremos durante la ejecución de nuestro programa el método que tenemos que llamar. ¿Qué harias si en un momento necesitamos ejecutar el método Suma con los parámetros 2 y 3, sabiendo unicamente el string "Suma" y el int 2 y 3 ?

    Este problema lo podemos solucinar utilizando el espacio de nombres Reflection, mediante el uso del método InvokeMember en el objeto Type.

    El método InvokeMember acepta los siguientes parámetros: nombre del método a invocar, una seria de flags de invocación, un atributo con una seria de propiedades de la misma, el objeto sobre el que se realiza la invocación y un arraya de object que contienen los parámetros del método. Para más información de los parámetros ver aquí.

    Un ejemplo seria el siguiente:

string metodo = Console.ReadLine(); //Recogemos por teclado el nombre del método a ejecutar.

int op1 = Convert.ToInt32(Console.ReadLine()); //Recogemos el primer operando

int op2 = Convert.ToInt32(Console.ReadLine()); //Recogemos el segundo operando

Type tipoObjeto = typeof(Calculadora); //Obtenemos el tipo del objeto calculadora.

object[] parametros = new object[] { op1, op2 };

int resultado = (int)tipoObjeto.InvokeMember(metodo, BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.InvokeMethod, null, pedroCalculadora, parametros);

Console.WriteLine(resultado); //Imprimimos por pantalla el resultado

 

      Del mismo modo podemos trabajar con las propiedades de un objeto, simplemente llamaremos al método GetProperty el cual acepta como parámetro el nombre de la propiedad y nos retorna un PropertyInfo a y con este objeto ya podemos acceder al metodo get de esta propiedad. Como mejor lo veremos es con un ejemplo. Imaginemos que en la clase Calcualdora del ejemplo anterior tenemos una propiedad para el nombre llamada Nombre y queremos acceder al Get de la misma en ejecuación simplemente conociendo el nombre de la propiedad:

 

Type tipoObjeto = typeof(Calculadora); //Obtenemos el tipo del objeto calculadora.

PropertyInfo propiedadInfo= tipoObjeto.GetProperty("Nombre");//Obtenemos la propiedad que queremos.

MethodInfo metodoInfo = propiedadInfo.GetGetMethod();//Obtenemos el método de la propiedad.

string resultado = (string)metodoInfo.Invoke(pedroCalculadora, new object[0]);

Console.WriteLine(resultado); //Imprimimos por pantalla el resultado

 

El resultado será el nombre de la calculadora y lo hemos obtenido conociendo el nombre de la propiedad.

En el post anterior comentamos cómo deserializar un fichero XML para obtener una serie de instancias de unas clases que lo representan. 

Ahora vamos a realizar lo contrario, a partir de una instancia de la clase Libro, vamos a generar un XML asociado que se ajusta al esquema.

 

Nos creamos un objeto de la clase libro y le añadimos la información del libro a través de las propiedades de la clase que se proporcionan. A continuación con creamos un fichero con la clase FileStream y posteriormente con la clase XmlSerializer serializamos el objeto de la clase Libro que nos hemos creado anteriormente.

 

 

static void Main(string[] args)

{

    Libro milibro = new Libro();

 

    milibro.precio = (double)30;

    milibro.precioSpecified = true;

    milibro.Titulo = "Los tres cerditos";

    milibro.Autores = new string[] {"Luis","Manolo","Laura" };

    milibro.Editorial = "MiEditorial";

 

    FileStream fs = new FileStream("prueba.xml", FileMode.Create);

    XmlSerializer xs = new XmlSerializer(typeof(Libro));

    xs.Serialize(fs, milibro);

    fs.Close();

}

Nota:  Si nos fijamos en la clase Libro que se ha generado podemos ver como para el atributo precio hay un atributo en la clase que representa al mismo y otro de tipo boleano asociado. Esto se debe a que para los elementos que pueden o no aparecer (minOccurs=0) o para el caso de los atributos, que nunca son obligatorios, debemos indicar si queremos que se serialicen o no. Para ello en este caso indicamos que precioSpecified=true.

 

El resultado del ejemplo anterior seria el siguiente documento XML:

 

<?xml version="1.0"?>

<Libro xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" precio="30">

 

  <Titulo>Los tres cerditos</Titulo>

  <Autores>Luis</Autores>

  <Autores>Manolo</Autores>

  <Autores>Laura</Autores>

  <Editorial>MiEditorial</Editorial>

</Libro>

 

Y esto ha sido todo para serializar y deserializar objetos en ficheros XML.

Muchas veces necesitamos crear o leer información de un fichero XML que se debe ajustar a un esquema XSD, para ello podemos utilizar la librería que viene con el Framework (System.Xml) y echar mano de las clases XmlElement, XmlNode, etc.

 

Hoy día estoy utilizando otra opción que me ha impresionado mucho por la potencia que te ofrece para trabajar con este tipo de documentos. El .Net Framework nos ofrece una herramienta llamada xsd, esta herramienta genera clases de esquemas XML o de Common Language Runtime a partir de archivos XDR, XML y XSD, o a partir de clases de un ensamblado de motor de tiempo de ejecución.

Esto significa que podemos generar a partir de un fichero xsd (esquema) una estructura de clases (en cualquier lenguaje de programación soportado por el CLR). Con la estructura de clases que nos genera podemos deserializar un documento XML con XmlSerializer de este modo nos instanciamos una serie de objetos de estas clases con la información del documento. Del mismo modo si serializamos objetos de estas clases obtenemos de forma directa un documento XML que se corresponde con ese esquema.

 

Veamos un ejemplo de como utilizar esta herramienta:

 

Tenemos un XSD para representar un libro que tiene un precio, un titulo, varios autores y una editorial con la siguiente estructura:

 

 

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">

     <xsd:element name="Libro">

         <xsd:complexType>

            <xsd:sequence>

                 <xsd:element name="Titulo" type="xsd:string"/>

<xsd:element name="Autores" type="xsd:string" maxOccurs="10"/>

                 <xsd:element name="Editorial" type="xsd:string"/>

            </xsd:sequence>

            <xsd:attribute name="precio" type="xsd:double"/>

        </xsd:complexType>

   </xsd:element>

</xsd:schema>

 

 

Ahora con xsd generamos las clases asociadas a este esquema. Para ello nos vamos a la consola de Visual Studio (Inicio/Todos los programas/Microsoft Visual Studio 2005/Visual Studio Tool/Símbolo del sistema de Vidual Studio 2005), accedemos a la carpeta donde se encuentra nuestro xsd y ejecutamos el siguiente comando:

 

xsd  –c  esquema.xsd

 

Para más información sobre los parámetros de xsd.exe mira aquí.

Una vez ejecutado este comando ya nos habrá creado un fichero con la extensión correspondiente al lenguaje por defecto que le tengamos indicado al Visual Studio, en mi caso se ha generado un fichero esquema.cs.

Este fichero contendrá una clase llamada Libro que representa al elemento compuesto libro, esta clase contiene para cada elemento que contiene el elemento libro un atributo y su propiedad asociada, por ejemplo para titulo tenemos:

 

            private string tituloField;

      public string Titulo {

        get {

            return this.tituloField;

        }

        set {

            this.tituloField = value;

        }

      }

De este modo ya podemos serializar y deserializar un XML y trabajar con tu contenido.

Ahora vamos a ver como acceder a la información de un documento XML, utilizando la clase generada deserializando previamente.

 

Dado un XML que se ajusta al XSD esquema.xsd:

 

 

<?xml version="1.0" encoding="UTF-8"?>

<Libro xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="libro.xsd" precio="20">

        <Titulo>Caperucita roja</Titulo>

        <Autores> Manolo Pérez</Autores>

        <Autores>María García</Autores>

        <Editorial>Editorial</Editorial>

</Libro>

 

Si ejecutamos este código:

 

 

static void Main(string[] args)

{

     FileStream fs = new FileStream("ejemplo.xml", FileMode.Open);

     XmlSerializer xs = new XmlSerializer(typeof(Libro));

     Libro milibro = (Libro)xs.Deserialize(fs);

     fs.Close();

 

     Console.WriteLine("Precio: " + milibro.precio);

     Console.WriteLine("Titulo: "+milibro.Titulo);

     foreach (string titulo in milibro.Autores)

     {

          Console.WriteLine("Autor: "+titulo);

     }

     Console.WriteLine("Editorial: " + milibro.Editorial);

     Console.ReadLine();

}

La salida es:

 

Precio: 20

Titulo: Caperucita roja

Autor: Manolo Pérez

Autor: María García

Editorial: Editorial

 

De esta forma tan sencilla podemos recoger la información de un XML en una estructura de objetos y de este modo acceder a la misma.

En un proximo post comentaremos cómo hacer lo contrario, una vez que tenemos los objetos de estas clases instanciados serializarlos y crear un documento XML.

                                                                

                                                       To be continue...

 

En un post anterior comenté brevemente como se trabaja con la generación de código utilizando las librerías System.CodeDom y System.CodeDom.Compiler. En este post extenderemos un poco más los ejemplos visto y veremos cómo podemos construir otro tipo de estructuras utilizadas comúnmente en nuestros programas.

 

Declarar un atributo:

 

La declaración de atributos consta de tres parte principales, la visibilidad, el tipo de atributo y el nombre.

 

 

//Declaramos el atributo con el nombre y tipo

CodeMemberField atributo = new CodeMemberField(("String","MiAtrib");

 

//Indicamos la visibilidad

atributo.Attributes = MemberAttributes.Private;

 

 

           

//Comentarios para documentación

atributo.Comments.Add(new CodeCommentStatement("<summary>", true));

atributo.Comments.Add(new CodeCommentStatement("comentario", true));

atributo.Comments.Add(new CodeCommentStatement("</summary>", true));

 

           

La salida de este ejemplo será un fragmento de código como el siguiente:

               

      /// <summary>

      /// comentario

      /// </summary>

      public string MiAtrib;

 

 

Crear una propiedad:

 

 

Una propiedad como ya sabemos está compuesta de su visibilidad, el tipo, el nombre y opcionalmente un set y get asociados a un atributo.

 

 

CodeMemberProperty propiedad = new CodeMemberProperty();

// Indicamos el nombre de la propiedad.

propiedad.Name = "MiPropiedad";

// Indicamos el tipo de la propiedad.

propiedad.Type = new CodeTypeReference("String");

// Establecemos la visibilidad de la propiedad.

propiedad.Attributes = MemberAttributes.Public;

 

 

//Comentarios para documentación

propiedad.Comments.Add(new CodeCommentStatement("<summary>", true));

propiedad.Comments.Add(new CodeCommentStatement("comentario", true));

propiedad.Comments.Add(new CodeCommentStatement("</summary>", true));

 

 

// Creamos el return del get

CodeMethodReturnStatement cmReturn = new CodeMethodReturnStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), nombreAtributoAsociado));

 

//Añadimos el get

propiedad.GetStatements.Add(cmReturn);

 

// Creamos el contenido del set

CodeAssignStatement caSet = new CodeAssignStatement(new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), nombreAtributoAsociado), new CodePropertySetValueReferenceExpression());

 

// Añadimos el set

propiedad.SetStatements.Add(caSet);

           

Nota: nombreAtributoAsociado sería el atributo que está asociado a la propiedad.

La salida de este ejemplo será un fragmento de código como el siguiente:

 

 

                                     /// <summary>

      /// comentario.

      /// </summary>

      public string Mipropiedad

      {

          get { return MiAtrib; }

          set { MiAtrib = value; }

      }

 

 

 

 

Crear una enumeración:

 

Para declarar una enumeración debemos especificar la visibilidad, tipo, nombre y los elementos de la misma.

 

//Declaramos el nodo para la enumeracion.

CodeTypeDeclaration enumerac = new CodeTypeDeclaration("MiEnum");

 

//Debemos indicar que el CodeTypeDeclaration va a ser tipo enumeración.

enumerac.IsEnum = true;

 

//Indicamos la visibilidad.

enumerac.Attributes = MemberAttributes.Public;

 

//Comentarios.

enumerac.Comments.Add(new CodeCommentStatement("<summary>", true));

enumerac.Comments.Add(new CodeCommentStatement("comentario", true));

enumerac.Comments.Add(new CodeCommentStatement("</summary>", true));

 

//Representa un campo.

CodeMemberField miembro;

 

//Vamos creando los valores de la enumeracion y los vamos añadiendo a la misma.

List<string> cadenasAtributos =new List<string>("elem1","elem2");

for (int i = 0; i < cadenasAtributos.Count; i++)

{

 

     miembro = new CodeMemberField();

     //Le damos un nombre al campo.

     miembro.Name = cadenasAtributos[ i ];

     //Añadimos el campo a la enumeración.

     enumerac.Members.Add(miembro);

}

 

 

 

La salida de este ejemplo será un fragmento de código como el siguiente:

       

 

/// <summary>

/// comentario.

/// </summary>

public enum MiEnum {

           

       elem1,

           

       elem2,

}

Un tema en el que estoy últimamente muy metido por cuestiones del trabajo es en la generación dinámica de código y la forma en que esta se puede automatizar para crear ficheros de código fuente en lenguajes soportados por el CLR.

 Para conseguir esto necesitamos básicamente apoyarnos en dos pilares, por un lado debemos generar un árbol en el que se recoja toda la parte sintáctica y semántica del programa fuente que queremos construir (independiente del lenguaje de programación) para ello utilizaremos las clases que podemos encontrar bajo el espacio de nombre System.CodeDom. Por otro lado, una vez que ya tenemos el árbol podemos pasar a generar el código asociado al mismo en un lenguaje especifico de programación soportado por el CLR ( de este modo, en un solo paso podemos generar el mismo programa en varios lenguajes como veremos más adelante).

En el espacio de nombres System.CodeDom podemos encontrar clases que nos representan cada una de las estructuras posibles que nos podemos encontrar en cualquier programa (Clases, Métodos, Propiedades, Enumeraciones, Parámetros, estructuras repetitivas, asignaciones, etc. etc...)

La raíz de nuestro arbol será un objeto del tipo CodeCompileUnit el cual recogerá una serie de objetos del tipo CodeNamespace el cual a su vez contiene una seria de Imports (objetos CodeNamespaceImport, utlizados para "importar" namespaces) y Types (una colección de objetos CodeTypeDeclaration, los cuales pueden representar código de clases, estructuras, interfaces y enumeraciones)

Finalmente para la generación de un programa en un lenguaje determinado necesitamos un generador de código, para ello utilizaremos cualquier clase que implemente la interface ICodeGenerator como es la clase CodeDomProvider. (localizada en el espacio de nombres System.CodeDom.Compiler). Para cada lenguaje especifico tenemos un proveedor (CSharpCodeProvider, VBCodeProvider,  JScriptCodeProvider, VJSharpCodeProvider).

 Veamos una serie de ejemplos de como podemos explotar esta funcionalidad:

 Crear un espacio de nombres:

// Declara el NameSpace indicando el nombre del mismo.

CodeNamespace espacioNombres = new CodeNamespace("MiEspacioNombres");

 

//Espacios de nombres a importar

CodeNamespaceImport import = new CodeNamespaceImport("System.CodeDom");

 

//Añadimos el espacio de nombres

espacioNombres.Imports.Add(import);

 

 

Crear una clase:

CodeTypeDeclaration clase = new CodeTypeDeclaration("MiClase");

 

//Indicamos que es clase.

clase.IsClass = true;

 

//Indicamos la visibilidad

clase.Attributes = MemberAttributes.Public;

           

//Añadimos a la clase sus elementos (atributos, propiedades, métodos…)

clase.Members.Add(new CodeTypeMember());

 

//Añadimos la clase al espacio de nombres.

espacioNombres.Types.Add(clase);

 

 

 

Ahora pasaremos a ver como generar el código y crear un fichero con el mismo.

Este ejemplo lo haremos para lenguaje C#, para cualquier otro habría simplemente que cambiar el proveedor.

CodeCompileUnit ccu = new CodeCompileUnit();

 

//Generador de codigo que vamos a utilizar para un determinado lenguaje.

CodeDomProvider proveedor;

ccu.Namespaces.Add(espacioNombres);

 

//Generador de codigo que vamos a usar

proveedor = new CSharpCodeProvider();

 

//Guardamos la extension que debe tener el archivo

string extension = proveedor.FileExtension;

 

//Creamos un TextWriter con el cual vamos a guardar el codigo generado

TextWriter t = new StreamWriter(rutaDestino+"\\"+nombreFichero+"."+extension, false);

 

//Finalmente generamos el codigo

proveedor.GenerateCodeFromCompileUnit(ccu, t, new CodeGeneratorOptions());

 

//Cerramos el fichero.

t.Close();

 

En proximos post comentaremos como utilizar más de estas estructuras...

Es típico tener controles personalizados en nuestras aplicaciones, estos controles normalmente estan compuestos de una serie de elementos los cuales permiten tratar sus eventos asociando un método que se ejecutará cuando el evento se dispare.

Este método debe estar dentro del ámbito del control personalizado de modo que cuando utilicemos nuestro control en aplicaciones que desarrollemos no podremos modificar el código asociado a los eventos de los elementos hijos de dicho control.

En este post explicaré una forma sencilla de solucionar este problema.

El ejemplo que pretendo mostrar consta de lo siguiente: un proyecto windows form donde tendremos en nuestro formulario principal un control personalizado, el control personalizado consta de un simple botón. Se pretende que desde el código del formulario principal podamos asociar código que se ejecutará cuando se dispare por ejemplo el evento de Click del botón que contiene el control personalizado.

Los pasos a seguir con los siguientes:

  1. Nos creamos un proyecto de Windows Form.
  2. Añadimos sobre la solución un Control de usuario llamado MiControl.
  3. Al control de usuario le añadimos un botón llamado MiControl.
  4. Seleccionamos el botón y en el cuadro de propiedades dentro de eventos hacemos doble click en el evento Click, de este modo le asociamos un método a dicho evento.
  5. Añadimos el código siguiente:

 

//Declaramos un delegado para el evento de clickado.

public delegate void ClickEventHandler(object sender, System.EventArgs e);

 

//Asociamos el evento a una categoria, en concreto a la categoria Action

[Category("Action")]

 

//Descripcion del evento

[Description("Ocurre cuando se clicka sobre el boton MiBoton.")]

 

//Asignamos al delegado el nombre del método que responderá al evento fuera del control de usuario

public event ClickEventHandler Click_boton_interno;

 

//Método que responde al evento de click dentro del control de usuario

private void MiBoton_Click(object sender, EventArgs e)

{

//Comprueba que desde fuera del control se ha añadido el evento.

if (Click_boton_interno != null)

{

Application.DoEvents();

Click_boton_interno(this, e);

}

}

 

  1. A continuación si añadimos un nuevo elemento del control personalizado MiControl en el formulario principal veremos que en dicho elemento aparece un nuevo evento disponible llamado Clic_boton_interno. Si hacemos doble clic sobre el nos creará un método asociado a dicho evento todo este ya en el ámbito del formulario principal de este modo ya podemos tratar dicho evento desde ahí fuera.

 

private void miControl1_Click_boton_interno(object sender, EventArgs e)

{

            MessageBox.Show("Se ha pulsado el boton que hay dentro de MiControl");

 }

 

1 comentarios
Archivado en:

Como algunas personas me ha preguntado como se lanza una linea de tiempo cuando ocurre un determinado evento, vamos a ver como hacerlo de forma sencilla sin necesidad de tocar código.

Uno de mis ultimos post iba sobre este tema pero trabajando con Expression Designer la version anterior de Blend, para ello habia que crear los triggers sobre código XAML y era muy tedioso.

Con la nueva versión Expression Blend Beta2 es muy sencillo, los pasos a seguir son los siguientes:

1.- Sobre el panel "Objects and Timeline" (parte inferior izquierda por defecto) crear una nueva linea de tiempo.

2.- Modificar la linea de tiempo para que actue sobre los objetos como nosotros queramos. (similar a flash)

3.- Seleccionar el control cuyo evento activará la linea de tiempo.

4.- Sobre el panel "Triggers" (parte superior izquierda por defecto) crear un nuevo trigger en la opción "+Event".

5.- Sobre el nuevo trigger creado indicarle el control que dispara el evento y el evento que dispara el trigger.

6.- Por último indicamos la linea de tiempo que se activará y la accion de la linea de tiempo (Begin, Stop, Pause, SkipToFill, Resume, Remove)

Al final debe quedar algo parecido a esto:

Más envíos Página siguiente >