piątek, 24 października 2008

Komunikacja pomiędzy Silverlight-em 2.0, a kodem javascript

W poprzednim artykule poświeconym połączeniom pomiędzy Silverlight-em, a kodem HTML (link), pokazałem jak w prosty sposób wskazać elementy strony html z poziomu aplikacji Silverlight i je użyć. Dowiedzieliśmy się także, w jaki sposób podpiąć Silverlight-a pod zdarzenia z kodu html. Całość zaowocowała nam "grą" w Ping Ponga :)

W tym artykule, chciałem krótko pokazać w jaki sposób możemy wywołać metody aplikacji Silverlight-a z kodu javascript i na odwrót, czyli metody javascript z kodu aplikacji Silverlight. Funkcjonalność ta okazuje się bardzo przydatna, szczególnie przy pracy z Virtual Earthem, Google Maps, obiektami JSONowymi i innymi aplikacjami/skryptami stworzonymi w javascript-cie.

Agenda

  1. Odwołanie do metody w javascript-cie z Silverlight-a
  2. Odwołanie do kodu aplikacji Silverlight, z javascript-u
  3. Obsługa event-ów wywołanych w Silverlight-cie, w kodzie javascript
  4. Przykładowy działający kod

Odwołanie do metody w javascript-cie z Silverlight-a

W pliku cs (np. Page.cs) dodajemy import Browser-a:

using System.Windows.Browser;

a w pliku javascript (np. Test.js), utworzonym przez nas w projekcie, dodajemy metodę

function testMethod(nothing) {
window.alert("[javascript] hello from javascript!");
}

i wywołujemy ją z kodu Silverlight-a (Page.cs):

Object[] args = null;
Object result = HtmlPage.Window.Invoke("testMethod", args);

, parametr args jest opcjonalny, tak samo jak wartość zwracana - result.

Plik Test.js musi być podłączony do strony html/aspx, która zawiera aplikacje Silverlight

<script type="text/javascript" src="Test.js"></script>

Alternatywnie, metoda testMethod może znajdować się bezpośrednio w pliku html/aspx, za pośrednictwem znaczników

<script type="text/javascript"> ... </script>

Odwołanie do kodu aplikacji Silverlight, z javascript-u

W celu odwołania się do Silverlight-a, musimy oznaczyć nasze zmienne, klasy, properties-y i eventy specjalnymi znacznikami ([ScriptableType], [ScriptableMember]). Dlatego też, klasa do której będziemy mogli się odwołać z javascript-u, będzie miała ten atrybut

[ScriptableType]
public class ScriptableClass
{
}

, natomiast jej zmienne i metody muszą mieć znaczniki ScriptableMember, np.:

[ScriptableType]
public class ScriptableClass
{
[ScriptableMember]
public string ScriptableMethod(string value){…}

[ScriptableMember]
public string val
{
get { return _val; }
set { _val = value; }
}
}

Następnie klasa musi zostać zarejestrowana na stronie html, poprzez wywołanie (np. w pliku Page.cs):

ScriptableClass scriptableClass;
scriptableClass = new ScriptableClass();
HtmlPage.RegisterScriptableObject("ScriptableClass", scriptableClass);

Na końcu, aby odwołać się do obiektu scriptableClass i jego metod/zmiennych w kodzie javascript, piszemy (w pliku Test.js):

var control = document.getElementById("Xaml1");
result = control.Content.ScriptableClass.scriptableMethod("Hello from javascript");

, a więc odnajdujemy kontrolkę Silverlight-a po jej id na stronie html/aspx (tu ta wartość może się u Was różnić jeśli modyfikowaliście kod html/aspx, w moim wypadku jest to "Xaml1") i wskazujcie zarejestrowany obiekt (ScriptableClass) i wywołujecie na nim metody (np. scriptableMethod(..)).

<div style="height: 100%;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
</div>

Mamy już wszystko co trzeba. Po wywołaniu metody scriptableMethod() z klasy ScriptableClass w kodzie javascript, wykona się metoda w kodzie Silverlight-a.

Obsługa event-ów wywołanych w Silverlight-cie w kodzie javascript

Aby event mógł być obsłużony, należy utworzyć EventHandler (np. public event EventHandler SilverHandler) w aplikacji (ScriptableClass.cs)

[ScriptableType]
public class ScriptableClass
{
[ScriptableMember]
public event EventHandler SilverEvent;

public virtual void OnEvent(ScriptableEventArgs e)
{
if (null != SilverEvent)
{
SilverEvent(this, e);
}
e.val.ToString(); //value from javascript
}
}

