Tutorial Silverlight 1.0 con ejemplo práctico.

Pincha aquí para ver el resultado, para ver si te animas a seguir.

Hola que tal, les dejo un tutorial del Silverlight 1.0, con un ejemplo práctico, algunos podrían decir "por que de 1.0 si ya estamos a puertas de la versión 2 definitiva", primero que nada, SL 1.0 apunta a otro tipo de aplicaciones, solo con programación del lado del cliente, por lo que si queremos hacer un banner o algún tipo de publicidad, etc, para que vamos a hacer que el usuario descargue 4.6 Mb solo para ver un aviso!, es descabellado. Pero bueno, veamos el caso práctico.

Tenemos el siguiente caso:

Una pequeña publicidad en donde el usuario puede arrastrar el color al Auto(un Peugeot 206, que es el que tengo, jejej) y la imagen del 206 cambiará de color. Además el muchacho (o muchacha, en realidad no sé), va a pestañear cada 6 segundos, los cuales podrían ser aleatorios.

La siguiente imagen ilustra el cambio de color del auto,

image
image  

Diseño

Para la construcción, lo primero fue pensar en el diseño, si bien no quedó muy bonito, (se hizo lo que se pudo!). Utilizaremos Microsoft Expression Blend , el CTP de Junio 2008 que lo puedes descargar de aquí. En realidad, si tienes el ctp de marzo, para este ejemplo da lo mismo, ya que no ocupamos nada nuevo de SL 2.0.

Lo primero es agregar al proyecto las imágenes  que vamos a utilizar, las cuales son:

image

Estas Imágenes nos van a permitir realizar el efecto de cambiar el color del auto según lo seleccionado por el usuario, además, si te fijas, existen dos imágenes con la cara del tipo que nos indica que hacer, esto es por que vamos a conseguir el efecto de "pestañeo" del tipo.

Luego vamos a diseñar con las figuras poligonales que nos ofrece ExpBlend el título y la paleta de colores, si te das cuenta el fondo, al igual que el titulo tiene un fondo degradado, esto se logra con las propiedades de "Brushes" en la barra de propiedades de un objeto.

La barra de colores, tiene algunas particularidades que tenemos que revisar.

Barra de Exploración de objetos Diseño de la Paleta
image

image

Podemos notar que existen cuadros de colores llamados color_fijo y color_movil, por cada uno de los colores, ahora bien, el cuadro de color fijo esta exactamente bajo el cuadro móvil ( te puedes fijar en las posiciones para comprobarlo) y esto tiene una razón de ser, cuando arrastramos el cuadro hacia el auto, debemos dejar una copia del cuadro en su posición, para que no quede el lugar vacío.

Con cuadro fijo de fondo Sin cuadro fijo de fondo
image image

Esta paleta de colores esta agrupada en un Canvas, por lo que va a afectar el calculo de la posición para determinar si el cuadro que se está arrastrando está efectivamente sobre el auto. Ya que los objetos contenidos en un canvas tienen sus propiedades atachadas, canvas.top y canvas.left en relación al canvas en donde están contenidos y no a todo el canvas principal.

image
Para el calculo de las posiciones a nivel del Canvas principal, vamos a tener que hacer referencia a posiciones negativas (sobre el canvas paleta)

Codificación.

1. Pestañeo

Primero veamos los ojos y como vamos hacer que el cristiano pestañee, la idea es que cada cierto tiempo se haga una sustitución de imagen. ( ojosOn = Ojos Abiertos,  OjosOff = Ojos Cerrados). Entonces lo que en realidad necesitamos es llamadas a funciones de ojosOn y ojosOff cada cierto período de tiempo, por lo que tenemos:

function ojosOn(){
document.getElementById("SilverlightControl").content.findName("cara").Source="caras/LinkPH.png";
    setTimeout("ojosOff()", 6000);
 
}

function ojosOff(){                            document.getElementById("SilverlightControl").content.findName ("cara").Source="caras/LinkPH3.png";
  setTimeout("ojosOn()", 300);
}

Teniendo en cuenta que:
LinkPH.png  =>Imagen ojos Abiertos
LinkPH3.png =>Imagen ojos Cerrados.

Tenemos que recordar que podemos hacer referencia a un objeto dentro del XAML con:
document.getElementById("SilverlightControl").content.findName (NombreDelObjeto).propiedad;

Por lo que vamos cambiando la propiedad source para hacer la sustitición.
Podemos darnos cuenta que utilizamos la función setTimeout para llamar a cierta cantidad de milisegundos una función u otra, esto nos permitirá hacer el efecto de pestañeo. La llamada por primera vez a la función ojosOn esta en la declaración del Canvas Principal:

