How to: Implement Communication Between Local Silverlight-Based Applications

Microsoft Silverlight will reach end of support after October 2021. Learn more.

The following code example demonstrates how to use the LocalMessageSender and LocalMessageReceiver classes.

In the XAML, the Receiver class defines a TextBlock for displaying the messages that it receives. The Sender class defines a Button for sending messages and a TextBlock for displaying the responses that it receives.

In the code-behind, the Receiver class initializes the LocalMessageReceiver and handles the MessageReceived event. The Sender class initializes the LocalMessageSender and provides custom handling for sending messages. This enables the sender to send messages repeatedly until the receiver responds. This is useful, for example, if the receiving application takes longer to load.

The sender passes the attempt number to the SendAsync(String, Object) method call along with the message. When the receiver finally responds, the sender displays the attempt number along with the response.

The HTML example hosts two copies of the sending application and one copy of the receiving application. This demonstrates that the receiver can receive messages from multiple senders.

NoteNote:

Silverlight for Windows Phone Silverlight for Windows Phone does not support local messaging.

Run this sample

Example

<UserControl x:Class="SendingApplication.Sender"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot">
        <StackPanel Orientation="Horizontal" >
            <TextBlock Text="Sender" FontSize="20" />
            <Button x:Name="button" Click="Button_Click"
                    Height="20" Margin="20,0,0,0" />
        </StackPanel>
        <TextBlock x:Name="output" />
    </StackPanel>
</UserControl>
Imports System
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Messaging

Partial Public Class Sender
    Inherits UserControl

    Private messageSender As LocalMessageSender

    Public Sub New()

        InitializeComponent()
        UpdateButton()
        messageSender = New LocalMessageSender( _
            "receiver", LocalMessageSender.Global)
        AddHandler messageSender.SendCompleted, _
            AddressOf sender_SendCompleted
        SendMessage("message from Sender constructor")

    End Sub

    Private clickNumber As Integer = 1

    Private Sub UpdateButton()
        button.Content = "send message 'click " & clickNumber & "'"
    End Sub

    Private Sub Button_Click(ByVal sender As Object, _
        ByVal e As RoutedEventArgs)

        SendMessage("click " & clickNumber)
        clickNumber += 1
        UpdateButton()

    End Sub

    Private Const MAX_ATTEMPTS As Integer = 10000
    Private attempt As Integer = 1

    Private Sub SendMessage(ByVal message As String)
        messageSender.SendAsync(message, attempt)
    End Sub

    Private Sub sender_SendCompleted(ByVal sender As Object, _
        ByVal e As SendCompletedEventArgs)

        If e.Error IsNot Nothing Then

            LogError(e)
            attempt += 1
            If attempt > MAX_ATTEMPTS Then
                output.Text = "Could not send message."
                Return
            End If
            SendMessage(e.Message)
            Return

        End If

        output.Text = _
            "Message: " & e.Message & Environment.NewLine & _
            "Attempt " & CType(e.UserState, Integer) & _
            " completed." & Environment.NewLine & _
            "Response: " & e.Response & Environment.NewLine & _
            "ReceiverName: " & e.ReceiverName & Environment.NewLine & _
            "ReceiverDomain: " & e.ReceiverDomain

        ' Reset attempt counter.
        attempt = 1

    End Sub

    Private Sub LogError(ByVal e As SendCompletedEventArgs)
        System.Diagnostics.Debug.WriteLine( _
            "Attempt number {0}: {1}: {2}", CType(e.UserState, Integer), _
            e.Error.GetType().ToString(), e.Error.Message)
    End Sub

End Class
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Messaging;

namespace SendingApplication
{
    public partial class Sender : UserControl
    {
        private LocalMessageSender messageSender;

        public Sender()
        {
            InitializeComponent();
            UpdateButton();
            messageSender = new LocalMessageSender(
                "receiver", LocalMessageSender.Global);
            messageSender.SendCompleted += sender_SendCompleted;
            SendMessage("message from Sender constructor");
        }

        private int clickNumber = 1;

        private void UpdateButton()
        {
            button.Content = "send message 'click " + clickNumber + "'";
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            SendMessage("click " + clickNumber);
            clickNumber++;
            UpdateButton();
        }

        private const int MAX_ATTEMPTS = 10000;
        private int attempt = 1;

        private void SendMessage(string message)
        {
            messageSender.SendAsync(message, attempt);
        }

        private void sender_SendCompleted(object sender, SendCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                LogError(e);
                attempt++;
                if (attempt > MAX_ATTEMPTS)
                {
                    output.Text = "Could not send message.";
                    return;
                }
                SendMessage(e.Message);
                return;
            }

            output.Text =
                "Message: " + e.Message + Environment.NewLine +
                "Attempt " + (int)e.UserState + 
                " completed." + Environment.NewLine +
                "Response: " + e.Response + Environment.NewLine +
                "ReceiverName: " + e.ReceiverName + Environment.NewLine + 
                "ReceiverDomain: " + e.ReceiverDomain;