Dodaliśmy także metodę OnEvent do ScriptableClass, która wywoła event SilverEvent. Teraz potrzebujemy metody która wywoła OnEvent (Page.cs):

ScriptableClass scriptableClass;

private void Button_Click_1(object sender, RoutedEventArgs e)
{
ScriptableEventArgs sea = new ScriptableEventArgs();
sea.val = "Event Args from Silverlight";

scriptableClass.OnEvent(sea);
}

Jak widać, pojawiła się dodatkowo klasa ScriptableEventArgs. Klasa ta, to nadpisana własna klasa EventArgs-ów. Musimy ją nadpisać, ponieważ potrzebujemy EventArgs-ów które są także typu [ScriptableType] ( ScriptableEventArgs.cs.)

[ScriptableType]
public class ScriptableEventArgs : EventArgs
{
private string _val;

[ScriptableMember]
public string val
{
get { return _val; }
set { _val = value; }
}
}

A więc mamy event (SilverEvent), mamy klasę argumentów (ScriptableEventArgs) oraz metodę która wywoła event. To co potrzebujemy, to obsługi eventa po stronie javascript (Test.js)

function loadedd(cos) {
var control = document.getElementById("Xaml1");
control.Content.ScriptableClass.SilverEvent = eventfunction;
}

function eventfunction(sender, args) {
value = args.val;
window.alert("[javascript] " + value);
args.val = "javascript values"; //return string
}

I tak, metoda eventfunction zostanie wywołana w momencie wciśnięcia przycisku w aplikacji Silverlight (Button_Click_1), ponieważ została przypisana do eventa SilverEvent. Przypisanie robimy podobnie jak dla wywołania metod z obiektu ScriptableClass, tylko tym razem przypisujemy metodę pod event.

control.Content.ScriptableClass.SilverEvent = eventfunction;

Ponieważ przypisanie może zostać wykonane dopiero po inicjalizacji aplikacji Silverlight, dlatego też w/w przypisanie eventa zostało zamknięte w metodę, którą ja wywołuje dopiero z metody Page_Loaded

public Page()
{
InitializeComponent();

this.Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke("loadedd");
}

W ten sposób mam pewność, że event SilverEvent zostanie prawidłowo przypisany.

Przykładowy działający kod

Dla celów tego artykułu, stworzyłem demo aplikacji, która zapewnia prostą komunikację pomiędzy Silverlightem i javascriptem. W aplikacji mamy trzy przyciski:

  • "Call javascript" – wywoła metodę w kodzie javascript (Test.js) z aplikacji Silverlight
  • "Call Silverlight" – wywoła metodę javascritp, która wywoła metodę w aplikacji Silverlight
  • "Call javascript event" – zostanie wywołany event (SilverEvent) w obiekcie ScriptableClass. Event zostanie przekazany i obsłużony w kodzie javascript. Kod javascript zwróci rezultaty poprzez użycie wartości w klasie ScriptableEventArgs

Plik Page.xaml:

<UserControl x:Class="SilverlightApplication1.Page"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="400" Height="300">
<Canvas x:Name="LayoutRoot" Background="White">
<Button Content="Call javascript" Click="Button_Click" Canvas.Left="100" Canvas.Top="50" />
<Button Content="Call javascript event" Click="Button_Click_1" Canvas.Left="100" Canvas.Top="100" />
</Canvas>
</UserControl>

Plik SilverlightApplicationTestPage.aspx

<%@ Page Language="C#" AutoEventWireup="true" %><%@ Register
Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
TagPrefix="asp" %>
<!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" style="height: 100%;">
<head runat="server">
<title>SilverlightApplication1</title>

<script type="text/javascript" src="Test.js"></script>

</head>
<body style="height: 100%; margin: 0;">
<form name="CallButtons" action="" method="GET">

<input type="button" name="button" value="Call Silverlight" onclick="testScriptableClassMethod()">

</form>
<br />
<form id="form1" runat="server" style="height: 100%;">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div style="height: 100%;">

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap"
MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />

</div>
</form>
</body>
</html>

Plik Page.cs

public partial class Page : UserControl
{
ScriptableClass scriptableClass;
public Page()
{
InitializeComponent();
scriptableClass = new ScriptableClass("Hello from Silverlight");
HtmlPage.RegisterScriptableObject("ScriptableClass", scriptableClass);

this.Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
HtmlPage.Window.Invoke("loadedd");
}

private void Button_Click(object sender, RoutedEventArgs e)
{
Object[] args = null;
Object result = HtmlPage.Window.Invoke("testMethod", args);
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
ScriptableEventArgs sea = new ScriptableEventArgs();
sea.val = "Event Args from Silverlight";
scriptableClass.OnEvent(sea);
}
}

