Aplicando el patrón MVVM en WPF .NET Core

Acá les dejo la serie de videos que hice para dar mas luz acerca de todas las dudas que poseen sobre este patrón de arquitectura MVVM.

Espero les sea de gran utilidad para sus proyectos en WPF, luego les explicare brevemente en UWP y Xamarin Forms.

Saludos.

Microsoft .NET Framework 4.8

Estamos encantados de anunciar el lanzamiento de .NET Framework 4.8. Se incluye en la actualización de Windows 10 de mayo de 2019. .NET Framework 4.8 también está disponible en Windows 7+ y Windows Server 2008 R2 +.

Puede instalar .NET 4.8 desde nuestro sitio de descarga .NET. Para crear aplicaciones dirigidas a .NET Framework 4.8, puede descargar NET 4.8 Developer Pack. Si solo desea el tiempo de ejecución de .NET 4.8, puede probar:

.NET 4.8 Web installer: requiere una conexión a Internet durante la instalación.
 .NET 4.8 Offline installer: se puede descargar e instalar más tarde en un estado desconectado.

Mejoras en la versión

.NET Framework 4.8 incluye un conjunto de herramientas actualizado, así como mejoras en varias áreas:

     [Tiempo de ejecución] Mejoras JIT y NGEN
     [BCL] ZLib actualizado
     [BCL] Reducción del impacto de FIPS en la criptografía
     [WinForms] Mejoras de accesibilidad
     [WCF] Mejoras de comportamiento del servicio
     [WPF] Mejoras de alta DPI, Mejoras de automatización UIA

Puede ver la lista completa de mejoras en las notas de la versión de .NET Framework 4.8. Las fuentes de referencia también se han actualizado para .NET 4.8.

Versiones de Windows compatibles

Versiones de cliente de Windows: Windows 10 versión 1903, Windows 10 versión 1809, Windows 10 versión 1803, Windows 10 versión 1709, Windows 10 versión 1703, Windows 10 versión 1607, Windows 8.1, Windows 7 SP1
Versiones de Windows Server: Windows Server 2019, Windows Server versión 1803, Windows Server 2016, Windows Server 2012, Windows Server 2012 R2, Windows Server 2008 R2 SP1

Pruebe estas mejoras en .NET Framework 4.8 y comparta sus comentarios en los comentarios a continuación o a través de GitHub.

¡Gracias!

Primer vistazo a Xamarin Essentials

Originalmente llamado Caboodle, Xamarin.Essentials es una libreria simple para acceder a funciones nativas tanto para iOS, Android y UWP

xamarin-essentials

Para hacerlo más fácil, ahora existe Xamarin.Essentials, un paquete único que puede instalar en cualquier aplicación Xamarin para obtener acceso multiplataforma a una amplia gama de API, como acelerómetro, brújula, conectividad de red, mantener la pantalla encendida y más . Puede ver la lista completa de características compatibles en la página de Xamarin Essentials GitHub. Este paquete actualmente tiene 24 conjuntos de API diferentes, con más planeado. Essentials es para todas las aplicaciones de Xamarin, tanto tradicionales como de formularios.

Empezando

Aquí, usaré Xamarin.Forms como punto de partida, simplemente agregue el paquete Xamarin.Essentials NuGet a todos los proyectos (iOS, Android y .NET estándar). Dado que actualmente se encuentra en vista previa, asegúrese de marcar la casilla incluir version preliminar en la ventana Agregar paquetes de Nuget.

2018-06-20_17-37-13

A continuación la lista confirmada de los APIs para su primer release:

Aprende más

Lea más sobre este lanzamiento en las notas de la versión completa y asegúrese de examinar nuestra documentación completa, que ofrece una descripción completa de cómo comenzar y cómo usar cada característica de Xamarin.Essentials.

Para mas información

 

Enjoy 🙂

Pruebas Unitarias – Parte 1

Hola, sean bienvenidos a una nueva sección, donde vamos a explicar un poco todo lo relacionado con este tema muy interesante de unit testing, a continuación en la primera entrega de videos de programación y buenas practicas.

