Publicado en .NET, ASP.NET, Javascript, Silverlight

Sobreponer html sobre plug-in de Silverlight!


Hola, amigos me reporto en el blog.

En esta entrada quiero veamos un tema que no es muy cómo a la hora de embeber un plug-in en las páginas ASPX.

Supongamos que en una página de asp.net, tenemos algún tipo de Menu muy sencillo, el cuál debe sobreponerse a todo el contenido de la página (html resultante de la ejecución de una página web aspx), este trabajo se logra con CSS básico, a través de la propiedad z-index, la cual permite sobreponer objetos html unos sobre otros, pero cuando se trabaja con un objeto de Silverlight el problema toma otra proporción.

Lo primero es crear un proyecto de Silverlight en Visual Studio 2010

Veamos, tengo el siguiente código de un Menu de ASP.NET con su respectivo CSS


<style type="text/css">
  #logo
        {
            float: left;
            width: 10.5em;
            background: #CCCCCC;
            padding: 0.5em 0.5em 0.5em 1em;
            margin: 0;
        }
        .primaryStaticMenu
        {
            background-color: transparent;
            float: right;
        }
        .primaryStaticMenuItem
        {
            width: 10em;
            background-color: #f7f2ea;
            border-width: 1px;
            border-color: #efefef #aaab9c #ccc #efefef;
            border-style: solid;
            color: #777777;
            padding: 0.5em 0 0.5em 1em;
        }
        .primaryStaticHover
        {
            color: #800000;
            background: #f0e7d7;
        }
        
        .primaryDynamicMenu
        {
            background-color: #f7f2ea;
            border-bottom: solid 1px #ccc;
        }
        .primaryDynamicMenuItem
        {
            width: 10em;
            background-color: #f7f2ea;
            color: #777;
            padding: 0.5em 0 0.5em 1em;
            border-width: 1px;
            border-color: #f7f2ea #aaab9c #f7f2ea #efefef;
            border-style: solid;
        }
        .primaryDynamicHover
        {
            color: #800000;
            background: #f0e7d7;
        }
        
        .secondaryLevelOne
        {
            background-color: transparent;
            background-repeat: repeat-x;
            margin: 1.5em 0 0 0;
            padding: 5px 0 0 5px;
            width: 12em;
            height: 35px;
        }
        .secondaryLevelTwo
        {
            background: #FAFBFB;
            padding: 5px 0 5px 5px;
        }
        .secondaryStaticHover
        {
            color: #800000;
        }
</style>

<div id="container">
        <asp:Menu ID="menuPrimary" runat="server" DataSourceID="siteSource1" Orientation="Horizontal"
            StaticEnableDefaultPopOutImage="false" StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1">
            <StaticMenuStyle CssClass="primaryStaticMenu" />
            <StaticMenuItemStyle CssClass="primaryStaticMenuItem" />
            <StaticHoverStyle CssClass="primaryStaticHover" />
            <DynamicMenuStyle CssClass="primaryDynamicMenu" />
            <DynamicMenuItemStyle CssClass="primaryDynamicMenuItem" />
            <DynamicHoverStyle CssClass="primaryDynamicHover" />
        </asp:Menu>
    </div>
    <asp:SiteMapDataSource ID="siteSource1" runat="server" ShowStartingNode="false" />

Control de Silverlight

<UserControl x:Class="ZInexProblem.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="50" d:DesignWidth="200" HorizontalAlignment="Left"  >

    <Grid x:Name="LayoutRoot" Background="White">
        <TextBox Foreground="Red" Background="Yellow" TextWrapping="Wrap" HorizontalContentAlignment="Center" FontSize="20" FontFamily="Comic Sans MS" Text="TextBox Especial"></TextBox>
    </Grid>
</UserControl>

Así creamos un control TextBox de Silverlight muy sencillo para hacer las pruebas.

De esta forma el problema consiste en que el plug-in de Silvelright por defecto se va a sobreponer a cualquier tipo de contenido que se cree en la página ASPX, es decir, en este caso el control menu va a quedar solapado bajo la película de silverlight, lo cual nos indicaría un bug(El cual no existe :).

Para solucionar esto debemos hacer lo siguiente:

Como ya algunos sabemos un plug-in de silverlight se carga y referencia a través de un tag object de html.

    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2">
            <param name="source" value="ClientBin/ZInexProblem.xap" />
            <param name="onError" value="onSilverlightError" />
            <param name="background" value="white" />
            <param name="minRuntimeVersion" value="3.0.40818.0" />

            <param name="autoUpgrade" value="true" />
            <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0" style="text-decoration: none">
                <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"
                    style="border-style: none" />
            </a>
        </object>
        <iframe id="_sl_historyFrame" style="visibility: hidden; height: 0px; width: 0px;
            border: 0px"></iframe>
    </div>