<Canvas
      xmlns="http://schemas.microsoft.com/client/2007"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      Width="619" Height="338"
      x:Name="proyecto" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" Loaded="ojosOn">

2. Drag & Drop y cambio de Color del Auto.

Ahora que sabemos como cambiar las imágenes haciendo referencia al atributo Source de un objeto imagen, ya nos imaginamos como ocurre el "mágico cambio de color del auto".

El código para hacer Drag&Drop es un código más bien genérico para este propósito, un poco modificado para poder determinar , una vez que dejen de arrastrar el cuadro y se libera el botón del mouse (MouseLeftButtonUp), la posición en donde esto ocurrió, si esta dentro del perímetro de la imagen del auto, se cambia de color. Revisemos el código:

var beginX;
var beginY;
var trackingMouseMove = false;

 function onMouseDown (sender, mouseEventArgs)
     {   sender.Visibility="Visible";
         beginX = mouseEventArgs.getPosition(null).x;
        
beginY = mouseEventArgs.getPosition(null).y;
         sender.Opacity = .5;
       
 trackingMouseMove = true;
        
sender.captureMouse();

    }

function onMouseMove (sender, mouseEventArgs)
    {   sender.Visibility="Visible";
        if (trackingMouseMove == true)
         {
          var actualX = mouseEventArgs.getPosition(null).x;
          var actualY = mouseEventArgs.getPosition(null).y;
          sender["Canvas.Left"] += actualX – beginX;
          sender["Canvas.Top"] += actualY – beginY;
          beginX = actualX;
          beginY = actualY;
                }
      }

function onMouseUp (sender, mouseEventArgs)
     {   sender.releaseMouseCapture();
        
trackingMouseMove = false;
        
switch(sender.Name){
               case "black_movil":
                 var imagen="img/peugeot_206_black.png";
                 checkinside(sender,‘_206’,imagen);
                 sender["Canvas.Top"]="14";
                 sender["Canvas.Left"]="12";
               break;
               case "celeste_movil":
                   var imagen="img/peugeot_206_blue.png";
                   checkinside(sender,‘_206’,imagen);
                   sender["Canvas.Top"]="14";
                   sender["Canvas.Left"]="84";
               break;

               case "blanco_movil":
                  var imagen="img/peugeot_206_grey.png";
                  checkinside(sender,‘_206’,imagen);
                  sender["Canvas.Top"]="14";
                  sender["Canvas.Left"]="157";
               break;
               case "naranjo_movil":
                    var imagen="img/peugeot_206_orange.png";
                    checkinside(sender,‘_206’,imagen);
                    sender["Canvas.Top"]="14";
                    sender["Canvas.Left"]="228";
              break;
              case "rojo_movil":
                    var imagen="img/peugeot_206_red.png";
                    checkinside(sender,‘_206’,imagen);
                    sender["Canvas.Top"]="14";
                    sender["Canvas.Left"]="300";
               break;
             }
            }

   function checkinside(sender,element,imagen)
 
{
   if (((sender["Canvas.Top"]>-180)&&(sender["Canvas.Top"]< -68))&&((sender["Canvas.Left"]> 61)&&(sender["Canvas.Left"]< 252)))
    {
   
  sender.findName(element).Source=imagen;
 
  }
  }

Y las llamadas a las funciones en el código XAML:

<Rectangle MouseLeftButtonUp="onMouseUp" MouseLeftButtonDown="onMouseDown" MouseMove="onMouseMove" Width="68" Height="57.709" Fill="#FFBCCDDF" Stroke="#FF000000" RadiusX="14.5" RadiusY="14.5" x:Name="blanco_movil" Canvas.Left="157" Canvas.Top="14"/>

            <Rectangle MouseLeftButtonUp="onMouseUp" MouseLeftButtonDown="onMouseDown" MouseMove="onMouseMove" Width="68" Height="57.709" Fill="#FFE47827" Stroke="#FF000000" RadiusX="14.5" RadiusY="14.5" x:Name="naranjo_movil" Canvas.Left="228" Canvas.Top="14"/>

            <Rectangle MouseLeftButtonUp="onMouseUp" MouseLeftButtonDown="onMouseDown" MouseMove="onMouseMove" Width="68" Height="57.709" Fill="#FF4C80BA" Stroke="#FF000000" RadiusX="14.5" RadiusY="14.5" x:Name="celeste_movil" Canvas.Left="84" Canvas.Top="14" RenderTransformOrigin="2.015,0.606"/>

            <Rectangle MouseLeftButtonUp="onMouseUp" MouseLeftButtonDown="onMouseDown" MouseMove="onMouseMove" Width="68" Height="57.709" Fill="#FFEE470D" Stroke="#FF000000" RadiusX="14.5" RadiusY="14.5" x:Name="rojo_movil" Canvas.Left="300" Canvas.Top="14"/>

            <Rectangle MouseLeftButtonUp="onMouseUp" MouseLeftButtonDown="onMouseDown" MouseMove="onMouseMove" Width="68" Height="57.709" Fill="#FF595D63" Stroke="#FF000000" RadiusX="14.5" RadiusY="14.5" x:Name="black_movil" Canvas.Left="12" Canvas.Top="14"/>