Espero les sea de provecho y utilidad, esperen la segunda parte que ya esta en el horno, salu2…

Demo Kinect Comandos por voz en ESPAÑOL

En este post explicare sobre el uso de el arreglo de microfonos del Kinect con un ejemplo donde a travez de las librerias Microsoft Speech SDK y el SDK de KINECT podremos a travez de comandos de voz dar alguna instruccion al computador para mostrar algo en una aplicacion C# natural en WPF…

Se me ocurrio un ejemplo similar al que nos trae la SDK Toolkit de Kinect donde al hablar se muestra el espectro de voz de la persona que habla, pero en este caso, utilizare para explicarles sencillamente como ejemplo una aplicacion que al decir un color de los que muestre en la aplicacion esta sea capaz de identificarlo y de pintarlo en la aplicación, dando un rango de exito o de fracaso…

Pensaran que es algo complejo de analizar y de sintetizar la voz y esas cosas pero realmente no nos complicaremos la vida y por suerte ya existen herramientas a la mano para hacer estas cosas como

Bien para esto es necesario previamente tener el Microsoft Speech SDK en este caso la version mas actual que es la 11.0 que la podemos descargar en el siguiente enlace: Microsoft Speech SDK v11.0

Tambien necesitaremos de una libreria de idioma en nuestro caso Español que debemos de desacargar de la pagina Oficial de Kinect en nuestro caso ES-mx (Español-Mexico) o ES-es (Español-España): Kinect for Windows Language Packs v11.0

Una vez instalado estas, procedemos ahora a crear un nuevo proyecto WPF en C# en Visual Studio 2012 o 2010 como lo vayan preferiendo.

blogaudiokinet1

Una vez creada la solucion del proyecto nos vamos al archivo MainWindow.xaml donde escribiremos el siguiente codigo..


<Window x:Class="WpfAudioKinectPruebaHablar.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        
        Title="Kinect Audio Demo" Height="364" Width="680">
    <Grid Background="white">
        <TextBlock Text="KINECT Demo Audio Prueba" FontSize="36" HorizontalAlignment="Left" VerticalAlignment="Top" Margin="10,5,0,0" FontWeight="Light" />
        <StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" >
            <TextBlock x:Name="tbColor" Height="100" Width="500"/>            
            <TextBlock x:Name="tbInfo" Text="" Foreground="Black" Height="50" FontSize="20" TextAlignment="Center" Padding="0,10,0,0"/>
            <TextBlock x:Name="tbSpeech" Text="" Foreground="Black" Height="60" FontSize="16" TextAlignment="Left" Padding="0,10,0,10"/>
        </StackPanel>
        <TextBlock FontSize="16" HorizontalAlignment="Left" Margin="80,93,0,0" Text="diga algo para activar el reconocimiento" VerticalAlignment="Top" Width="379" FontWeight="Light" />
        
    </Grid>
</Window>

En el codigo aparecen tres TextBlock de nombre tbColor, tbInfo, tbSpeech estos son para mostrar una breve leyenda, el color procesado y el indice de acierto…

Antes de iniciar el codigo y la logica de la aplicacion debemos de agregar las referencias o DLLs que ya habiamos mencionado que son la Microsoft.Speech y Microsoft.Kinect

addreference

ahora bien, vamos con la parte mas interesante que es la de trabajar con las librerias de Microsoft Speech y por supuesto la libreria de KINECT sdk, procedemos a abrir el code-behind de MainWindow.xaml que es MainWindow.cs; donde ya abierto, agregamos la libreria Microsoft.Kinect, las siguientes Microsoft.Speech.AudioFormat y Microsoft.Speech.Recognition


using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;