Bien la primer impresión que nos llevamos luego de ejecutar la aplicación es la siguiente:

Para solucionar este inconveniente, es necesario agregar al tag object de html el atributo.

<param name="windowless" value="true" />

Esto permite que de cierta forma el plug-in se integre con el DOM de html, y así podamos a través del manejo de las propiedades zindex indicar que capa asumira la película respecto al div contendor del objeto menu.

Veamos el código completo de la página ASPX:

<%@ Page Language="C#" AutoEventWireup="true" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>ZInexProblem</title>
    <style type="text/css">
        html, body
        {
            height: 100%;
            overflow: auto;
        }
        body
        {
            padding: 0;
            margin: 0;
        }
        #silverlightControlHost
        {
            text-align: left;
            z-index: 0;
        }
        #logo
        {
            float: left;
            width: 10.5em;
            background: #CCCCCC;
            padding: 0.5em 0.5em 0.5em 1em;
            margin: 0;
        }
        .primaryStaticMenu
        {
            background-color: transparent;
            float: right;
        }
        .primaryStaticMenuItem
        {
            width: 10em;
            background-color: #f7f2ea;
            border-width: 1px;
            border-color: #efefef #aaab9c #ccc #efefef;
            border-style: solid;
            color: #777777;
            padding: 0.5em 0 0.5em 1em;
        }
        .primaryStaticHover
        {
            color: #800000;
            background: #f0e7d7;
        }
        
        .primaryDynamicMenu
        {
            background-color: #f7f2ea;
            border-bottom: solid 1px #ccc;
        }
        .primaryDynamicMenuItem
        {
            width: 10em;
            background-color: #f7f2ea;
            color: #777;
            padding: 0.5em 0 0.5em 1em;
            border-width: 1px;
            border-color: #f7f2ea #aaab9c #f7f2ea #efefef;
            border-style: solid;
        }
        .primaryDynamicHover
        {
            color: #800000;
            background: #f0e7d7;
        }
        
        .secondaryLevelOne
        {
            background-color: transparent;
            background-repeat: repeat-x;
            margin: 1.5em 0 0 0;
            padding: 5px 0 0 5px;
            width: 12em;
            height: 35px;
        }
        .secondaryLevelTwo
        {
            background: #FAFBFB;
            padding: 5px 0 5px 5px;
        }
        .secondaryStaticHover
        {
            color: #800000;
        }
    </style>
    <script type="text/javascript" src="Silverlight.js"></script>
    <script type="text/javascript">
        function onSilverlightError(sender, args) {
            var appSource = "";
            if (sender != null && sender != 0) {
                appSource = sender.getHost().Source;
            }

            var errorType = args.ErrorType;
            var iErrorCode = args.ErrorCode;

            if (errorType == "ImageError" || errorType == "MediaError") {
                return;
            }

            var errMsg = "Unhandled Error in Silverlight Application " + appSource + "\n";

            errMsg += "Code: " + iErrorCode + "    \n";
            errMsg += "Category: " + errorType + "       \n";
            errMsg += "Message: " + args.ErrorMessage + "     \n";

            if (errorType == "ParserError") {
                errMsg += "File: " + args.xamlFile + "     \n";
                errMsg += "Line: " + args.lineNumber + "     \n";
                errMsg += "Position: " + args.charPosition + "     \n";
            }
            else if (errorType == "RuntimeError") {
                if (args.lineNumber != 0) {
                    errMsg += "Line: " + args.lineNumber + "     \n";
                    errMsg += "Position: " + args.charPosition + "     \n";
                }
                errMsg += "MethodName: " + args.methodName + "     \n";
            }

            throw new Error(errMsg);
        }
    </script>
</head>
<body>
    <form id="form1" runat="server" style="height: 100%">
    <div id="container">
        <asp:Menu ID="menuPrimary" runat="server" DataSourceID="siteSource1" Orientation="Horizontal"
            StaticEnableDefaultPopOutImage="false" StaticDisplayLevels="1" MaximumDynamicDisplayLevels="1">
            <StaticMenuStyle CssClass="primaryStaticMenu" />
            <StaticMenuItemStyle CssClass="primaryStaticMenuItem" />
            <StaticHoverStyle CssClass="primaryStaticHover" />
            <DynamicMenuStyle CssClass="primaryDynamicMenu" />
            <DynamicMenuItemStyle CssClass="primaryDynamicMenuItem" />
            <DynamicHoverStyle CssClass="primaryDynamicHover" />
        </asp:Menu>
    </div>
    <asp:SiteMapDataSource ID="siteSource1" runat="server" ShowStartingNode="false" />
    <div id="silverlightControlHost">
        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2">
            <param name="source" value="ClientBin/ZInexProblem.xap" />
            <param name="onError" value="onSilverlightError" />
            <param name="background" value="white" />
            <param name="minRuntimeVersion" value="3.0.40818.0" />
            <param name="windowless" value="true" />
            <param name="autoUpgrade" value="true" />
            <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40818.0" style="text-decoration: none">
                <img src="http://go.microsoft.com/fwlink/?LinkId=161376" alt="Get Microsoft Silverlight"
                    style="border-style: none" />
            </a>
        </object>
        <iframe id="_sl_historyFrame" style="visibility: hidden; height: 0px; width: 0px;
            border: 0px"></iframe>
    </div>
    </form>