El código no es tan extenso :), lo hacemos es en la función onMouseUp es determinar el nombre del sender, es decir, del objeto que se está arrastrando (cuadro_movil). Entonces, como decíamos, determinamos el nombre del objeto y lo sometemos a evaluaciones con switch, y dependiendo del caso, seteamos la variable imagen con la ruta que corresponde a la imagen del auto según el color, luego llamamos a la función checkinside, con los tres argumentos, sender, element e imagen. Sender es el objeto que se arrastra y lo ocupamos para comprobar la posición (aquí se ve que se hacen comparaciones a posiciones negativas), element, que hace referencia a la imagen _206 y e imagen, que tiene la ruta de la imagen.

Una vez que determinamos si está o no dentro de la imagen, devolvemos el cuadro a su lugar, para que no quede sobre la imagen del auto (función onMouseUp).

Como vez, no es difícil y se logra un efecto interesante!

Ve el resultado de este ejemplo aquí

Baja el código aquí

Espero que te haya servido!, se agradecen los comentarios!!! 😛
Saludos,
Gonzalo

Listar Archivos de una carpeta con LinQ y ASP.NET

Algunas veces debemos listar el contenido de una carpeta del servidor en nuestras intranets, por distintos motivos. Ahora que existe LinQ , a mi parecer es mucho más cómodo e intuitivo.

Para el ejemplo, vamos a tener un dropdownlist que va a contener una lista de todas las extensiones de archivo que hay en la carpeta, además un GridView que va a contener una lista con la info de los archivos cuya extensión coincide con lo seleccionado en el dropdownlist.

Partamos por el “Diseño”, que es simplemente aplicar un autoformato sobre el GridView 🙂 y el dropdownlist tiene la propiedad autopostback=true

Espacio de Nombres:

Imports System.Linq
Imports System.IO

Diseño:

image 

Ahora veamos el código asociado al iniciar el formulario.

Código:

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

If Not Page.IsPostBack Then

Dim tipo= From archivo In Directory.GetFiles(“/”) _
          Let extension = New FileInfo (archivo).Extension _
          Select Ext = extension, _
                 descripcion = “Archivos “ & extension _
         
Distinct

For Each f In tipo
     filtro.Items.Add(New ListItem(f.descripcion, f.Ext))
Next

End If
End Sub

Algunos puntos que debemos ver de este código que sirve para listar en el dropdownlist que se llama filtro. Primero, hacemos la consulta sobre la coleccion que devuelve GetFiles de mi carpeta raíz, luego utilizo Let para setear la variable extension. Hay que tener en cuenta que si asignas a una variable un valor por medio de Let , ya no vas a poder asignarle nuevamente otro valor, es decir, solo una vez puedes asignarle un valor por este medio. Ya que podemos tener varios archivos con la misma extensión, ocupamos Distinct para que solo nos traiga una ocurrencia de “registros”. Como vez es lo mismo que ocupar Distinct en una variable SQL.

Protected Sub filtro_SelectedIndexChanged(ByVal sender As Object, ByVal e As System.EventArgs) Handles filtro.SelectedIndexChanged

Dim archivos = From archivo In Directory.GetFiles(“/”) _
Where Me.filtro.SelectedValue = New FileInfo(archivo).Extension _
Select Nombre = New FileInfo(archivo).Name, _
        FechaCreacion = New FileInfo(archivo).CreationTime, _
        Carpeta = New FileInfo(archivo).DirectoryName, _
        Extension = New FileInfo(archivo).Extension

Me.listado.DataSource = archivos
Me.listado.DataBind()
End Sub

En este código hacemos la consulta que nos trae la información de los archivos cuya extensión coincide con la selección del dropdownlist. Ocupamos Where  para filtrar por la extensión sobre la misma colección y obtenemos la info de los archivos. Luego bindeamos la colección genérica archivos.

image

Y logramos lo que queríamos, espero que te siva!.

Te dejo acá el link el skydrive para que bajes el código.

Nos vemos y gracias por leer este post!.

Gonzalo