Geeks With Blogs
Peter Tweed Exploring and explaining the mysteries of .NET

With any complex enterprise application delivered over the web it is typical there are very complex functions that truly need Rick Internet Application interactivity with the end user and other areas where a simple web page will suffice.  Similarly it is reasonable to see situations where more than one RIA component will exist on the screen at the same time.  It would be great if there were an easy way for these RIA components were decoupled yet able to send messages between each other.

 

3 allows this scenario to be easily handled using Local Connections.  Two separate Silverlight applications can communicate with each other in a publisher-subscriber relationship.  So one application can publish messages as a named sender and determine if a listener was registered and received them and a second can listen to a named message sender and respond to messages received.

 

This enables us to decouple components yet allow them to communicate yet gracefully handle the communication whether or not another component is listening.  Very cool.

 

In this post I will show how to achieve this.  The scenario that I will implement is a single web page that hosts two separate Silverlight applications.  One of the Silverlight applications will send messages and receive a response from a listener and the second Silverlight application will listen for messages from the first and respond to them.

 

This app is built on Visual Studio 2008 SP1 and Silverlight 3 using C#.

Steps:

 

1.       Create a new Silverlight application named LocalConnectionFrom in an solution called LocalConnection.

2.       Choose to add a test web application for the Silverlight application named Localconnection.Web.

3.       Replace the layout root grid with the following xaml in the MainPage.xaml

 

  <Grid x:Name="LayoutRoot" Background="Red">

        <Grid.RowDefinitions>

            <RowDefinition Height="30" ></RowDefinition>

            <RowDefinition Height="30" ></RowDefinition>

            <RowDefinition Height="30" ></RowDefinition>

        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>

            <ColumnDefinition Width="100"></ColumnDefinition>

            <ColumnDefinition Width="100"></ColumnDefinition>

            <ColumnDefinition Width="100"></ColumnDefinition>

            <ColumnDefinition Width="*"></ColumnDefinition>

        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="0" Grid.Row="1">Select Color:</TextBlock>

        <ComboBox x:Name="ColorsSelector" Grid.Column="1" Grid.Row="1" SelectionChanged="ColorsSelector_SelectionChanged" >

            <ComboBoxItem Content="[Select a color]"></ComboBoxItem>

            <ComboBoxItem Content="Blue"></ComboBoxItem>

            <ComboBoxItem Content="Orange"></ComboBoxItem>

            <ComboBoxItem Content="Gray"></ComboBoxItem>

        </ComboBox>

        <TextBlock Grid.Column="2" Grid.Row="1">Message Status:</TextBlock>

        <TextBlock Grid.Column="3" Grid.Row="1" x:Name="status" ></TextBlock>

    </Grid>

 

This UI has a combo box that allows the user to select a color.  We will send the color selected to the second Silverlight application so it can change it’s background to reflect the color received.

 

4.       In the MainPage.xaml.cs add the following to the using statements

 

using System.Windows.Messaging;

 

5.       Replace the constructor of the MainPage class with the following code

 

        public MainPage()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

        }

 

        LocalMessageSender msger = new LocalMessageSender("ColorMessaging");

 

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            msger.SendCompleted += new EventHandler<SendCompletedEventArgs>((s, ea) =>

            {

                Dispatcher.BeginInvoke(new Action(() =>

                {

                    if (ea.Error != null)

                    {

                        status.Text = String.Format("Error [{0}]",

                          ea.Error.Message);

                    }

                    else

                    {

                        status.Text = ea.Response;

                    }

                }

                ));

            });

        }

 

        private void ColorsSelector_SelectionChanged(object sender, SelectionChangedEventArgs e)

        {

            if (ColorsSelector != null)

            {

                String selectedColor = (ColorsSelector.SelectedItem as ComboBoxItem).Content.ToString();

                msger.SendAsync(selectedColor);

            }

        }

 

The constructor is updated to define an event handler for the loaded event.  A LocalMessageSender object is defined with the name “ColorMessaging”.  This is the unique name that a LocalMessageReceiver object will use to attach to and receive messages.

When the user control is loaded an event handler is defined for the SendCompleted event of the LocalMessageSender.  In the event handler the Dispatcher invokes a delegate function so that the UI can be interacted with.  As the communication occurs asynchronously the Dispatcher thread must be used so the UI thread can interact with the UI – if the UI is to be updated.  The event handler receives a SendCompletedEventArgs object (ea in our code) which has various properties.  We use Error and Response in our example.  The Error property holds an Error object if an error occurred in the sending of the message – for example if no listener was available to receive the message.  The Response object is a string response from the listener.  This allows the user to communicate to the sender any response they wish.  In our example we will respond to the sender a message acknowledging the color received.

An event handler for the selection changed event of the combo box is then defined to retrieve the user selected named color and send it via the LocalMessageSender object to any registered listeners.

 

6.       Add a second Silverlight application to your LocalConnection solution named LocalConnectionTo.

7.       Replace the layout root grid with the following xaml in the MainPage.xaml

 

  <Grid x:Name="LayoutRoot" Background="Green">

        <TextBlock x:Name="txtColor" Text="[No color]" FontSize="60" Foreground="White" ></TextBlock>

  </Grid>

 

This displays a text block that will display the name of the color received from the LocalConnectionFrom application LocalMessageSender.  Notice we set the background of the grid to green.

 

8.       In the MainPage.xaml.cs in the LocalConnectionTo project add the following to the using statements

 

using System.Windows.Messaging;

 