</body>
</html>

Archivo XML web.sitemap para la fuente de los items del menú.

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

<siteMap xmlns="http://schemas.microsoft.com/AspNet/SiteMap-File-1.0" >

  <siteMapNode title="Home" description="Home Page" url="Default.aspx">
    <siteMapNode title="News" description="The Latest News" url="News.aspx">
      <siteMapNode title="U.S." description="U.S. News" url="News.aspx?cat=us" />
      <siteMapNode title="World" description="World News" url="News.aspx?cat=world" />
      <siteMapNode title="Technology" description="Technology News" url="News.aspx?cat=tech" />
      <siteMapNode title="Sports" description="Sports News" url="News.aspx?cat=sport" />
    </siteMapNode>
    <siteMapNode title="Weather" description="The Latest Weather" url="Weather.aspx" />
  </siteMapNode>
</siteMap>

El resultado final es:

Codigo Link Código

Publicado en .NET, C#, POO, Silverlight

CPOO en Silverlight – Polimorfismo 10


El polimorfismo es nuestro último tema en esta serie de POST para el tutorial de fundamentos de Programación Orientada a Objetos abordada desde Silverlight.

A lo largo de estos post, ya se habrá sugerido de forma abstracta el uso de polimorfismo, pero aquí en este punto es donde se establece su definición y uso.

DEFINAMOS

El polimorfismo, es la capacidad que se tiene en POO para, a partir de una definición base sea posible crear diferentes tipos de comportamiento para un grupo de clases que implementen dicha definición.

Por ejemplo, se tiene la clase Figura y las clases Triangulo, Cuadrado y Circulo y se plantea el requerimiento de calcular el área par a cada figura, en sí el proceso se llama CalcularArea, pero sera la obligación de cada figura generar el código necesario para realizar dicho cálculo.

Veamos el diagrama del clases para el ejemplo:

Como se ve, las clases concretas están implementando la interface IFiguraAreaCalculable, en donde se define un método que apunta a ser de tipo polimorfico, debido a que las clases que implementen esta interface, se someten a generar el código necesario que permita calcular el área correspondiente a cada una de las figuras.

Publicado en .NET, C#, POO, Silverlight

CPOO en Silverlight – Encapsulamiento – 09


En este post se concreta el concepto de Encapsulamiento, pues hasta el momento se habría usado mucho en el recorrido de cada uno de los POST, pero no se había definido un espacio para aclarar este concepro, ¿Por qué asta estas instancias hablar un tema tan importante? Cuando al principio se aborda el tema de encapsulamiento sin haber tenido contacto con términos y conceptos de POO es más tortuoso entender su significado. Luego de estudiar, qué es Clase, Objeto, Propiedades, Comportamientos, Métodos, Estados, Interfaces, Clases Abstractas etc, se puede tener una visión más general sobre el tema.

DEFINAMOS

Encapsulamiento o encapsulación es todo comportamiento, operación o estado interno de un objeto, que para otros objetos o su exterior no es ni relevante ni necesario conocer.

Por ejemplo para aplicaciones silverlight existe el Toolkit de Silverlight que a la hora de crear aplicaciones, permite usar componetes tales como cajas de texto, selectores y otros muchos más controles que permiten crear interfaces de usuario eficientes, compactas e interactivas.

Para ver ejemplos a cerca del uso de estos controles puedes dirigirte al siguiente link.

Ahora es posible afirmar que: El Toolkit de Silverlight encapsula componentes orientados a objetos, los cuales permiten crear y mejorar la experiencia del usuario.

PRACTIQUEMOS

A través de un ejemplo con Silverlight vamos a poner a prueba el poder del encapsulamiento.

1- En una solución de Silverlight en el archivo MainPage.xaml, se va a crear un objeto Ellipse tal cómo se ve en el siguiente código:

<Ellipse x:Name="Balon" Width="50" Height="50" Fill="Black"/>

La idea inicial es poder lograr un efecto de balón con este objeto tipo Shape de Silverlight.

