One of the features of Silverlight 3 that developers are going to love is local connections, which enable Silverlight control instances to communicate with each other. Local connections use a publish/subscribe mechanism to connect senders and receivers. And they work just as well whether the control instances are in the same page (and the same process) or in different pages and different processes. In Silverlight 2, you could do a lot of manual work to allow control instances in the same page to message each other, but it was next to impossible to bridge the gap between two control instances in two different browsers.

I wrote a sample app that demonstrates the basics of local connections. One of the test pages in the solution–LocalConnectionDemoTestPage.html–declares two Silverlight control instances. The control instance at the top of the page is a throwback to the old MFC Scribble tutorial from years ago: you scribble in it by holding down the left mouse button. The control instance at the bottom of the page mirrors the strokes drawn in the first control instance:

Local Connections (1) 

When the first control instance starts up, it initializes a LocalMessageSender object in order to send messages to the second control:

private LocalMessageSender _sender =

    new LocalMessageSender(“StrokeReflector”);

When the left mouse button goes down, the first control records the mouse coordinates and then sends them to the second control:

_last = e.GetPosition((FrameworkElement)sender);

_sender.SendAsync(String.Format(CultureInfo.InvariantCulture,

    “S{0},{1}”, _last.X, _last.Y));

And when the mouse moves with the left button held down, the first control draws a line from the previous mouse coordinates to the current coordinates and fires off a message to the second control containing the current coordinates:

// Add a line

Point current = e.GetPosition((FrameworkElement)sender);

 

Line line = new Line();

line.X1 = _last.X;

line.Y1 = _last.Y;

line.X2 = current.X;

line.Y2 = current.Y;

line.Stroke = new SolidColorBrush(Colors.White);

line.StrokeThickness = 8.0;

line.StrokeStartLineCap = PenLineCap.Round;

line.StrokeEndLineCap = PenLineCap.Round;

ScribbleSurface.Children.Add(line);

 

_last = current;

 

// Notify the other control

_sender.SendAsync(String.Format(CultureInfo.InvariantCulture,

    “D{0},{1}”, current.X, current.Y));

For its part, the second control initializes a LocalMessageReceiver when it starts up:

private LocalMessageReceiver _receiver =

    new LocalMessageReceiver(“StrokeReflector”);

Then it registers a handler for MessageReceived events and calls LocalMessageReceiver.Listen to listen for messages:

_receiver.MessageReceived +=

    new EventHandler<MessageReceivedEventArgs>(OnMessageReceived);

_receiver.Listen();

The event handler decodes each message transmitted by the first control and either records the anchor point if the mouse button just went down in the first control, or duplicates the stroke drawn in the first control if the mouse was moved:

void OnMessageReceived(object sender, MessageReceivedEventArgs e)

{

    string command = e.Message.Substring(0, 1);

 

    switch (command)

    {

        case “S”:

            _last = GetPointFromMessage(e.Message);

            break;

 

        case “D”:

            Point point = GetPointFromMessage(e.Message);

 

            Line line = new Line();

            line.X1 = _last.X;

            line.Y1 = _last.Y;

            line.X2 = point.X;

            line.Y2 = point.Y;

            line.Stroke = new SolidColorBrush(Colors.White);

            line.StrokeThickness = 8.0;

            line.StrokeStartLineCap = PenLineCap.Round;

            line.StrokeEndLineCap = PenLineCap.Round;

            ScribbleSurface.Children.Add(line);

 

            _last = point;

            break;

    }

}

It really gets interesting when you run the app’s other two test pages. SenderTestPage.html creates an instance of the first control (the “sender”), and ReceiverTestPage.html creates an instance of the second control (the “receiver”). Without changing a line of code, you can start each page in a different browser instance and draw in the sender and see your strokes duplicated in the receiver. The screen shot below was taken with the sender running in IE, and the receiver running in Firefox–two different browsers and two different processes.

Local Connections (2) 

But don’t believe me: download the sample app and try it yourself!