Plik ScriptableClass.cs

[ScriptableType]
public class ScriptableClass
{
private string value;

[ScriptableMember]
public event EventHandler SilverEvent;

public ScriptableClass(string val)
{
value = val;
}

[ScriptableMember]
public string scriptableMethod(string val)
{
string temp = value;
value = val;
return temp;
}

public virtual void OnEvent(ScriptableEventArgs e)
{
if (null != SilverEvent)
{
SilverEvent(this, e);
}
e.val.ToString(); //value from javascript
}
}

Plik ScriptableEventArgs.cs

[ScriptableType]
public class ScriptableEventArgs : EventArgs
{
private string _val;

[ScriptableMember]
public string val
{
get { return _val; }
set { _val = value; }
}
}

Plik Test.js

function testMethod(nothing) {
window.alert("[javascript] hello from javascript!");
}


function testScriptableClassMethod() {
var control = document.getElementById("Xaml1");
result = control.Content.ScriptableClass.scriptableMethod("Hello from javascript");

window.alert("[javascript] " + result);
}

function eventfunction(sender, args) {
value = args.val;
window.alert("[javascript] " + value);
args.val = "javascript values";
}

function loadedd(cos) {
var control = document.getElementById("Xaml1");

control.Content.ScriptableClass.SilverEvent = eventfunction;
}

Pełny kod dema znajdziecie tu -> link

Resources


Pozdrawiam,
JAcek Ciereszko

wtorek, 14 października 2008

Silverlight 2 released!!!

No i stało się, pojawił się długo oczekiwany Silverlight 2.0 w wersji RTW!!! Ma być dostępny do ściągnięcie już dziś pod adresem http://silverlight.net/GetStarted, (w chwili pisania tego postu jest dopiero kilka minut po północy ;P ).

Nowy Silverlight 2.0 RTW, w stosunku do wersji Beta 2 ma wprowadzić kilka nowych poprawek na błędy, kilka kontrolek + skiny i tyle, nie spodziewałbym się zbyt wielu zmian (więcej informacji znajdziecie w porównaniu wersji Beta 2 z wersją 2.0 RTW - link). Natomiast to co może szokować, to informację o tym, że wraz z wydaniem Silverlight 2.0, pojawi się plug-in do Eclipse-a, który obsłuży tworzenie aplikacji przy użyciu tego IDE - http:/www.eclipse4sl.org/ :)

Jak to zadziała, tak jak widać na screenach na oficjalnej stronie projektu (link), to przesiadam się na Eclipse-a, na stałe! :D

I jako ostatnie, warto dodać, że Microsoft zapowiedział wypuszczenie także zbioru darmowych templatek (Silverlight Control Pack) oraz specyfikacji dla Silverlight's Extensible Application Markup Language (XAML). Wszystko w ramach darmowej licencji Microsoft Permissive License i zgodnie z obietnicą o otwartych "źródłach" (Microsoft's Open Specification Promise). W ten oto sposób, użytkownicy darmowego Visual Web Developer 2008 Express Edition będą mogli także tworzyć aplikację w Silverlight-cie 2.0!!!

Resources

  • Blog Jesse Liberty-iego (link)
  • www.blogs.zdnet.com (link)


Lecę spać, może rano już będą źródła :)

Pozdro,

JAcek C.

sobota, 11 października 2008

Podsumowanie Bloggers Underground i zdjęcia

7 października odbyła się wspaniała impreza, o której pisałem poprzednio (link), a mianowicie Bloggers Underground. O godzinie 19:00 w klubie Leżaki na warszawskiej starówce, zebrali się najlepsi blogerzy z Polski - wyjadacze wieczornego kodowania i dzielenia się zebraną wiedzą. Na imprezie tej, miałem okazję być także ja, choć wiedzą i doświadczeniem nie dorównuje żadnemu z nich :)

Cel spotkania

Celem tego zacnego spotkania były poprostu plotki oraz możliwość zobaczenie i poznania ludzi, których artykuły czyta się na co dzień. W trakcie spotkania każdy z uczestników miał możliwość przedstawienia się oraz zaprezentowania ciekawej opowieści związanej z blogowaniem.

Plan Spotkania