2 – Crearemos 2 botones en la ventana, de forma tal me permitan interactuar con los eventos Click para iniciar y parar la animación.

 <Button Canvas.Left="179" Canvas.Top="265" Content="Empezar"
         Height="23" Name="BtEmpezar" Width="75" Click="BtEmpezar_Click" />
<Button Canvas.Left="270" Canvas.Top="265" Content="Parar"
        Height="23" Name="BtParar" Width="75" Click="BtParar_Click" />

Cada uno de los anteriores objetos con un controlador de evento asociado.

3 – El contenedor principal para este ejemplo sea un Panel tipo canvas, en el cual se va a definir de forma especial un recurso el cual se usaría para lograr el efecto de la animación:

<Canvas x:Name="LayoutRoot" Background="White">
        <Canvas.Resources>
            <Storyboard x:Name="SBAnimacion">
                <DoubleAnimation Storyboard.TargetName="Balon" RepeatBehavior="Forever"
                                 Storyboard.TargetProperty="(Canvas.Top)"
                                 From="0" To="250" Duration="00:00:05">
                    <DoubleAnimation.EasingFunction>
                        <BounceEase Bounces="2" EasingMode="EaseOut" Bounciness="3"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
        </Canvas.Resources>
</canvas>

Como se ve en el anterior código se ha creado un objeto StoryBoard como recurso del objeto Canvas, este objeto el cual llamaremos SBAnimacion va a contener un objeto de tipo animación que permite definir una interacción o comportamiento del Objeto Balon y Propiedad Top de este, en este caso el tipo de animación será DoubleAnimation, en la cual se configuran los parámetros de dicha animación. Incluido en el código y dentro del objeto DoubleAnimation existe una Propiedad especial, llamada EasingFunction, en el cual se definen unos atributos más, respecto a la animación que se está haciendo, y con el objetivo de obtener el efecto de rebote para el balón(funciones matemáticas de comportamiento para los objetos de la UI en Silverlight).

Cómo se ve hasta este punto no se le ha hecho nada más si no mediante código XAML parametrizar cada objeto respecto a lo que se quiere hacer al momento de ejecutar la animación.

Si vemos el código completo XAML quedará así:

<UserControl x:Class="Silverlight_CPOO_03_Encapsulamiento.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Canvas x:Name="LayoutRoot" Background="White">
        <Canvas.Resources>
            <Storyboard x:Name="SBAnimation">
                <DoubleAnimation Storyboard.TargetName="Balon" RepeatBehavior="Forever"
                                 Storyboard.TargetProperty="(Canvas.Top)"
                                 From="0" To="250" Duration="00:00:05">
                    <DoubleAnimation.EasingFunction>
                        <BounceEase Bounces="2" EasingMode="EaseOut" Bounciness="3"/>
                    </DoubleAnimation.EasingFunction>
                </DoubleAnimation>
            </Storyboard>
        </Canvas.Resources>
        <Ellipse x:Name="Balon" Width="50" Height="50" Fill="Black"/>
        <Button Canvas.Left="179" Canvas.Top="265" Content="Empezar" Height="23" Name="BtEmpezar" Width="75" Click="BtEmpezar_Click" />
        <Button Canvas.Left="270" Canvas.Top="265" Content="aParar" Height="23" Name="BtParar" Width="75" Click="BtParar_Click" />
    </Canvas>
</UserControl>

Ahora veamos el código de C#:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight_CPOO_03_Encapsulamiento
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
        }

        private void BtEmpezar_Click(object sender, RoutedEventArgs e)
        {
            SBAnimation.Begin();
        }

        private void BtParar_Click(object sender, RoutedEventArgs e)
        {
            SBAnimation.Stop();
        }
    }
}

Si repasamos el código de C#, en ninguna parte estamos creando algún tipo de funcionalidad para mover el objeto Balón de tipo Ellipse en pantalla, pero si se observa el código de cada evento generado por cada botón, allí se hace el llamado a funciones del objeto StoryBoard siendo estas Begin() y Stop(), cada una para iniciar y parar la animación respectivamente. Hasta este punto solo se ha estado configurando y estableciendo los llamados a los métodos que internamente ejecutan y controlan la animación, lo interesante acá es que para nosotros no es ni relevante, ni necesario conocer cómo se haya implementado el código que este por debajo de esos métodos, y es aquí donde vale destacar el poder de “encapsular”, pues se esta usando un objeto el cual determina cómo utilizar X configuración en pro de ejecutar una animación y después de eso la gestión será interna sin tener nosotros que preocuparnos por mucho más.

Veamos un pequeño video en el que se ve la ejecución de la aplicación:

Publicado en .NET, ASP.NET, C#, POO, Silverlight

CPOO en Silverlight – Modificadores de Ámbito– 08


