Twitter Facebook RSS Feed

domingo, 04 de enero de 2009 a las 20:26hs por Gustavo Cantero (The Wolf)

Ejecutar JavaScript desde Silverlight

Al desarrollar con Silverlight muchas veces necesitamos que nuestro control interactúe con el resto de la página, por ejemplo, con un botón de HTML o con un DIV, colocando dentro algún texto. Para poder lograr esto el framework de .NET que posee el Silverlight nos ofrece la clase HtmlPage, la cual se encuentra en el namespace System.Windows.Browser. Esta clase posee varias propiedades y métodos estáticos para interactuar con el navegador del cliente, por ejemplo, la propiedad BrowserInformation nos brinda información del navegador, pudiendo saber su versión a través de la siguiente propiedad: HtmlPage.BrowserInformation.BrowserVersion, o la plataforma sobre la cual está corriendo con esta otra: HtmlPage.BrowserInformation.Platform.
Para poder interactuar con la página que contiene a nuestro control en el cliente podemos utilizar la propiedad HtmlPage.Window, la cual posee una instancia del objeto window del navegador, pudiendo, por ejemplo, crear un “alert” con la siguiente línea:

HtmlPage.Window.Alert("Hola mundo!");

crear un diálogo de confirmación con esta otra:

bool bolOK = HtmlPage.Window.Confirm("¿Está seguro de hacer eso?");

o simplemente navegar a otra página:

HtmlPage.Window.Navigate("http://www.silverlight.net");

Pero si lo que necesitamos es llamar a una función creada en JavaScript, podemos utilizar el método Invoke, el cual toma como primer parámetro el nombre de la función a ejecutar, y los subsiguientes parámetros se los pasa a la función. El valor devuelto por el método es el retornado por la función ejecutada (si es que devuelve algún valor). Como ejemplo vamos a ejecutar la llamada a la función “alert” pero a través del método invoke:

HtmlPage.Window.Invoke("alert", "Hola mundo!");

Cabe mencionar que para que nuestra aplicación pueda interactuar con la página necesitamos agregar el parámetro HtmlAccess="Enabled" en la creación del objeto de Silverlight.

Ejecutar métodos de Silverlight desde JavaScript

También puede darse el caso que necesitemos llamar a algún método de nuestro control al ejecutarse algún evento de la página, por ejemplo, al pulsarse un botón de HTML, para lo cual necesitamos registrar nuestro objeto para que pueda ser accedido a través de JavaScript y el método (o todos los miembros) de la clase también como accesibles.
Comencemos por el primer paso: para registrar nuestro objeto, por ejemplo, el control, simplemente necesitamos ejecutar el método RegisterScriptableObject, pasándole como primer parámetro el nombre de la propiedad de JavaScript a través de la cual será accedido, y como segundo parámetro la instancia del mismo, por ejemplo:

HtmlPage.RegisterScriptableObject("Page", this);

El siguiente paso es registrar a la clase completa para que pueda ser accedida a través de JavaScript con el atributo ScriptableType, o registrar sólo los métodos que se necesitan usar, a través del atributo ScriptableMember.
A continuación muestro como ejemplo una aplicación Silverlight que posee marcado como accesible desde JavaScript un método que cambia el texto un botón del mismo.

public partial class Page : UserControl
{
    public Page()
    {
        InitializeComponent();
        HtmlPage.RegisterScriptableObject("Page", this);
    }
    [ScriptableMember]
    public void ChangeButtonText(string Text)
    {
        TextBlock objTB = new TextBlock();
        objTB.Text = Text;
        Button1.Content = objTB;
    }
}

Y la página que utiliza este método:

<body style="height: 100%; margin: 0; background-color: Blue">
    <form id="form1" runat="server">
    <asp:scriptmanager ID="ScriptManager1" runat="server"></asp:scriptmanager>
    <input type="button" onclick="$get('Xaml1').Content.Page.ChangeButtonText('Html')"
        value="Prueba" />
    <div>
        <asp:silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication5.xap"
MinimumVersion="2.0.31005.0" Width="500" Height="300" Windowless="true" HtmlAccess="Enabled"></asp:silverlight>
    </div>
    </form>