            // Reset attempt counter.
            attempt = 1;
        }

        private void LogError(SendCompletedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(
                "Attempt number {0}: {1}: {2}", (int)e.UserState, 
                e.Error.GetType().ToString(), e.Error.Message);
        }

    }
}
<UserControl x:Class="ReceivingApplication.Receiver"
    xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml">
    <StackPanel x:Name="LayoutRoot">
        <TextBlock Text="Receiver" FontSize="20" />
        <TextBlock x:Name="output"/>
    </StackPanel>
</UserControl>
Imports System
Imports System.Windows.Controls
Imports System.Windows.Messaging

Partial Public Class Receiver
    Inherits UserControl

    Public Sub New()

        InitializeComponent()

        Dim messageReceiver As New LocalMessageReceiver("receiver", _
            ReceiverNameScope.Global, LocalMessageReceiver.AnyDomain)
        AddHandler messageReceiver.MessageReceived, _
            AddressOf messageReceiver_MessageReceived

        Try

            messageReceiver.Listen()

        Catch ex As ListenFailedException

            output.Text = "Cannot receive messages." & Environment.NewLine & _
                "There is already a receiver with the name 'receiver'."

        End Try

    End Sub

    Private Sub messageReceiver_MessageReceived( _
        ByVal sender As Object, ByVal e As MessageReceivedEventArgs)

        e.Response = "response to " & e.Message
        output.Text = _
            "Message: " & e.Message & Environment.NewLine & _
            "NameScope: " & e.NameScope.ToString() & Environment.NewLine & _
            "ReceiverName: " & e.ReceiverName & Environment.NewLine & _
            "SenderDomain: " & e.SenderDomain & Environment.NewLine & _
            "Response: " & e.Response

    End Sub

End Class
using System;
using System.Windows.Controls;
using System.Windows.Messaging;

namespace ReceivingApplication
{
    public partial class Receiver : UserControl
    {
        public Receiver()
        {
            InitializeComponent();

            LocalMessageReceiver messageReceiver =
                new LocalMessageReceiver("receiver",
                ReceiverNameScope.Global, LocalMessageReceiver.AnyDomain);
            messageReceiver.MessageReceived += messageReceiver_MessageReceived;
            try
            {
                messageReceiver.Listen();
            }
            catch (ListenFailedException)
            {
                output.Text = "Cannot receive messages." + Environment.NewLine +
                    "There is already a receiver with the name 'receiver'.";
            }
        }

        private void messageReceiver_MessageReceived(
            object sender, MessageReceivedEventArgs e)
        {
            e.Response = "response to " + e.Message;
            output.Text =
                "Message: " + e.Message + Environment.NewLine +
                "NameScope: " + e.NameScope + Environment.NewLine +
                "ReceiverName: " + e.ReceiverName + Environment.NewLine +
                "SenderDomain: " + e.SenderDomain + Environment.NewLine +
                "Response: " + e.Response;
        }
    }
}
<!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" >
<!-- saved from url=(0014)about:internet -->
<head>
  <title>LocalMessaging</title>

  <style type="text/css">
  html, body {
    height: 100%;
    overflow: auto;
  }
  body {
    padding: 0;
    margin: 0;
  }
  #silverlightControlHost1 {
    padding: 0;
    margin: 0;
  }
  #silverlightControlHost2 {
    padding: 0;
    margin: 0;
  }
  </style>
</head>

<body>
  <table border="10" cellpadding="10" cellspacing="10">
    <tr>
      <td>
        <div id="silverlightControlHost1">
          <object data="data:application/x-silverlight-2," 
            type="application/x-silverlight-2" 
            width="400" height="120">
            <param name="source" value="ClientBin/SendingApplication.xap"/>
            <param name="onerror" value="onSilverlightError" />
            <param name="background" value="white" />
          </object>
          <iframe style='visibility:hidden;height:0;width:0;border:0px'>
          </iframe>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div id="Div1">
          <object data="data:application/x-silverlight-2," 
            type="application/x-silverlight-2" 
            width="400" height="120">
            <param name="source" value="ClientBin/SendingApplication.xap"/>
            <param name="onerror" value="onSilverlightError" />
            <param name="background" value="white" />
          </object>
          <iframe style='visibility:hidden;height:0;width:0;border:0px'>
          </iframe>
        </div>
      </td>
    </tr>
    <tr>
      <td>
        <div id="silverlightControlHost2">
          <object data="data:application/x-silverlight-2," 
            type="application/x-silverlight-2" 
            width="400" height="120">
            <param name="source" value="ClientBin/ReceivingApplication.xap"/>
            <param name="onerror" value="onSilverlightError" />
            <param name="background" value="white" />
          </object>
          <iframe style='visibility:hidden;height:0;width:0;border:0px'>
          </iframe>
        </div>
      </td>
    </tr>
  </table>
</body>
</html>