Un tema importante a tener en cuenta en POO son los modificadores de ámbito.

DEFINAMOS

Un modificador de ámbito permite que las partes de un objeto puedan ser expuestas al exterior y a la vez especificar aquellas que no serán accesibles o modificables.

Los tres tipos de modificadores más importantes y a tener muy en cuenta en POO son:

public: Permite que un objeto, clase, propiedad, método entre otros sean accesibles desde cualquier punto de un código de Software Orientado a Objetos.

private: en cuanto a propiedades, métodos u otros componentes que pertenezcan a un objeto sólo se permite accederlos y manipularlos internamente en el bloque que define la clase y en ningún otro lugar más.

protected: Cuando se habla de un objeto que hereda de otro, es posible afirmar que, si un atributo, método u otro está marcado como protected, su uso sera posible en el bloque de la clase que lo define o en aquellas clases que están heredando de la principal.

Complementando este tema, en el siguiente post se habla sobre Encapsulamiento.

Publicado en .NET, C#, POO, Silverlight

CPOO en Silverlight – Herencia – Interfaces – 07


Existe una tercer forma de permitir que una clase sea más robusta, y es a través de la interfaces como puedo indicar a una o varias clases un comportamiento similar.

DEFINAMOS

Una interface permite definir el tipo de objeto más abstracto posible en POO, debido a que no implementa ningún tipo de funcionalidad, carece de constructor y no se puede inicializar ninguna instancia a partir de su propio tipo.

PRACTIQUEMOS

1- Para crear una interface, lo primero es agregar un item tipo clase al proyecto y luego modificarle el atributo class por interface.

2 – Recordemos que a diferencia de las clases abstractas una interfas no implementa nada respecto a sus propiedades o métodos.

3 – A diferencia de herencia las interfaces indican uncicamente la forma de implementación.

Un ejercicio para aplicar esto puede verse en la necesidad de enviar diferentes avisos de publicidad a diferentes tipos de usuario. Por ejemplo en una Pizzería se requiere enviar la oferta del día en una forma muy gráfica a sus clientes favoritos, mientras que una Librería quiere enviar la la oferta del Libro recomendado para el día a sus clientes que son personas elegantes y serias.

Lo primero es crear un componente genérico sobre el cual se puedan cargar los mensajes que van a ser enviados. Y luego tener una forma de crear la interfaz de usuario, el mensaje y enviarlo.

Para este ejercicio se pensó la siguiente interface:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight_CPOO_02_Herencia_Interfaces
{
    public interface ICreadorMensaje
    {
        string Titulo { get; set; }

        string Contenido { get; set; }

        string De { get; set; }

        string Para { get; set; }

        void CrearMensaje(Panel panel);
    }
}

Como se vé, existen propiedades que permiten especificar el mensaje en sí, y existe un método el cual requiere como parámetro un objeto Panel en el cual se va a escribir o dibujar el mensaje que se envía al usuario final.

Se crean 2 UserControl, para simular los dos tipos de entidades, Librería y Pizzería así:

Publicado en .NET, ASP.NET, C#, POO, Silverlight

CPOO en Silverlight – Herencia y Clases Abstractas – 06


En POO además de poder heredar comportamientos o atributos, también es posible permitir que dichos comportamientos o características, sean definidos por las clases que implementen una clase abstracta.

DEFINAMOS

La Clase abstracta es una forma para definir un tipo de Objeto genérico, por lo tanto no será posible crear una instancia a partir de dicha clase.

Por ejemplo, pensemos en clases como Carro, Avión, Cicla o Barco, en común se puede abstraer que todos ellos son vehículos, así la definición de un tipo abstracto será la clase Vehiculo.


    public abstract class Vehiculo
    {
        public abstract void Encender();
        public abstract void Mover();
        public abstract void Parar();
        public abstract void Apagar();
    }

Un Vehiculo no constituye nada puntual para un software orientado a objetos, por lo tanto nunca podría crearse un objeto a partir de esta clase:

Pero si podemos crear clases las cuales hereden esa la clase abstracta:

    public class Avion: Vehiculo
    {

        public override void Encender()
        {

        }

        public override void Mover()
        {

        }

        public override void Parar()
        {

        }

        public override void Apagar()
        {

        }
    }

    public class Carro : Vehiculo
    {

        public override void Encender()
        {

        }

        public override void Mover()
        {

        }

        public override void Parar()
        {

        }

        public override void Apagar()
        {

        }
    }

     public class Barco: Vehiculo
    {

        public override void Encender()
        {

        }

        public override void Mover()
        {

        }

        public override void Parar()
        {

        }

        public override void Apagar()
        {

        }
    }

Así al inicializar un avión, carro o barco, lo que realmente se está haciendo es crear la instancia de un objeto tipo Vehiculo.