siguiendo con el codigo creamos 5 variables de tipo SolidColorBrush y le di a cada una un color y creamos la variable kinect de tipo KinectSensor, un DispatcherTimer que le llame readyTimer y dos variables muy interesantes que vienen de la libreria Speech que son EnergyCalculatingPassThroughStream que es la variable que contendra el espectro de la energia y la forma de la voz sintetizada para a travez de la segunda variable que es la que crea una especie de gramatica dependiendo de la cultura y el enfasis de la voz la como se muestra en el siguiente codigo.


 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

“Suena dificil y complejo pero son solo sencillas primitivas para trabajar el reconocimiento de voz en nuestras aplicaciones”.. aca les dejo unas rutinas establecidas para el control de la voz, sintetizarla y despues tomarla en la variable para asi ahora poder trabajar con ella a travez del Kinect, por ahora solo les dejo el siguiente codigo:

 private class EnergyCalculatingPassThroughStream : Stream
 {
   private const int SamplesPerPixel = 10;

   private readonly double[] energy = new double[500];
   private readonly object syncRoot = new object();
   private readonly Stream baseStream;

   private int index;
   private int sampleCount;
   private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
   this.baseStream = stream;
 }

 public override long Length
 {
   get { return this.baseStream.Length; }
 }

 public override long Position
 {
   get { return this.baseStream.Position; }
   set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
   get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
   get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
   get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
   this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
   lock (this.syncRoot)
   {
     int energyIndex = this.index;
     for (int i = 0; i < this.energy.Length; i++)       {       energyBuffer[i] = this.energy[energyIndex];       energyIndex++;       if (energyIndex >= this.energy.Length)
     {
       energyIndex = 0;
     }
   }
  }
 }

  public override int Read(byte[] buffer, int offset, int count)
  {
    int retVal = this.baseStream.Read(buffer, offset, count);
    const double A = 0.3;
    lock (this.syncRoot)
    {
    for (int i = 0; i < retVal; i += 2)      {        short sample = BitConverter.ToInt16(buffer, i + offset);        this.avgSample += sample * sample;        this.sampleCount++;        if (this.sampleCount == SamplesPerPixel)        {          this.avgSample /= SamplesPerPixel;          this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2));          this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

        if (this.index > 0)
        {
          this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
        }

     this.index++;

     if (this.index >= this.energy.Length)
     {
       this.index = 0;
     }

       this.avgSample = 0;
       this.sampleCount = 0;
    }
   }
  }

  return retVal;
 }

  public override long Seek(long offset, SeekOrigin origin)
  {
    return this.baseStream.Seek(offset, origin);
  }

  public override void SetLength(long value)
  {
    this.baseStream.SetLength(value);
  }

  public override void Write(byte[] buffer, int offset, int count)
  {
    this.baseStream.Write(buffer, offset, count);
  }
 }

Y aca les dejo todo codigo fuente para poner a andar nuestro Kinect por voz y en español!…. despues les seguire mostrando detalladamente cada una de las funcionalidades de este demo para que lo apliquen a un sin fin de cosas.

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Threading;

using Microsoft.Kinect;

using Microsoft.Speech.AudioFormat;
using Microsoft.Speech.Recognition;
namespace WpfAudioKinectPruebaHablar
{
 ///
 /// Interaction logic for MainWindow.xaml
 ///
 public partial class MainWindow : Window
 {
 private readonly SolidColorBrush redBrush = new SolidColorBrush(Colors.Red);
 private readonly SolidColorBrush greenBrush = new SolidColorBrush(Colors.Green);
 private readonly SolidColorBrush yellowBrush = new SolidColorBrush(Colors.Yellow);
 private readonly SolidColorBrush blueBrush = new SolidColorBrush(Colors.Blue);
 private readonly SolidColorBrush WhiteBrush = new SolidColorBrush(Colors.White);

 KinectSensor kinect;

 private DispatcherTimer readyTimer;
 private EnergyCalculatingPassThroughStream stream;
 private SpeechRecognitionEngine speechRecognizer;

 #region class EnergyCalculatingPassThroughStream

 private class EnergyCalculatingPassThroughStream : Stream
 {
 private const int SamplesPerPixel = 10;

 private readonly double[] energy = new double[500];
 private readonly object syncRoot = new object();
 private readonly Stream baseStream;

