martes, 21 de septiembre de 2010

[SilverLight] Integrando UserControls en Layouts (II), pero automático.

Volviendo a la integración, la opción del artículo anterior tiene un problema  de escalabilidad. Si tuviésemos 500 pantallas, ¿implica que deberíamos tener un manejador y una clase principal con 500 atributos privados que iremos instanciando? Entonces, si aplicamos la idea anterior y la resolvemos de un modo un poco más elegante la solución será que cada botón u acción de cambio de estado sea el responsable de internamente notificar a la aplicación cuál es ese estado para que instancie correctamente el objeto adecuado. Para ello, vamos a usar la propiedad DataContext que tiene la clase Button como sigue:

   1: <Button x:Name="buttonArticle" Content="Articles" Click="buttonArticle_Click" BorderBrush="#FF7100FF" Cursor="Hand" ClickMode="Press">
   2:                 <Button.DataContext>
   3:                     <local:Article/>
   4:                 </Button.DataContext>
   5:             </Button>
   6:             <Button x:Name="buttonAbout" Content="About" Click="buttonAbout_Click" BorderBrush="#FF7100FF" Cursor="Hand" ClickMode="Press">
   7:                 <Button.DataContext>
   8:                     <local:About/>
   9:                 </Button.DataContext>
  10:             </Button>

Estamos rellenando la propiedad DataContext con el nombre del UserControl que vamos a instanciar. Cuando hagamos click en cada botón, usaremos el Assembly para instanciarlo. Con esto nos ahorramos tener que declarar y gestionar los atributos o variables necesarias para instanciar manualmente cada una de las clases. Por ejemplo, cuando haga click en el botón de About ocurriá lo siguiente:

 

   1: private void buttonAbout_Click(object sender, System.Windows.RoutedEventArgs e)
   2: {
   3:     this.renderOnCanvas((Button)sender).DataContext);
   4: }

Y el método renderOnCanvas será el encargado de obtener la clase adecuada cuyo nombre hemos asignado dentro del DataContext e instanciarla:

   1: private void renderOnCanvas(string controlName)
   2: {
   3:     Type type = this.GetType();
   4:     Assembly assembly = type.Assembly;
   5:     UserControl newPage = (UserControl)assembly.CreateInstance(type.Namespace + "." + controlName);
   6:     canvas.Children.Clear();
   7:     canvas.Children.Add(newPage);
   8: }

De este modo evitamos el añadir manualmente los atributos o variables de cada instancia y podemos automatizarlo, además de traspasar la responsabilidad de cada sección al botón correspondiente.

[SilverLight] Integrando UserControls en Layouts (I)

En el momento de hacer una aplicación se pueden tomar varias decisiones para organizar las diferentes pantallas y opciones que tengan. Una de ellas, la más básica es tener una serie de N canvas en los cuales al pulsar en la opción correspondiente, nosotros haremos que se muestre el adecuado. Sin embargo para mí esto presenta dos grandes inconvenientes:

  1. El diseño de la interfaz se va haciendo más complejo a medida que incrementamos la cantidad de canvas a gestionar.
  2. Al instanciar la pantalla principal, estamos instanciando todas las opciones/pantallas disponibles (independientemente de que sean usadas o no).

Por lo tanto, me surge la duda de cómo se podría evitar esto y me encontrado dos opciones. La primera de ellas consiste en una extensión algo más limpia del método básico, con la diferencia de que cada una de las pantallas tendrá su propia clase y lo único que tendremos que hacer será instanciarlas cuando sean requeridas e integrarlas en nuestro canvas principal. Como por ejemplo, lo siguiente:

Disponemos de varios UserControls, entre los cuales destacan estos ( sírvase únicamente como ejemplo ):

   1: public partial class About : UserControl
   2: {}
   1: public partial class Articles : UserControl
   2: {}

En primer lugar declaro cada uno de los userControls dentro de nuestra MainPage (o donde corresponda):

   1: private About aboutUX;
   2: private Articles articlesUX;

Supongamos que disponemos de un layout de tipo Grid donde tenemos dispuesto un layout Canvas que en un alarde de originalidad lo he denominado canvas; sobre él se irán cargando los respectivos UserControls:

   1: <Canvas x:Name="canvas" Margin="1,1,0,0" Grid.Row="4"/>

La idea es sencilla. Cuando se quiera cambiar a cada pantalla, podemos gestionarlo de modo que sólo instancie el user control si no está creado aún:

   1: private void changeToAbout()
   2: {
   3:     if ( this.aboutUX == null )
   4:     {
   5:         this.aboutUX = new About();
   6:     }
   7:     //borramos el contenido del canvas
   8:     this.canvas.Childrens.Clear();
   9:     //añadimos el nuevo user control
  10:     this.canvas.Childrens.Add(this.aboutUX);
  11: }

Así podemos controlar levemente la gestión de UserControls.

viernes, 17 de septiembre de 2010