Pero esto no se diferencia mucho de lo que se vio en el capítulo anterior de Herencia. Entonces ¿Qué es y para que sirve una clase abstracta?

Para explicar esto veamos el siguiente ejemplo:

Para el ejemplo de la clase Vehiculo existen acciones (métodos) abstractas por ejemplo: Encender, Mover, Parar y Apagar pero para este caso será la responsabilidad de cada Subclase (Carro, Barco, Avion) implementar lo necesario para llevar a cabo esos procesos.

Publicado en .NET, C#, Silverlight

CPOO en Silverlight – Herencia – 05


Este es uno de los pilares y conceptos más importantes en el paradigma de Programación Orientada a Objetos:

DEFINAMOS

Herencia es una relación entre clases, a través de la cual una clase (Base) permite que sus miembros, atributos, métodos entre otros, puedan ser reutilizados por otras clases (Subclases) y por otra parte se pueda extender la funcionalidad inicial.

Pensemos en un juego de Ajedrez y veamos por ejemplo la necesidad de crear piezas negras y blancas. Pero sinteticemos algo más esto, veamos que hay diferentes tipos de piezas y cada una tiene un tipo de movida diferente.

– Rey – Dama – Alfil – Caballo – Torre – Peón

De este grupo se elige por ejemplo: Caballo y Torre.

El caballo corre en L es decir que segun su posición inicial avanza dos unidades y gira una en sentido lateral.

La torre en cambio se desplaza horizontal y verticalmente tanto como tenga espacio para avanzar.

Según esta pequeña introducción al movimiento de este tipo de piezas. Continuamos y pasamos a abstraer el tipo de objeto base, se tiene en común que ambas tanto Caballo como Torre  son Piezas de jugar al ajedrez. Por lo que se puede ver allí, el primer tipo de objeto es la clase Pieza.

Pero antes de seguir con la definición de la clase, veamos un nuevo tipo de dato  especial, tenemos un enum (Enumeración de tipos de dato), el cual me va a permitir definir si la pieza es blanca o negra, de esta forma se puede conocer si un objeto pertenece al bando blanco o al bando negro.

Posible Diagrama de clases:

Publicado en ASP.NET, Silverlight, WebCast

CPOO en Silverlight – Clases y Objetos – 04


En el siguiente WEBCAST se ve el compendio de los temas tratados hasta el momento, Clases, Objetos en aplicaciones Silverlight.

Código de la clase Balón:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight_CPOO_01_Clases_Demo
{
    public class Balon
    {
        private const double distancia = 10;
        public Ellipse Grafico { get; set; }

        public Balon()
        {
            Grafico = new Ellipse();
            Grafico.Height = 50;
            Grafico.Width = 50;
            Grafico.Fill = new SolidColorBrush(Colors.Green);
        }

        public void MoverArriba()
        {
            double posTop = (double)Grafico.GetValue(Canvas.TopProperty);
            posTop -= distancia;
            Grafico.SetValue(Canvas.TopProperty, posTop);
        }

        public void MoverAbajo()
        {
            double posTop = (double)Grafico.GetValue(Canvas.TopProperty);
            posTop += distancia;
            Grafico.SetValue(Canvas.TopProperty, posTop);
        }

        public void MoverIzquierda()
        {
            double posLeft = (double)Grafico.GetValue(Canvas.LeftProperty);
            posLeft -= distancia;
            Grafico.SetValue(Canvas.LeftProperty, posLeft);
        }

        public void MoverDerecha()
        {
            double posLeft = (double)Grafico.GetValue(Canvas.LeftProperty);
            posLeft += distancia;
            Grafico.SetValue(Canvas.LeftProperty, posLeft);
        }
    }
}

Código de la clase MainPage

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight_CPOO_01_Clases_Demo
{
    public partial class MainPage : UserControl
    {
        Balon balon;
        public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            balon = new Balon();
            LayoutRoot.Children.Add(balon.Grafico);
        }

        private void btArr_Click(object sender, RoutedEventArgs e)
        {
            balon.MoverArriba();
        }

        private void btIzq_Click(object sender, RoutedEventArgs e)
        {
            balon.MoverIzquierda();
        }

        private void btAba_Click(object sender, RoutedEventArgs e)
        {
            balon.MoverAbajo();
        }

        private void btDer_Click(object sender, RoutedEventArgs e)
        {
            balon.MoverDerecha();
        }
    }
}

Código de la UI para el manejo del Balón:

<UserControl x:Class="Silverlight_CPOO_01_Clases_Demo.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="400">

    <Canvas x:Name="LayoutRoot" Background="White">
        <Button Canvas.Left="244" Canvas.Top="227" Content="Arriba" Height="23" Name="btArr" Width="75" Click="btArr_Click" />
        <Button Canvas.Left="163" Canvas.Top="256" Content="Izquierda" Height="23" Name="btIzq" Width="75" Click="btIzq_Click" />
        <Button Canvas.Left="244" Canvas.Top="256" Content="Abajo" Height="23" Name="btAba" Width="75" Click="btAba_Click" />
        <Button Canvas.Left="325" Canvas.Top="256" Content="Derecha" Height="23" Name="btDer" Width="75" Click="btDer_Click" />
    </Canvas>
</UserControl>

Publicado en .NET, ASP.NET, POO, Silverlight, WebCast

CPOO en Silverlight – Clases y Objetos – 03


Después de haber estudiado el concepto de Clase y Objeto pasemos a estudiar algunos objetos de silverlight.

DEFINAMOS

LAYOUT

Para empezar con silverlight se deben tener claros conceptos tales como en que forma se van a posisionara los controles (objetos) y que objetos me permiten organizar visualmente la UI (interfaz de usuario) de forma tal que para el usuario una aplicación sea atractiva y funcional.

Objetos de tipo Panel tales como canvas, grid, stackpanel son muy importantes a la hora de implementar el layout o UI (interfaz de usuario) en una aplicación Silverlight.

PRACTIQUEMOS

1 – Grid : Objeto contenedor  para posicionar elementos de la UI en aplicaciones Silverlight, en forma de tabla o cuadricula.

XAML

<Grid x:Name="LayoutRoot" Background="White" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Button Name="BT00" Content="0 0" Grid.Column="0" Grid.Row="0" FontSize="28"></Button>
            <Button Name="BT01" Content="0 1" Grid.Column="1" Grid.Row="0" FontSize="28"></Button>
            <Button Name="BT02" Content="0 2" Grid.Column="2" Grid.Row="0" FontSize="28"></Button>

            <Button Name="BT10" Content="1 0" Grid.Column="0" Grid.Row="1" FontSize="28"></Button>
            <Button Name="BT11" Content="1 1" Grid.Column="1" Grid.Row="1" FontSize="28"></Button>
            <Button Name="BT12" Content="1 2" Grid.Column="2" Grid.Row="1" FontSize="28"></Button>

            <Button Name="BT20" Content="2 0" Grid.Column="0" Grid.Row="2" FontSize="28"></Button>
            <Button Name="BT21" Content="2 1" Grid.Column="1" Grid.Row="2" FontSize="28"></Button>
            <Button Name="BT22" Content="2 2" Grid.Column="2" Grid.Row="2" FontSize="28"></Button>
        </Grid>

Viendo el anterior código se observa dentro del Grid, una sección Grid.ColumnDefinitions, una Grid.RowDefinitions las dos anteriores permiten determinar el número de columnas y el número de filas respectivamente. La definición de cada objeto tipo botón se hace a través de las propiedades Grid.Column y Grid.Row referentes a la fila y columna respectiva como se ve en la imagen inferior.

Código XAML

<UserControl x:Class="Silverlight_CPOO_Clases_03.MainPage"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
            xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
            mc:Ignorable="d"
            d:DesignHeight="800" d:DesignWidth="400">
    <Grid Name="LayoutPrincipal">
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <Grid x:Name="LayoutRoot" Background="White" Grid.Row="0">
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition/>
                <RowDefinition/>
                <RowDefinition/>
            </Grid.RowDefinitions>

            <Button Name="BT00" Content="0 0" Grid.Column="0" Grid.Row="0" FontSize="28"></Button>
            <Button Name="BT01" Content="0 1" Grid.Column="1" Grid.Row="0" FontSize="28"></Button>
            <Button Name="BT02" Content="0 2" Grid.Column="2" Grid.Row="0" FontSize="28"></Button>

            <Button Name="BT10" Content="1 0" Grid.Column="0" Grid.Row="1" FontSize="28"></Button>
            <Button Name="BT11" Content="1 1" Grid.Column="1" Grid.Row="1" FontSize="28"></Button>
            <Button Name="BT12" Content="1 2" Grid.Column="2" Grid.Row="1" FontSize="28"></Button>

            <Button Name="BT20" Content="2 0" Grid.Column="0" Grid.Row="2" FontSize="28"></Button>
            <Button Name="BT21" Content="2 1" Grid.Column="1" Grid.Row="2" FontSize="28"></Button>
            <Button Name="BT22" Content="2 2" Grid.Column="2" Grid.Row="2" FontSize="28"></Button>
        </Grid>

    </Grid>
</UserControl>

