Monday, May 12, 2008

Inter silverlight communication design

Here is the solution which I promised to give in one of my older posts titled Javascripting silverlight.I delayed because this post needs some prerequisites which I discussed in the below posts.


Inter silverlight communication or cross Silverlight plugin communication means just interaction between 2 or more plugins hosted in same web page.To achieve this we have to write a javascript layer which controls the flow of communication.

It means each plug in will talk to javascript layer if they want to communication to other plug in.The javascript layer is responsible for the routing of these communications.

For 2 way communication we need to make the Page class as Scriptable.The Page class should have methods decorated with ScriptableMember which talk to javascript.

Sample

Lets take the case of Sliders.Our Silverlight page have a slider and there are 2 instances of Plug in the same web page.Our aim is to sync Sliders in these plugins.

Silverlight side

On slider's ValueChanged event handler we tells Javascript to adjust the slider in plugins.The reverse ie setting slider value on valuechange of other plug in is done in some other method which is marked as ScriptableMember.

[ScriptableType]

public partial class Page : UserControl

{

public Page()

{

InitializeComponent();

HtmlPage.RegisterScriptableObject("mainpage", this);

}

private void sldr_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)

{

HtmlPage.Window.Invoke("ValueChanged", sldr.Value);

}

[ScriptableMember]

public void SetValue(double d)

{

sldr.Value = d;

}

}
Javascript side

Here we will accept the value provided by plugin and pass the same to all the plugins by getting their references

<head runat="server">

<title>Test Page For SilverlightApplication1</title>

<script language="javascript">

function ValueChanged(value)

{

var Host1 = document.getElementById("Xaml1");

var Host2 = document.getElementById("Xaml2");

Host1.content.mainpage.SetValue(value);

Host2.content.mainpage.SetValue(value);

}

function clicked()

{

var name=document.getElementById("txt");

var val=parseFloat(name.value);

if(val!=null){

ValueChanged(val);

}

}

</script>

</head>

<body style="height:300;margin:0;">

<form id="form1" runat="server" style="height:300;">

<asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>

<div style="height:300;">

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" Version="2.0" Width="300" Height="300" />

</div>

<br /> <hr />

<marquee> <a href="#">HTML area</a></marquee>

<hr />

<input type="text" id="txt" value="50" />

<button onclick="clicked()">Change value</button>

<div style="height:300;">

<asp:Silverlight ID="Xaml2" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" Version="2.0" Width="300" Height="300" />

</div>

</form>

</body>

Sample available here


Saturday, May 10, 2008

What is ScriptObject?

Simply,this is the managed code representation of complex javascript objects.

Confused?? Here is one scenario.Suppose there is a method in Javascript which returns a string value.We will call that method by simply executing HtmlPage.Invoke() method and process the return value as needed in silverlight.

This is possible because the javascipt function returns string.There is a proper mapping in silverlight to accept the value.What to do if javascript has to return the following object.

function GetDetails()
{
var me={Name:'joy',Company:'identitymine'};
return me;
}

How can silverlight recognize the object type?In this case we have to use ScriptObject.See more details about the class here in msdn

Below is the solution which solves the said scenario

private void btn_Click(object sender, RoutedEventArgs e){
ScriptObject obj = HtmlPage.Window.Invoke("GetDetails", "");
txtName.Text = (string)obj.GetProperty("Name");
}

Sample available here

Thursday, May 8, 2008

Silverlight - Javascript Communication - Part 2

Please have a look at my previous post which handles the communication in a easy way.Better use that technique whenever required.But Of course as per your requirements it may vary.

As I told in the earlier post we need to have understanding about Scriptable attribute,ScriptObject etc.I have listed some links which I feel explains the concept well.

  1. ScriptableType attribute: This tells that the type is accessible from script.Usually we decorate the Page class with this attribute.(See what MSDN tells)
  2. ScriptableMember attribute : Tells that this member is accessible from script.(See what msdn tells)