 private int index;
 private int sampleCount;
 private double avgSample;

 public EnergyCalculatingPassThroughStream(Stream stream)
 {
 this.baseStream = stream;
 }

 public override long Length
 {
 get { return this.baseStream.Length; }
 }

 public override long Position
 {
 get { return this.baseStream.Position; }
 set { this.baseStream.Position = value; }
 }

 public override bool CanRead
 {
 get { return this.baseStream.CanRead; }
 }

 public override bool CanSeek
 {
 get { return this.baseStream.CanSeek; }
 }

 public override bool CanWrite
 {
 get { return this.baseStream.CanWrite; }
 }

 public override void Flush()
 {
 this.baseStream.Flush();
 }

 public void GetEnergy(double[] energyBuffer)
 {
 lock (this.syncRoot)
 {
 int energyIndex = this.index;
 for (int i = 0; i < this.energy.Length; i++) { energyBuffer[i] = this.energy[energyIndex]; energyIndex++; if (energyIndex >= this.energy.Length)
 {
 energyIndex = 0;
 }
 }
 }
 }

 public override int Read(byte[] buffer, int offset, int count)
 {
 int retVal = this.baseStream.Read(buffer, offset, count);
 const double A = 0.3;
 lock (this.syncRoot)
 {
 for (int i = 0; i < retVal; i += 2) { short sample = BitConverter.ToInt16(buffer, i + offset); this.avgSample += sample * sample; this.sampleCount++; if (this.sampleCount == SamplesPerPixel) { this.avgSample /= SamplesPerPixel; this.energy[this.index] = .2 + ((this.avgSample * 11) / (int.MaxValue / 2)); this.energy[this.index] = this.energy[this.index] > 10 ? 10 : this.energy[this.index];

 if (this.index > 0)
 {
 this.energy[this.index] = (this.energy[this.index] * A) + ((1 - A) * this.energy[this.index - 1]);
 }

 this.index++;

 if (this.index >= this.energy.Length)
 {
 this.index = 0;
 }

 this.avgSample = 0;
 this.sampleCount = 0;
 }
 }
 }

 return retVal;
 }

 public override long Seek(long offset, SeekOrigin origin)
 {
 return this.baseStream.Seek(offset, origin);
 }

 public override void SetLength(long value)
 {
 this.baseStream.SetLength(value);
 }

 public override void Write(byte[] buffer, int offset, int count)
 {
 this.baseStream.Write(buffer, offset, count);
 }
 }
 #endregion

public MainWindow()
{
 InitializeComponent();

 kinect = KinectSensor.KinectSensors[0];

 if (this.kinect != null)
 {
 this.InitializeKinect();
 }
}

 private void Start()
 {
 var audioSource = this.kinect.AudioSource;
 audioSource.BeamAngleMode = BeamAngleMode.Adaptive;

 audioSource.EchoCancellationMode = EchoCancellationMode.CancellationAndSuppression;
 var kinectStream = audioSource.Start();

 this.stream = new EnergyCalculatingPassThroughStream(kinectStream);
 this.speechRecognizer.SetInputToAudioStream(this.stream, new SpeechAudioFormatInfo
 (EncodingFormat.Pcm, 16000, 16, 1, 32000, 2, null));
 this.speechRecognizer.RecognizeAsync(RecognizeMode.Multiple);
 }

 private static RecognizerInfo GetKinectRecognizer()
 {
 Func<RecognizerInfo, bool> matchingFunc = r =>
 {
 string value;
 r.AdditionalInfo.TryGetValue("Kinect", out value);
 return "True".Equals(value, StringComparison.InvariantCultureIgnoreCase) &&
 "es-ES".Equals(r.Culture.Name,StringComparison.InvariantCultureIgnoreCase);
 };
 return SpeechRecognitionEngine.InstalledRecognizers().Where(matchingFunc).FirstOrDefault();
 }

