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.
Note: |
---|
Silverlight for Windows Phone does not support local messaging. |
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>
See Also