Well in the C# we had told that these are the types and members which are accessible in script.But how the browser ,HTML ,Javascript or DOM knows that.For that we just have to register the object with HTML DOM.

This uses the RegisterScriptableObject () method of HtmlPage class.(See what msdn says)

HtmlPage.RegisterScriptableObject("mainpage", this);//mainpage is the name in which DOM should access the object

Now we completed works in C#.Lets put that all together
[ScriptableType]
public partial class Page : UserControl {
public Page(){
InitializeComponent();
HtmlPage.RegisterScriptableObject("mainpage", this);
}
[ScriptableMember]
public void SetData(double val){
sldr.Value = val;//sldr is an object of Slider
}
}

At the javascript side we just need to get the object of plug in to invoke the method which is scriptable.

var Host = document.getElementById("Xaml1");//Xaml1 is id of Silverlight Control

Once we get the plug in just call

Host.content.mainpage.SetData(val);

Putting altogether

<head runat="server">
<title>Test Page For SilverlightApplication1title>
<script language="javascript">
   1:     function setvalue() { 
   2:         var v=document.getElementById("txt");
   3:         var val=parseFloat(v.value);
   4:         var Host = document.getElementById("Xaml1");
   5:         Host.content.mainpage.SetData(val);
   6:     }
</script>
</head>
<body style="height:300;margin:0;">
<form id="form1" runat="server" style="height:300;">
<asp:ScriptManager ID="ScriptManager1" runat="server">asp:ScriptManager>
<div style="height:300;">
<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightApplication1.xap" Version="2.0" Width="300" Height="300" />
</div>
<br />

<a href="#">HTML Areaa><br />
<input type="text" id="txt" /> <button onclick="setvalue()">Update Sliderbutton>
</form>
</body>

Sample available here.

Silverlight - Javascript communication - Part 1

Please don't confuse this with one of my earlier post which described how to do things with javascript without disturbing C#.

Here I am going to say how to accomplish communication between C# code in Silverlight and Javascript in aspx , html or any file which hosts Silverlight plug in.

Simple communication
Here I am using the Invoke() method of HTMLWindow class for communication.
  • Silverlight –> Javascript The data flow here is from Silverlight to Javascript.For accomplishing this we need to entities.
    1. Sender->Silverlight code which initiate the action.This is Invoke() method call now.
    2. Receiver -> Javascript function which is being called by Silverlight's Invoke method
    Silverlight
    private void Button_Click(object sender, RoutedEventArgs e){
    System.Windows.Browser.HtmlPage.Window.Invoke("ShowMsg", txtInput.Text);

    }

    Javascript

    function ShowMsg(msg)
    {
    alert(msg);
    }



  • Javascript -> Silverlight

    Here the data flow is from Javascript to Silverlight.i.e we returns some value from the javascript function to Silverlight .

    Javascript

    function GetData()
    {
    var reply = prompt("What's your name?", "");
    return (reply);
    }


    Silverlight


    private void Button_Click_1(object sender, RoutedEventArgs e){
    string o=(string)System.Windows.Browser.HtmlPage.Window.Invoke("GetData", "");
    txtOutput.Text = o;
    }

Sample here

Here initiator of all the communications is Silverlight.But what to do if Javascript has to start communication.For that we should be familiar with Scriptable attribute,ScriptObject etc..That will discuss later otherwise this post become a story. :-)

Tuesday, May 6, 2008

Run Tag v/s code

As a Silverlight dev or designer, we are all familiar with Run tag which helps us to show multiple text formats in single TextBlock.

Normally we achieve the Run functionality through XAML.But have you think of doing the same from c#?? There is no direct children in TextBlock where we can pump objects of Run.
Then what to do ?

The solution is simple Use the TextBlock.Inlines collection.

Here goes the implementation

Run joy = new Run();

joyr.Text = "joy";

joy.Foreground = new SolidColorBrush(Colors.Blue);

Run george = new Run();

george.Text = "joy";

george.Foreground = new SolidColorBrush(Colors.Blue);


txt.Inlines.Add(joy);

txt.Inlines.Add(george);