 private SpeechRecognitionEngine CreateSpeechRecognizer()
 {
 RecognizerInfo ri = GetKinectRecognizer();
 if (ri == null)
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.",
 "Falla al cargar Speech SDK", MessageBoxButton.OK, MessageBoxImage.Error);

 this.Close();
 return null;
 }

 SpeechRecognitionEngine sre;
 try
 {
 sre = new SpeechRecognitionEngine(ri.Id);
 }
 catch
 {
 MessageBox.Show(@"Hay un problema al inicializar el dispositivo de reconocimiento de voz.
 asegurese de tener Microsoft Speech SDK instalado y configurado.", "Falla al cargar Speech SDK",
 MessageBoxButton.OK, MessageBoxImage.Error);
 this.Close();
 return null;
 }

 var colors = new Choices();
 colors.Add("rojo");
 colors.Add("verde");
 colors.Add("azul");
 colors.Add("amarillo");

 var gb = new GrammarBuilder { Culture = ri.Culture };
 gb.Append(colors);

 // Create the actual Grammar instance, and then load it into the speech recognizer.
 var g = new Grammar(gb);

 sre.LoadGrammar(g);
 sre.SpeechRecognized += this.SreSpeechRecognized;
 sre.SpeechHypothesized += this.SreSpeechHypothesized;
 sre.SpeechRecognitionRejected += this.SreSpeechRecognitionRejected;

 return sre;
 }

 private void RejectSpeech(RecognitionResult result)
 {
 string status = "Rechazado: " + (result == null ? string.Empty : result.Text + " " + result.Confidence);
 this.ReportSpeechStatus(status);

 Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = WhiteBrush; }), DispatcherPriority.Normal);
 }

 private void SreSpeechRecognitionRejected(object sender, SpeechRecognitionRejectedEventArgs e)
 {
 this.RejectSpeech(e.Result);
 }

 private void SreSpeechHypothesized(object sender, SpeechHypothesizedEventArgs e)
 {
 this.ReportSpeechStatus("Hipotetico: " + e.Result.Text + " " + e.Result.Confidence);
 }

 private void SreSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
 {
 SolidColorBrush brush;

 if (e.Result.Confidence < 0.7) { this.RejectSpeech(e.Result); return; } switch (e.Result.Text.ToUpperInvariant()) { case "ROJO": brush = this.redBrush; break; case "VERDE": brush = this.greenBrush; break; case "AZUL": brush = this.blueBrush; break; case "AMARILLO": brush = this.yellowBrush; break; default: brush = this.WhiteBrush; break; } string status = "Reconocido: " + e.Result.Text + " " + e.Result.Confidence; this.ReportSpeechStatus(status); Dispatcher.BeginInvoke(new Action(() => { tbColor.Background = brush; }), DispatcherPriority.Normal);
 }

 private void ReportSpeechStatus(string status)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbSpeech.Text = status; }), DispatcherPriority.Normal);
 }

 private void UpdateInstructionsText(string instructions)
 {
 Dispatcher.BeginInvoke(new Action(() => { tbInfo.Text = instructions; }), DispatcherPriority.Normal);
 }

 private void MainWindowClosing(object sender, System.ComponentModel.CancelEventArgs e)
 {
 this.UninitializeKinect();
 }

 private void ReadyTimerTick(object sender, EventArgs e)
 {
 this.Start();
 this.ReportSpeechStatus("Listo para reconocer voz!");
 this.UpdateInstructionsText("Diga: 'rojo', 'verde', 'amarillo' o 'azul'");
 this.readyTimer.Stop();
 this.readyTimer = null;
 }

 private void InitializeKinect()
 {
 var sensor = this.kinect;
 this.speechRecognizer = this.CreateSpeechRecognizer();
 try
 {
 sensor.Start();
 }
 catch (Exception)
 {

 }

 if (this.speechRecognizer != null && sensor != null)
 {
 // NOTE: Need to wait 4 seconds for device to be ready to stream audio right after initialization
 this.readyTimer = new DispatcherTimer();
 this.readyTimer.Tick += this.ReadyTimerTick;
 this.readyTimer.Interval = new TimeSpan(0, 0, 4);
 this.readyTimer.Start();

 this.ReportSpeechStatus("Inicializando el dispositivo de audio Kinect...");
 this.UpdateInstructionsText(string.Empty);

 this.Closing += this.MainWindowClosing;
 }
 }

 private void UninitializeKinect()
 {
 var sensor = this.kinect;

 if (this.speechRecognizer != null && sensor != null)
 {
 sensor.AudioSource.Stop();
 sensor.Stop();
 this.speechRecognizer.RecognizeAsyncCancel();
 this.speechRecognizer.RecognizeAsyncStop();
 }

 if (this.readyTimer != null)
 {
 this.readyTimer.Stop();
 this.readyTimer = null;
 }
 }

 }
}