</body>

Por último, dejo un ejemplo creado con Visual Studio® 2008 donde se muestra un botón en una aplicación de Silverlight que cambia el texto de un botón de HTML, y un botón de HTML que cambia el texto de un botón de Silverlight.
Proyecto de ejemplo de llamadas entre JavaScript y Silverlight
Espero que este artículo les sea de utilidad.

18 comentarios »

  1. Alex dice:

    HOLA A TODOS, necesito de su ayuda, como hago para llamar a una pagina de Silverlight desde Silverlight, y como hago para vincular silverlight a una pagina de asp.net, es decir en lugar de usar CSS para maquillarla usar Silverlight para ello, saludos desde Ecuador.

  2. Dario Krapp dice:

    Hola Alex,
    Te voy comentando por pregunta, la primera es sobre la vinculación de un control Silverlight a una página ASP.NET, si ya posees un control Silverlight terminado, por ejemplo un control hecho por terceros o uno hecho por vos ya testeado y funcionando por completo (como un archivo .xap), lo que debes hacer es copiarlo en la carpeta bin o si lo deseas en alguna subcarpeta dentro
    de la carpeta bin y luego en la pagina .aspx crear un elemento Silverlight y hacerle referencia en el atributo Source, por ejemplo

    <asp:Silverlight ID=»Xaml1″ runat=»server» Source=»~/ListTree.xap»
    MinimumVersion=»2.0.31005.0″ Width=»100%» Height=»100%» />

    Si no posees un control ya terminado, o sea que estás creando un control Silverlight, Visual Studio (2008) puede ayudarte automatizando las tareas de prueba del control, podés agregar en la solución del projecto Silverlight un proyecto ASP.NET convencional desde las propiedades del proyecto ASP.NET, en la solapa «Silverlight Applications» (Versión en inglés del VS) podrás incluir el proyecto Silverlight que estás creando presionando el botón «Add»,Visual Studio te permitirá crear una página .aspx (también te incluirá una pagina html) de pruebas con el control ya embebido y ajustará a la solución para que compile, genere el .xap y lo copie a la carpeta bin automáticamente ahorrandote mucho tiempo.

    Para conectar dos controles Silverlight dentro de una misma página, supongamos que desde el control Sil1 deseas enviarle una cadena de texto al control Sil2, ambos embebidos en una página .aspx, hay tres pasos que debes seguir;
    Hacer que el control Sil1 exporte información, Hacer que el control Sil2 importe información y hacer el puente entre ambos.

    Para el primer paso deberás hacer que el control Sil1 exporte información, esto en el mundo práctico es hacer que Sil1 llame una función JavaScript en la página .aspx, para hacer eso simplemente deberás invocar a la función JavaScript de la siguiente forma

    HtmlPage.Window.Invoke(«miJSFunc», «Cadena enviada desde Sil1!»);

    Luego debes hacer que el control Sil2 importe información, la idea es que Sil2 posea métodos invocables desde JavaScript para recibir información y esto se hace incluyendo el atributo «ScriptableMember» en el método de Sil2 que será invocado

    [ScriptableMember]
    public void RecibirTexto(string Text)
    {

    Además deberás registrar el control como scriptable, simplemente agregando

    HtmlPage.RegisterScriptableObject(«Page», this); en el constructor del control Sil2

    Finalmente deberás crear el puente entre ambos como una función javascript en la página .aspx que contiene ambos controles

    function miJSFunc(texto) {
    var Objs1 = $find(«Sil2»);
    var Elems1 = Objs1.get_element();
    Elems1.Content.Page.RecibirTexto(texto);
    }

    Con esos pasos deberías poder conectar ambos controles, esto es solo un ejemplo mínimo, en un caso real podrías sofisticar un poco este esquema y hacer que el control Sil1 escriba el javascript en la pagina, deberías emplear el clientID de ASP.NET en el $find (<%= Sil2.ClientID ) y no usar el nombre directamente ya que el nombre del control (Sil2) puede variar en ciertos escenarios, por ejemplo si el control se encuentra dentro de panels.
    También podrías necesitar enviar información compleja entre los controles, dejo esas posibilidades a tu creatividad y espero que esta información te haya resultado útil.

  3. Alex dice:

    hola y gracias por ser atento a mi pedido, sabes se me olvido decirte q entiendo algo en VB y no C#, tu explicacion es buena pero no la entiendo en c#, me la podrias decir en VB por favor, y perdona la molestia, para no enredarme respondeme a esta pregunta, «Como hago para llamar a una pagina de silverlight desde silverlight» es que necesito aprender, de nuevo gracias, estoy atento a tu respuesta.

  4. Alex dice:

    Dario, me explico mejor, yo cree una aplicacion de asp.net y luego agrege una nueva aplicacion en este caso de silverlight (en el proyecto tengo 2 aplicaciones asp y silverlight), agrege un tex un password dos etiquetas y un boton en la pagina de silverlight en donde en el boton hay un evento clic que le agrege para q al dar clic me valide la entrada a sql2005, si existe el usuario me de paso al sistema que quiero desarrollar en asp.net entre lo q voy a desarrollar esta el control de bodegas, ese es solo un modulo, seran mas con el tiempo,estoy intentando usar linq para trabajar con los datos, ahora ¿..cómo llamo al dar clic en el boton a la pagina de asp….??? (estoy dando un inicio de sesion), claro y de ahi seguira a donde tiene que segir en asp… el diseño de la pagina en silverlight lo he trabajado en blend 2 sp1 ojo no soy experto recien estoy intentando crear mi apliccion desde cero, tanto en blend, como en silverlight. disculpa por no haberme explicado mejor antes, creo q ahora esta mas clara la pelicula, … como llamo a una pagina de asp desde el boton de silverlight, te seguire molestando amigo…
    salu2

  5. Dario Krapp dice:

    Alex,
    Entiendo el problema, el tema es que en estos casos se está empleando un enfoque diferente, en lugar pasar la información a la pagina .aspx desde Silverlight para que la misma envíe los datos
    al servidor en un postback, es más frecuente hacer que el control Silverlight se comunique directamente con el servidor através de servicios web, esta modalidad es el que se está empleando mayormente para el acceso a datos desde Silverlight.
    Entonces, me parece que lo que podrías hacer es crear un servicio web que se encargue de autenticar al usuario e invocarlo desde el control Silverlight, luego a la vuelta de la llamada del servicio web (que es una llamada asincrónica) en base a la respuesta podrías redireccionar desde Silverlight
    a la página correspondiente, recuerda que además de validar al usuario en el servicio web deberás verificar en cada página si el mismo se encuentra autenticado, para que no ingresen a paginas que requieren autenticación escribiendo la url en browser. Para hacer esto podrías emplear el enfoque de Forms Authentication y Membership que es provisto por asp.net y te ahorrará algo de tiempo si ya lo conoces.
    Otra opción es utilizar variables de sesión, aunque vas a tener que verificar manualmente la autenticación en ese caso.
    Espero que esta respuesta te haya ayudado y saludos.

  6. Alex dice:

    ok, gracias, claro q me has ayudado, pero aun no me has dicho como llamo a una pagina desde silverlight, explicamelo con codigo incluido (en VB) por favor.
    salu2

  7. Saludos Dario, tengo una pregunta y va por el mismo camino de alex con la diferencia que ya cree ciertas partes de mi aplicacion, lo unico que me detiene es el famoso paso de una pagina de silverlight a otra de la misma catergoria, te explico:

    Logro Autenticar a mis usuarios y validar que existan en la base de datos, despues de ello, requiero automaticamente invocar o llamar a mi segunda pagina Silverlight de mi solucion…

    Es Decir desde mi MainPage.xaml -> Autenticacion -> SecondPage.xaml.

    La Pregunta de los Mil Dolares, no se como hacerlo automaticamente.

    Si Pudieras Ayudarme seria de mucha ayuda… Muchisimas Gracias… Excelente Blog.

    Codigo de Revision de Datos de Autenticacion:

    if (r.Result.Count != 1)
    MessageBox.Show(«Clave o Usuario Incorrecto, Verifique Por Favor»);
    else

    y alli me quedo… Gracias Amigo.

    • Jesus:
      Yo creo que lo mejor sería que desde la primer página de Silverlight llamaras a un servicio web que autentique al usuario (el Membership de ASP.NET tiene ya creado un servicio web para esto), y luego actualices tu página de Silverlight.
      Si no quieres usar los servicios web del Membership puedes autenticarlo contra tu base de datos y luego hacer lo siguiente (del lado del servidor, en un servicio web): System.Web.Security.FormsAuthentication.SetAuthCookie(NombreDelUsuario, false);. Esto va a generar una cookie del lado del cliente para saber que está autenticado. Luego, cada vez que quieras saber si el usuario está logeado, puedes usar un código como este: System.Web.HttpContext.Current.User.Identity.IsAuthenticated, y esta linea para saber el nombre del usuario: System.Web.HttpContext.Current.User.Identity.Name. Obviamente tu control Silverlight deberá comunicarse con servicios web para saber si el usuario está autenticado o no.
      Cualquier consulta no dudes en avisar.
      Saludos.

  8. Gustavo, Gracias por Responder, cambiare esa parte según tu respuesta, pero aun quedo en la duda de como invocar una nueva pagina desde mi pagina Principal despues de autenticar, si me facilitas una direccion de correo, podria enviarte mi proyecto para que lo evalues y veas que tan bien esta y que cosas podria mejorar, ya que en verdad me urge despues de autenticar a mi usuario ir a la nueva pagina Silverlight, del resto Muy agradecido por sus atenciones prestadas.

    Jesus Castrillo
    P2P Analisis.

  9. Imaz dice:

    Buenas.
    Me gustaria preguntar en relacion a este tema, una cosita.
    System.Windows.Browser.HtmlPage.Window.Navigate(Dirección) esto usas para «ir» a otra pagina, pero si quisieramos abrir un webform dentro de un Grid del xaml, como podriamos hacerlo? Tengo un menu, tanto en la parte superior como en un lateral(todo en silverlight) y me gustaria que al pinchar un item del menu, se me abriera en la misma pantalla un web form. Es esto posible?
    Gracias po la ayuda

    • Imaz: No puedes abrir una página html dentro de Silverlight, pero puedes crear un IFRAME «sobre» el silverlght y navegar ahí tus páginas. Una buena implementación para hacer esto de manera más sencilla es el control HtmlHost de divelements, donde podrias crear un IFRAME y hacer que ahí dentro se carguen tus páginas.
      Suerte!

  10. Imaz dice:

    Hola Gustavo, Gracias por el aporte. Creo que el iFrame es lo que busco. Pero estoy trabajando con controles telerik y no se si es que no me entero(soy nuevo en esto del silverlight) o es que estoy haciendo algo mal.uso el iframe.Navigate y me dice que la ruta no es correcta, quehe de usar una ruta rekativa, pero no doy con ella.Tengo en una misma solucion dos `proyectos, uno de silverlight y el de vb.como pongo la ruta para que de la parte silverlight me muestre un aspx de la parte de vb?.Muchas gracias por la ayuda y espero no molestar. Un saludo

    • Imaz:
      Para hacer que desde Silverlight navegue una página en un IFRAME deberías crearlo en el HTML con un nombre, por ejemplo:

      <IFRAME name="NombreDelIFrame"></IFRAME>

      y luego, desde Silverlight, invocar la siguiente linea (obviamente cambiando la URL a navegar):

      System.Windows.Browser.HtmlPage.Window.Navigate("http://www.scientia.com.ar", "NombreDelIFrame");

      Si con esto aún no te funciona tu proyecto te invitio a nuestro foro (http://foro.scientia.com.ar) donde podrás ingresar tu consulta y, si puedes, subir la parte de tu proyecto que no funciona, para que podamos mirarlo y ayudarte.
      Saludos.

  11. Imaz dice:

    Hola de nuevo,
    Pensaras que soy un pesado, pero si lo que deseo es mostrarlo directamente en el codigo xaml?
    Es decir que dentro de MainPage.xaml se muestre la pagina aspx.
    Es eso posible? gracias

  12. Imaz dice:

    Muchisimas gracias.Ya lo solucione,gracias al HtmlHost.Estoy real,mente agradecido.Mil gracias

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.