Y para la carga del Grid desde C#:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Silverlight_CPOO_Clases_03
{
    public partial class MainPage : UserControl
    {
        public MainPage()
        {
            InitializeComponent();
            Loaded += new RoutedEventHandler(MainPage_Loaded);
        }

        void MainPage_Loaded(object sender, RoutedEventArgs e)
        {
            //Inicialización de un objeto Grid
            Grid grid = new Grid();

            //Definición de Columnas
            grid.ColumnDefinitions.Add(new ColumnDefinition());
            grid.ColumnDefinitions.Add(new ColumnDefinition());
            grid.ColumnDefinitions.Add(new ColumnDefinition());

            //Definición de Filas
            grid.RowDefinitions.Add(new RowDefinition());
            grid.RowDefinitions.Add(new RowDefinition());
            grid.RowDefinitions.Add(new RowDefinition());

            //Primera fila de botones/////////////////
            Button button00 = new Button();
            button00.SetValue(Grid.ColumnProperty, 0);
            button00.SetValue(Grid.RowProperty, 0);
            button00.Content = "0 - 0";
            grid.Children.Add(button00);

            Button button01 = new Button();
            button01.SetValue(Grid.ColumnProperty, 1);
            button01.SetValue(Grid.RowProperty, 0);
            button01.Content = "0 - 1";
            grid.Children.Add(button01);

            Button button02 = new Button();
            button02.SetValue(Grid.ColumnProperty, 2);
            button02.SetValue(Grid.RowProperty, 0);
            button02.Content = "0 - 2";
            grid.Children.Add(button02);
            ////////////////////////////////////////////

            //Segunda Fila//////////////////////////////
            Button button10 = new Button();
            button10.SetValue(Grid.ColumnProperty, 0);
            button10.SetValue(Grid.RowProperty, 1);
            button10.Content = "1 - 0";
            grid.Children.Add(button10);

            Button button11 = new Button();
            button11.SetValue(Grid.ColumnProperty, 1);
            button11.SetValue(Grid.RowProperty, 1);
            button11.Content = "1 - 1";
            grid.Children.Add(button11);

            Button button12 = new Button();
            button12.SetValue(Grid.ColumnProperty, 2);
            button12.SetValue(Grid.RowProperty, 1);
            button12.Content = "1 - 2";
            grid.Children.Add(button12);
            ////////////////////////////////////////////

            ///Tercer Fila//////////////////////////////
            Button button20 = new Button();
            button20.SetValue(Grid.ColumnProperty, 0);
            button20.SetValue(Grid.RowProperty, 2);
            button20.Content = "2 - 0";
            grid.Children.Add(button20);

            Button button21 = new Button();
            button21.SetValue(Grid.ColumnProperty, 1);
            button21.SetValue(Grid.RowProperty, 2);
            button21.Content = "2 - 1";
            grid.Children.Add(button21);

            Button button22 = new Button();
            button22.SetValue(Grid.ColumnProperty, 2);
            button22.SetValue(Grid.RowProperty, 2);
            button22.Content = "2 - 2";
            grid.Children.Add(button22);
            /////////////////////////////////////////////

            //Por último se agrega el nuevo Grid al layout
            //Principal y así poder comparar las dos formas
            //mencionadas.
            grid.SetValue(Grid.RowProperty, 1);
            LayoutPrincipal.Children.Add(grid);
        }
    }
}

Tal como se ve en el código de C# la Programación Orientada a Objetos es muy importante a la hora de crear controles dinámicos para una aplicación de silverlight, pero es innegable la facilidad y legibilidad del código XAML a la hora de definir objetos de la UI.

Si inspeccionamos un poco los objetos de Silverlight como button o grid se puede ver allí que hay diferentes métodos y propiedades. Sin profundizar mucho en estas instancias, clases y tipos de objeto es posible afirmara que:

button21.SetValue(Grid.ColumnProperty, 1);

A través de este método se puede establecer el valor index referente de la propiedad Column en la que se va a posicionar el objeto button, una vez sea agregado al control Grid.

button21.SetValue(Grid.RowProperty, 2);

En este caso y de igual forma que en el anterior se establece la posición pero referente a la fila del Grid.

button21.Content = “2 – 1”;

El objeto button dispone de una propiedad Content (de tipo object) la cual permite registrar cual va a ser el contenido del botón, en este caso un texto.

grid.Children.Add(button21);

El objeto Grid contiene una propiedad Children (de tipo UIElementCollection), en la cual se puede hacer uso del método Add para agregar cada elemento al control contenedor.

Así pues se empieza a notar que de la Programación Orientada a Objetos en Silverlight, permite a través de las propiedades y métodos de un objeto poder configurar y en este caso a un botón darle su respectiva posición cuando es agregado a un control Grid desde código. Aclarando que la forma estándar de hacer esto es crear la UI en código XAML el cual es por mucho, más fácil, flexible y legible.