nota: esta entrada esta sujeta a cambios por la actualizacion de la libreria KINECT, luego les seguire comentando acerca de esto, por ahora solo les adelanto este post!…

Tutorial: Cargar el Plug-In Silverlight en PHP

Microsoft Silverlight4 por ser un tecnología de gran poder para correr aplicaciones RIA (Rich Internet Applications) tanto del lado Cliente como Servidor, básicamente es una tecnología multiplataforma y multinavegador.

Actualmente Silverlight 4 puede ejecutarse en las plataformas Windows, Mac y Linux con el plug-in Moonlight con los navegadores web más populares como Internet Explorer, Mozilla Firefox, Google Chrome, Safari.

El ciclo de vida del plug-in Silverlight comienza con la apertura de una página web que albergan un plug-in de Silverlight valga la redundancia. Si Silverlight no está presente, entonces la página web, automáticamente le pide al usuario instalar el plug-in. Luego activa el navegador web y empezar a descargar el paquete de solicitud. Luego en los servicios de carga esta ejecuta el núcleo de Silverlight o el (Silverlight core), seguido de CLR (Common Language Runtime) que no es más que el framework .NET en el cual la aplicación de tipo Silverlight toma y crea un dominio de aplicación para su aplicación. Después de descargar el paquete de aplicaciones CLR crea un objeto de clase de aplicación en la que se cargan las UI principales que vienen definidas en clases Heredadas del CLR y el Core de Silverlight para tener la aplicación base de ejecución Silverlight.

Como único requisito para correr aplicaciones de tipo Silverlight basta solo con descargar el Plug-in en el navegador y este podrá ejecutarse en el navegador web (similar al plug-in Adobe Flash, pero ya este es otro mundo, sigamos con Silverlight).

Silverlight viene preestablecido para iniciar en páginas de tipo ASP.NET en Visual Studio 2010 pero en este caso para los desarrolladores de PHP para poder trabajar cómodamente en Silverlight puesto que por ser un plug-in este debe de ser cargado en una página HTML a través de en los que podemos invocar al XAP de silverlight (es como el SWF de Flash que debemos cargar para poder ver las películas o animaciones).

Ahora bien básicamente en este tutorial cargaremos una aplicación de tipo Silverlight en una página PHP en la que pueda ver claramente un botón y con este al hacer click me muestre un mensaje en la aplicación,

Nota: no voy a especificar lenguaje XAML por lo que más adelante en futuras entregas si lo explicare más a fondo y a detalle, pero en este caso lo fundamental es ver como corre el plug-in de Silverlight y como invoco mi aplicación en una página PHP.

Para empezar creo mi aplicación Silverlight colocando un botón y una etiqueta oculta, a través del evento OnClick del Botón creado le asigno la cadena de texto a la etiqueta colocando “Hello PHP Developers” compilo mi aplicación y en la carpeta del proyecto se crea un archivo de tipo XAP llamado “HelloPHPdevelopers.xap” lo copio y lo pego a la carpeta donde vaya a correr mi pagina en PHP, en mi caso en la carpeta WWW del servidor Apache donde coloque ejemplo.