9.       Replace the constructor of the MainPage.xaml.cs file in the LocalConnectionTo project with the following code

 

        public MainPage()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(MainPage_Loaded);

        }

 

        LocalMessageReceiver msger = null;

 

        void MainPage_Loaded(object sender, RoutedEventArgs e)

        {

            msger = new LocalMessageReceiver("ColorMessaging");

 

            msger.MessageReceived+=new EventHandler<MessageReceivedEventArgs>((o,ev)=>

                {

 

                    String color = ev.Message;

                    String resp = string.Empty;

                    Brush bgColor = null;

                    switch (color)

                    {

                        case "Blue":

                            resp = "Received color 'BLUE'";

                            bgColor = new RadialGradientBrush(Colors.Blue, Colors.Black);

                            break;

                        case "Orange":

                            resp = "Received color 'ORANGE'";

                            bgColor = new RadialGradientBrush(Colors.Orange, Colors.Black);

                            break;

                        case "Gray":

                            resp = "Received color 'GRAY'";

                            bgColor = new RadialGradientBrush(Colors.Gray, Colors.Black);

                            break;

                        default:

                            resp = "Couldn't decode color received '" + color + "'";

                            bgColor = new SolidColorBrush(Colors.Green);

                            break;

                    }

 

                    ev.Response = resp;

 

                    Dispatcher.BeginInvoke(new Action(() =>

                    {

                        this.LayoutRoot.Background = bgColor;

                        txtColor.Text = color;

                    }));

                }

                );

            msger.Listen();

        }

 

The constructor is updated to define an event handler for the loaded event.  When the user control is loaded a LocalMessageReceiver object is defined with the name “ColorMessaging”.  This is the unique name that the LocalMessageSender object in the LocalConnectionFrom project was defined with to send messages with.  An event handler is then defined for the Messagereceived event of the LocalMessageReceiver.  In the event handler the name of the color received in the message is used to create a brush that will be used to set the background color of the layout root grid of the MainPage user control.  A response message is also defined indicating the receipt of the color or that the color received couldn’t be processed, which will be populated into the Response object of the SendCompletedEventArgs of the sender event handler.  The Dispatcher thread updates the background color of the layout root grid and sets the text block to show the received message.

Finally the LocalMessageReceiver object starts listening for the named sender.

 

10.   In the LocalConnectionFromTestPage.aspx replace the existing div containing the Silverlight object with the following code

 

    <div id="silverlightControlHostFrom">

        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="200">

              <param name="source" value="ClientBin/LocalConnectionFrom.xap"/>

              <param name="onError" value="onSilverlightError" />

              <param name="background" value="white" />

              <param name="minRuntimeVersion" value="3.0.40624.0" />

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

              <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">

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

              </a>

          </object><iframe id="Iframe1" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>

 

    <div id="silverlightControlHostTo">

        <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="500">

              <param name="source" value="ClientBin/LocalConnectionTo.xap"/>

              <param name="onError" value="onSilverlightError" />

              <param name="background" value="white" />

              <param name="minRuntimeVersion" value="3.0.40624.0" />

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

              <a href="http://go.microsoft.com/fwlink/?LinkID=149156&v=3.0.40624.0" style="text-decoration:none">

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

              </a>

          </object><iframe id="_sl_historyFrame" style="visibility:hidden;height:0px;width:0px;border:0px"></iframe></div>

 

This defines the first Silverlight application LocalConnectionFrom above the second Silverlight application LocalConnectionTo.

 

11.   Run the application

 

 

12.   Select a color from the combo box and notice the background color change in the lower area of the browser to a radial gradient with the inner color the named color selected from the combo box.  Also notice the message received from the message listener displayed to the right of the combo box.

 

 

 

 

Congratulations!!!! You have implemented inter Silverlight application messaging.

 

What have we done?

 

We have defined two Silverlight applications for use in one web application.

 

We have defined one Silverlight application to publish messages via a LocalMessageSender object and the other Silverlight application to listen to messages from the sender and respond to them

 

We have seen how to use the Dispatcher to invoke the UI thread to interact with the UI in this asynchronous messaging scenario.

 

Conclusion

Silverlight 3 offers a nice neat way to send messages between multiple Silverlight applications and handle whether the sending was received and if so if any response is sent back.

This scenario demonstrated in this post is a simple one but the functionality available also allows message handling across domains and explicitly only within the current domain.

Posted on Sunday, July 26, 2009 11:18 AM Silverlight | Back to top


Comments on this post: Inter Silverlight Application Communication in Silverlight 3

# re: Inter Silverlight Application Communication in Silverlight 3
Requesting Gravatar...
Humm... interesting,

Thanks for writing about it
Left by web development company on Aug 27, 2009 10:04 AM

# re: Inter Silverlight Application Communication in Silverlight 3
Requesting Gravatar...
Great. Just what I was looking for! Much nicer than havingto go through JS.
Left by Ian Jones on Sep 03, 2009 2:18 AM

# re: Inter Silverlight Application Communication in Silverlight 3
Requesting Gravatar...
Yep - it's a great feature that is key to building Silverlight mashup apps that can be modularized nicely and (almost) loosely hooked together.
Left by Peter on Sep 13, 2009 10:38 AM

# re: Inter Silverlight Application Communication in Silverlight 3
Requesting Gravatar...
Silverlight 3 does work very well. Thank you for this detailed explanation.
Left by Boiler Systems on May 05, 2010 6:08 AM

Your comment:
 (will show your gravatar)


Copyright © PeterTweed | Powered by: GeeksWithBlogs.net