Silverlight Native Child Window

Silverlight Native Child Window

Old forum URL: forums.lhotka.net/forums/t/12165.aspx


MadGerbil posted on Friday, September 27, 2013

I've a record on display in my main Silverlight window.  I can flip through the records and while I do so I'd like native child windows to update with details.  This is no problem for a ChildWindow control but it is a different matter for a child window (native) proper.

Anyone else done this or know of a good article on it?

skagen00 replied on Friday, September 27, 2013

When you are talking about native child windows vs ChildWindow, what is your distinction?  What do you mean by native child window?

In our application we do utilize a multiple browser capability - i.e. one can spawn additional instances of the application in multiple browser windows (open record in new window sort of thing) and the different browser windows (app instances) end up talking to each other.

 

MadGerbil replied on Monday, September 30, 2013

The 'native windows' are additional browser windows.

That is different (as you well know) than an instance of a child window class which cannot leave the parent window.

skagen00 replied on Monday, September 30, 2013

Every child window that opens up, we pass in the query string a Guid-type value that says "this is your listener ID".  During the startup, this child window (new browser window/new instance of the app) creates and registers its receiver with the "intra application communication manager" that we created.

LocalMessageReceiverManager.CreateReceiver(_thisListenerId, true, MessageReceivedHandler);

This call basically is a factory method to get a "LocalMessageReceiver" with the name of that Guid.  It also subscribes to the MessageReceived event and then turns itself on - (Listen()).

        public static LocalMessageReceiver CreateReceiver(string receiverName, bool keepAlive, EventHandler<MessageReceivedEventArgs> handler)
        {
            if (String.IsNullOrWhiteSpace(receiverName))
            {
                throw new ArgumentNullException("receiverName");
            }

            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }

            LocalMessageReceiver receiver = new LocalMessageReceiver(receiverName, ReceiverNameScope.Global, LocalMessageReceiver.AnyDomain);
            receiver.MessageReceived += new MessageHandler(handler, keepAlive).HandleMessage;
            receiver.Listen();

            return receiver;
        }

In Isolated Storage we keep a list of "queued" messages, which each new window checks too - "are there any messages waiting for me to process".  We also keep a list of the listener IDs there so that we know who we need to broadcast to.

Generally we then broadcast messages - which are often times to notify that a record changed (which may require the window to refresh/adjust itself) or even things like "shut down/log out".  This mechanism of communicating across application instances has worked extremely well for us.

         /// <summary>
        /// Broadcasts the indicated message to all listeners.
        /// </summary>
        /// <param name="message">
        /// Message to broadcast.
        /// </param>
        internal static void BroadcastMessage(IntraApplicationMessage message)
        {
            var info = GetIsolatedStorageFile();

            foreach (string listener in info.ListenersList)
            {
                LocalMessageSender messageSender = new LocalMessageSender(listener, LocalMessageSender.Global);

                messageSender.SendCompleted += (o, e) =>
                {
                    if (e.Error != null)
                    {
                        // The message did not sent successfully - remove the listener.
                        UnregisterListener(e.ReceiverName);
                    }
                };

                // Fire off the message.
                messageSender.SendAsync(message.ToString());
            }
        }

Hopefully that's enough to stir some ideas, but generally the LocalMessageReceiver is the area I'd suggest exploring.

MadGerbil replied on Monday, September 30, 2013

That does stir some ideas.   I'd like to get your thoughts on one other thing though.   My 'main' window is showing the record and the child windows will show 'detail'.   How is the 'detail' retrieved?   Should the detail be retrieved async or should I just pass the detail (already loaded on the record) to the child window somehow?   How do you handle this?

skagen00 replied on Monday, September 30, 2013

Oh do you have basically an list in your master window and clicking on a row displays details in the other window?  And your list isn't actually an info list, you actually have all the details you want to show in the child window?

If you didn't have all the details (it sounds like you do), I would probably basically broadcast to the child to "show details for record ID 5".

(If I understand you correctly).

Since you have the details - I don't know what the limitation is in terms of size for the messaging... you could potentially try MobileFormatter.Serialize and pass the object through the listener - deserialize it and you have it in your other app instance.   I've never tried something like that but it might work.

Another alternative would be to use MobileFormatter.Serialize and then compress it, put it into Isolated Storage under some defined key, and broadcast to your child window to "get the object from Isolated Storage"

skagen00 replied on Monday, September 30, 2013

One followup - max size is 40K.

http://msdn.microsoft.com/en-us/library/dd833063(v=vs.95).aspx

"Sending complex messages

With local messaging, you can send any string up to 40 kilobytes in length. In many situations, the message will only need to be a simple notification or a simple set of values that the receiver can parse and interpret easily. However, within the 40 kilobyte limit, you can send arbitrarily complex messages, including serialized objects and encrypted messages. "

If you still have the compression libraries in place, 40K can actually be a fairly meaningful object (serialized and compressed).  If you don't or your object could likely exceed 40K compressed, you may want to shuttle it along via Isolated Storage (if you want to not have to refetch in the child window)

MadGerbil replied on Monday, September 30, 2013

The isolated storage solution works very well.    Thank you.  Big Smile

Copyright (c) Marimer LLC