Luego de tener nuestro XAP en el servidor abrimos nuestra pagina PHP, en este caso Default.php en cualquier editor PHP o Web que soporte este tipo de tecnología web por ejemplo (Adobe DreamWeaver, Bluefish, Eclipse, Notepad++) y encontramos el siguiente código HTML:


<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN” “http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”&gt;

<html xmlns=”http://www.w3.org/1999/xhtml”&gt;

<head>

<meta content=”text/html; charset=utf-8″ http-equiv=”Content-Type” />

</head>

<body>

<?php echo “Hello PHP Developers” ?>

<br/><br/>

</body>

</html>

Ahora bien dentro dentro del tag <body> y </body> procederemos a invocar el XAP de la siguiente forma con el tag <object>


Donde el invocamos que es un “data:application/x-silverlight“ de tipo “application/x-silverlight-2” (noten que al final del nombre de tipo de aplicación dice x-silverlight-2: no quiere decir que sea conforme con la versión 2 de Silverlight, sino que es solo el nombre del tipo de aplicación puesto que esto tiende a confundir al desarrollador), también definimos el ancho y alto ( por defecto estos valores vienen en 100% respectivamente inicialmente para que el plug-in ocupe todo el espacio de la pagina pero vamos a darle un valor de tamaño 640 x 480 respectivamente).

Luego definimos los parámetros necesarios para que la aplicación corra según nuestro criterio y necesidad en el que la regla es <param(tag) seguido por el nombre del parámetro name=”nombre del parámetro” y el valor Value=”valor del nombre del parametro” />para ello necesitamos especificar el nombre del XAP con esta línea

<param name=”source” value=”HelloPHPdevelopers.xap”/>

donde colocamos el nombre del archivo que colocamos en la carpeta de prueba del servidor anteriormente citado, también necesitamos darle atributos de inicialización como el color de fondo, aunque por defecto viene en color Blanco vamos dejarlo así pero el desarrollador es libre de elegir el color en el cual el fondo se puede mostrar, el siguiente parámetro es de definición de versión del Runtime de Silverlight que ejecuta actualmente el plugin en el navegador, con estas líneas

<param name=”autoUpgrade” value=”true” />

<a href=”http://go.microsoft.com/fwlink/?LinkID=124807&#8243; style=”text-decoration: none;”>

<img src=”http://go.microsoft.com/fwlink/?LinkId=108181&#8243; alt=”Get Microsoft Silverlight” style=”border-style: none”/>

La primera es para establecer si el plug-in nos permite auto actualizar el Runtime, las otras líneas es la ruta en la cual está establecida la última versión del runtime de Microsoft silverlight, dependiendo si está instalada o no en el navegador o si necesita aplicar una actualización, dicho esto es necesario para que automáticamente al liberar una nueva versión del Runtime de Silverlight requiera una actualización este plug-in automáticamente muestra al usuario que hay una actualización y que debe de instalar y reemplazar la versión anterior.

Al explicar los parámetros básicos de invocación del plug-in para mostrar en nuestra página PHP, ya podemos contar con la tecnología Silverlight en nuestras páginas PHP.

Abrimos el navegador web, en este caso con Firefox escribimos la siguiente dirección URL

Http://127.0.0.1/nombredelacarpetaenelservidor/nombredelarchivo.php





Una vez cargado el XAP en la pagina PHP ya podemos interactuar con la aplicación Silverlight“Hello PHP Developers” en nuestra página que al hacer click en el botón coloque visible la etiqueta que muestra

Vemos así la interoperabilidad entre varias tecnologías de programación, hasta involucrando la plataforma .Net en aplicaciones web ya sean soportadas en PHP bajo esta nueva tecnología que está marcando mucha tendencia a lo que son las aplicaciones RIA en la web.

Espero les sirva de gran ayuda el conocimiento e implementación del Plug-in para que las aplicaciones Silverlight puedan correr en cualquier tecnología web de libre elección para el desarrollador, próximamente estare explicando a fondo los fundamentos del lenguaje XAML para diseñar y crear aplicaciones Silverlight.

Salu2 😀