Na początku było zapoznanie, które bardziej przypominało spotkanie AA ("cześć, jestem Jacek, piszę od 10 miesięcy i nie mogę przestać) ale ta część okazała się bardzo wesoła i bardzo rozruszała towarzystwo (szczególnie 13-nastki). Każdemu można było się przyjrzeć dokładnie i skojarzyć z blogiem który prowadzi :)

Następnie rozpoczęły się krótkie prezentacje, podczas to których słuchaliśmy ciekawych przemówień, popijając pyszne piwko i zagryzając smacznym jedzonkiem. Prezentację miały trwać mniej więcej po 10 minut i zawsze pociągały za sobą dyskusję. Ponieważ impreza trwała tylko jeden wieczór, nie każdy mógł coś prezentować, dlatego też organizatorzy wybrali (prawdopodobnie po kolejności zgłoszeń), kilka osób które mogły coś powiedzieć, a byli to:

  • Nataniel Zieliński
    Czy nazwa kompa w lesie może się duplikować?
  • Arkadiusz Waśniewski
    Coś o mobilnych, o komunikacjach z urządzeniami, o wykorzystaniu IIS do stworzenia własnego serwera komunikacji...
  • Tomasz Wiśniewski
    Jak jeden temat na blogu potrafi generować 90% odwiedzi na stronie.
  • Mariusz Kędziora
    O statystykach odwiedzin blogów Microsoft i o tym co można robić żeby próbować podnosić odwiedziny bloga.
  • Łukasz Sowa
    Startup bloga, czyli tworzenie swojej internetowej osobowości.
  • Paweł Potasiński
    Na jakie braki i niedoróbki w SQL Server najczęściej narzekamy w SoftLabie.
  • Jacek Ciereszko
    Blog czy blogów dwa. Wady i zalety pisania bloga w dwóch językach.
  • Justyna Spychała
    Pozycja na pomidorka czyli jak pseudotechnicznym blogiem wzbudzić wzruszenie w czytelnikach.
  • Marcin Borecki
    Czy niewolnictwo na pewno zniesiono? - pierwsza praca informatyka
  • Joanna Kozłowska
    Blogi w zastosowaniach edukacyjnych.

Tak!, ja także miałem okazję zabrania głosu, co przy moim stresie do przemówień, wymagało trochę alkoholu, choć i tak się bałem :P

Po wszystkich przemówieniach oraz długich plotkach, uczestnicy spotkania stopniowo rozeszli się do domów, aby rano wstać na MTS.

Uczestnicy

Uczestnicy którzy zgłosili się i którzy są wypisani na oficjalnej stronie imprezy to:

  1. Rafał Antas
  2. Agnieszka i Marcin Krupińscy
  3. Kuba Skalbania
  4. Joanna Kozłowska
  5. Jacek Barcikowski
  6. Tomasz Bryja
  7. Wojciech Kowasz
  8. Krzysztof Pietrzak
  9. Sebastian Wilczewski
  10. Wiktor Gworek
  11. Piotr Pawlik
  12. Jacek Laskowski
  13. Łukasz Sowa
  14. Jacek Ciereszko
  15. Daniel Dąbrowski
  16. Jacek Segit
  17. Jakub Gutkowski
  18. Ziemek Borowski
  19. Tomek Onyszko
  20. Radek Kępa
  21. Paweł Potasiński
  22. Marek Krupa
  23. Marcin Borecki
  24. Marcin Goł
  25. Bartłomiej Legiędź
  26. Michał Grzegorzewski
  27. Mariusz Kędziora
  28. Justyna Spychała
  29. Maciej Aniserowicz
  30. Paula Januszkiewicz
  31. Arkadiusz Waśniewski
  32. Grzegorz Tworek
  33. Nataniel Zieliński
  34. Jarosław Karaś
  35. Jacek Doktór
  36. Tomasz Wiśniewski
  37. Konrad Sagała

Wliczając Państwo Krupińskich, daje nam to 38 osób, ale Ci co byli, wiedza, że odwiedzili nas także gości z MS i nie tylko, a więc uczestników było jeszcze więcej!

Fotki








Sponsor

Sponsorem, jak się okazało była firma na M, i to nie McDonald's, także nie MediaMarkt, a było nim MS, czyli Microsfot (uwaga nie napisałem M$, poprawiam się!!!).



Podziękowania

No i na końcu specjalne podziękowania dla organizatorów imprezy, czyli Karol Stilger, Łukasz Foks i Aneta Sidorowicz.

Do zobaczenia na następnym Bloggers Underground!!!

Pozdro,

JAcek Ciereszko