[EBooks] Ebooks GRATIS de SQL Server 2008 R2 y Windows Server 2008 R2

Navegando navegando se encuentran multitud de recursos. En este caso y temporalmente he encontrado una oferta suculenta: la descarga de los siguientes ebooks:

image image

Efectivamente, es un libro de introducción a Windows Server 2008 R2 y otro a SQL Server 2008 R2. Simplemente yendo a la sección ofertas podemos encontrar los links de descarga de los libros, disponibles en PDF y XPS y previo login con nuestra cuenta de Windows Live.

¿Dónde los he encontrado? Pues en Microsoft Learning, que es el portal de Microsoft dedicado al aprendizaje y formación de todo el mundo, incluyendo las certificaciones y sus itinerarios. Recomiendo a todo el mundo que se pase por ahí y esté atento, pues en este caso las ofertas son tentadoras (dos buenos libros) y en otros casos puedes encontrar descuentos así como todo el soporte que requieras para tu información.

jueves, 16 de septiembre de 2010

[XNA] Lanzamiento XNA 4.0

Hoy se ha publicado por fin la versión 4.0 de XNA Game Studio, y como ya ocurrió en la beta ahora también se integran dentro de la Windows Phone Tool Developer Tools. Este kit incluye lo siguiente:

  • Visual Studio 2010 Express for Windows Phone
  • Windows Phone Emulator
  • Silverlight for Windows Phone
  • XNA Game Studio 4.0
  • Expression Blend
  • Como siempre, gratis y sin coste alguno para poder empezar o seguir trasteando con XNA y Windows Phone 7!

    miércoles, 15 de septiembre de 2010

    [WCF] Codificaciones de texto y controlando la serialización mediante eventos

    El motor de serialización de WCF está limitado a unos cuantos formatos de codificación y por defecto siempre codifica el tipo string en el formato UTF8. A priori no hay ningún problema, pero te puede ocurrir el siguiente escenario:

    Tenemos una serie de entidades serializadas con WCF en las que se almacena texto. Por ejemplo, objetos de negocio como artículos en una tienda en la que algunos de sus campos son la descripción, el nombre del artículo, además de todos aquellos que se crean necesarios. Partamos de la base de que hemos serializado nuestro objeto siguiendo el artículo correspondiente. En un momento determinado, comienzas a escribir la información de los objetos en el XML, de un modo a como sigue:

    <ArticleManager xmlns="http://schemas.datacontract.org/2004/07/Logic" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">

    <Articles>

    <Article>

    <Name>Halo Reach</Name>

    <Description>La apasionante última entrega de la exitosa saga de shooters. </Description>

    </Article>

    </ArticleManager>

    Para una codificacion en UTF-8 no tendríamos ningún problema en deserializar el campo Name, puesto que todos los caracteres son válidos en bytes desde el punto de vista de esa codificación. Sin embargo, no ocurre lo mismo con el campo Description. Este campo incluye caracteres que no son válidos para esa coficación, como por ejemplo los caracteres con tildes (en última) y otros propios del castellano (como el caracter ñ). En el momento en que se deserializa ese dato, provoca una excepción en XmlSerializer por no encontrarse dentro del esquema de UTF8 y similares. ¿Qué podemos hacer? Muchas cosas, como por ejemplo establecer un XmlSerializer propio para nuestras clases de modo que los campos de tipo string se codifiquen y decodifiquen empleando las codificaciones que queramos, crear un decodificador propio exclusivo para manejar texto o bien lo que propongo aquí, que consiste en almacenar la información con bytes de cara al fichero XML pero mostrándola al usuario como string controlando mediante eventos los procesos de serialización y deserialización. Veamos cómo se puede hacer:

    Nuestra clase artículo tiene el siguiente juego de atributos:

       1: [DataContract()]
       2: public class Article
       3: {
       4:     [DataMember()]
       5:     public string Name;
       6:     [DataMember()]
       7:     public string Description;
       8: }

    Y lo que vamos a hacer es transformar y encapsular los campos miembros serializables dentro de arrays de bytes:

       1: [DataContract()]
       2: public class Article
       3: {
       4:     [DataMember()]
       5:     public byte[] ByteName;
       6:     [DataMember()]
       7:     public byte[] ByteDescription;
       8:  
       9:     public string Name;
      10:     public string Description;
      11:     ...
      12: }

    La idea es sencilla y se expuso anteriormente pero la recuerdo. Vamos a guardar los campos en el xml como bytes y al cargar el fichero, automáticamente se transforma en string. Para ello se proporcionan una serie de etiquetas de eventos que se pueden asociar a funciones de la clase que sufre el proceso para que actúen de manejadores del propio proceso. Estas etiquetas son:

    • OnDeserialized: Se invoca cuando el objeto ya se ha deserializado.
    • OnDeserializing: Se invoca justo antes de deserializar el objeto.
    • OnSerialized: Se invoca cuando el objeto ya ha pasado por el proceso de serialización.
    • OnSerializing: Se invoca justo antes de serializar el objeto.

    Debemos asociar posteriormente estas etiquetas a un método que nos sirva de manejador. Este método debe tener un único parámetro de tipo StreamingContext cuyo cometido es controlar el origen y destino de la secuencia de serialización. Dicho de otro modo más llano y campechano indica qué objeto es quien inicia la secuencia de datos (en este caso para la seriailzación/deserialización) a través de Context y con State indica cuál es el origen o destino de los datos. Esto último puede servir para especificar si es para un fichero, remoto, serializado, otra máquina, otro proceso, etc. Sabiendo esto, ya sólo nos falta escribir el método para deserializar:

       1: [OnDeserialized()]
       2: private void onDeserialize(StreamingContext context)
       3: {
       4:     this.Name = Encoding.Unicode.GetString(this.ByteName);
       5:     this.Description = Encoding.Unicode.GetString(this.ByteDescription);
       6: }

    Para habilitar caracteres con tildes, ñ y otros, he usado la codificación de Unicode que si permite usarlos. Como se aprecia, se invoca una vez el objeto ya está serializado y se han leído los miembros (los campos ByteName y ByteDesription tendrás sus oportunos valores). Ahora vayamos a por la serialización, que invocaremos antes de serializar para preparar los arrays de bytes:

       1: [OnSerializing()]
       2: private void onSerialize(StreamingContext context)
       3: {
       4:     this.ByteName = Encoding.Unicode.GetBytes(this.Name);
       5:     this.ByteDescription = Encoding.Unicode.GetBytes(this.Description);
       6: }

    Con este sencillo procedimiento no tendremos problemas de conversiones entre cualquier tipo de codificaciones.

    jueves, 9 de septiembre de 2010

    [SilverLight] Integración con HTML

    Uno de los temas más complicados o que por el momento no parece que tenga una solución clara es integrar HTML normal con una aplicación de SilverLight. Me explico con un sencillo ejemplo: supongamos el escenario de una aplicación en la que tenemos dentro un mininavegador donde podemos acceder a otras páginas. ¿Es posible? Evidentemente. ¿Es una solución bonita? En mi modesta opinión, no. ¿Y por qué voy a hablar de ello? Porque no he encontrado otras soluciones…

    Como primera medida encuentro la solución que se propone a través de este tutorial, empleando un control WebBrowser al que mediante su propiedad Source le podemos indicar el código html a carga. Podemos indicarlo mediante un típico enlace a página, creando un URI o bien añadiendo en el string el código html “a pelo”. El problema de todo esto es que para que el objeto WebBrowser funcione debe ejecutarse fuera del navegador (es un requerimiento del propio objeto). Si queremos que a través del propio navegador usemos html, tenemos la siguiente opción.

    Esta opción consiste en un tipo de fuerza bruta. Como principio básico conocemos que SilverLight no puede procesar el código HTML desde dentro del navegador, por lo que nuestra solución pasa por añadir un iframe desde el cual carguemos el código HTML y separarlo de la propia aplicación SilverLight (pero dentro de la misma aplicación ASP). El método es simple: creamos un tag div en la página principal, introducimos el iframe (podemos acceder a él a través del DOM) y le asignamos coordenadas absolutas, de forma que aparezca encima de la aplicación SilverLight:

       1: <iframe id="iframeReport" style="position:absolute;top:120px;left:0px;width:200px;height:200px;visibility:hidden;margin-left:15px;" src="http://www.google.com/"></iframe>
       1: System.Windows.Browser.HtmlElement myFrame = System.Windows.Browser.HtmlPage.Document.GetElementById("iframeReport"); 
       2: myFrame.SetStyleAttribute("visibility",

    Evidentemente hay varios componentes que intentan simular el comportamiento del HTML (como por ejemplo este), pero sin soporte oficial por parte del equipo de desarrollo de SilverLight.

    [Web] WebMatrix

    WebMatrix es un producto destinado al desarrollo web orientado a estudiantes y gente que aún no tiene un conocimiento muy amplio de la materia. Incluye todo lo necesario para comenzar:

    • IIS Developer Express: Un servidor web de desarrollo sobre el que podremos comprobar cómo funciona nuestra web.
    • ASP.NET: Nuestro querido framework para desarrollar web.
    • SQL Server Compact: Una base de datos embedida.

    En cuanto a la aplicación, dispone de la interfaz Ribbon (famosa por ser la interfaz de Office 2007 y usada en la mayoría de software incluido Windows 7) y acceso directo a Visual Studio para poder desarrollar mejor la web.

    Es un producto en fase beta, por lo que es muy posible que tenga algún fallo o cosilla que sea necesaria depurar. Por todo lo demás, pienso que es una buena idea el despojar de la complejidad el desarrollo web para pequeños sitios y en especial para todos aquellos que quieran aprender poco a poco y paso a paso antes de pasar por otro tipo de soluciones bastante más complejas.

    Aquí os dejo el enlace:

    http://www.microsoft.com/web/webmatrix