Disappearing Silverlight controls and SharePoint modal dialogs

If you’ve spent anytime developing Silverlight controls for SharePoint that utilise SP.UI.ModalDialog dialogs you may have noticed a idiosyncrasy with the way Silverlight behaves when a modal dialog is thrown from the page that hosts the Silverlight control. The behaviour in IE is that the Silverlight is hidden whilst the modal is visible:

Before throwing a modal – Silverlight control is visible on a page:

image

During – modal is thrown and Silverlight is hidden:

image

Once the modal dialog has been closed, the control is made visible again. This presents two issues as far as I can tell, firstly the Silverlight control is actually reloaded when the modal is closed due to a bug. I’ve blogged about this issue including a workaround on this post. Secondly, user context is broken. Depending on the operation your controls is performing, it could be important that the Silverlight controls remain visible whilst a modal dialog is open.

One thing to note is that the behaviour described above is different in Firefox. Here, the Silverlight control remains visible but is not masked by the opaque div that is used to dim the background:

During – Firefox keeps the Silverlight control visible:

image

So why is the Silverlight control hidden by IE but not by Firefox? The answer is in the out-of-the-box SP.UI.Dialog.js file, or in this example, the SP.UI.Dialog.debug,js file:

image

The out-of-the-box JavaScript  checks the browser agent (line 1158) and, if you’re running IE, it loops through every object tag on the page and sets their style visibility attribute to hidden (line 1164). It certainly looks like the disappearing Silverlight controls in IE is the intended behaviour – more about is in a moment. In the meantime, if you need to work around this issue we can use a little additional JavaScript after we’ve opened our modal to show the Silverlight control in IE again.

The script extract below is actually taken from lines 1180 to 1190 of the SP.UI.Dialog.debug.js file and is what gets executed out-of-the-box when a modal dialog is closed. We’re simply running the same JavaScript immediately after opening the modal dialog. Walking through the code below we can see just before we open the modal, we set the browser focus away from our Silverlight control (this stops the control reloading when the modal is closed – see this post for details). Next, we show our modal as usual via a call to SP.UI.ModalDialog.showModalDialog. Finally we immediately loop through all the object tags on the page and set them to back visible:

image

Why do this? Well, we’ve worked around the out-of-the-box behaviour of SharePoint modals, Silverlight and IE that hides object tags and our user experience in IE now behaves just like Firefox:

So now in IE and Firefox we see the same behaviour – the Silverlight control remains visible but is not covered by the opaque div used to dim the modal background. 1 line of XAML and 2 lines of C# will fix that.

Next, open the source code of your Silverlight control and append to the end of your control stack (so that it appears over the top of all other controls), a canvas that is the same size as your entire usercontrol:

image

The important attributes of this canvas are highlighted. The opacity and background colour attributes match those of the out of the box opaque div and the initial visibility is set to collapsed (hidden). Next, in our Silverlight control just before we throw the modal dialog, we make our new canvas visible:

image

This approach assumes you’re initiating the modal dialogs from the Silverlight control. If not, it would be easy enough to call a ScriptableMember from the JavaScript that calls a Silverlight method that changes the canvas visibility to visible.

Lastly, once the modal is closed, I’m using another ScriptableMember  that is called from the JavaScript that collapses the canvas:

image

The end result is a visible Silverlight control that has a canvas applied over the top of it that matches the opacity and colour of the out-of-the-box modal background. This ‘fix’ works in both IE and Firefox:

image

Now the downside, and possibly why objects tags are hidden in IE by the out-of-the-box JavaScript shipped with SharePoint. With the Silverlight control visible, they can be clicked on and when you do so, they gain focus and are displayed above the modal dialog (this only happens in IE). In my environment, this is less of an issue than the whole control being hidden but you need to know about this side effect:

image

Luckily by adding a canvas to the top of the control stack of the Silverlight control I’m stopping any Silverlight buttons or controls from being clicked. I’m looking at a possible fix for this last issue and will blog further if it works.

I hope this helps someone…

Silverlight, JavaScript and SharePoint Modal Dialogs

I spent some time recently using Silverlight and SharePoint modal dialogs in anger for a client engagement. For this particular project we’re dealing with lots of hierarchical data structures and the function requirement is to provide a drag and drop user interface to support building and reorganising these hierarchies. When combined with the platform choice of SharePoint, Silverlight seemed to be the obvious technology with which to build these controls. We’re using the drag and drop examples form the Silverlight Toolkit for the basis of our controls and combining them with the SharePoint modal dialog framework via SP.UI.ModalDialog.showModalDialog.

To support the solution, we need to create lots of modal dialogs in SharePoint and test the Silverlight controls functionality within these modals. To help support this testing, I built a SharePoint web part that is used to launch modal dialogs:

image

The web part itself, renders a Silverlight control that is used to capture the options needed to launch the modal. When the ‘Go’ button is clicked, the Silverlight control calls the required JavaScript function that launches the modal. The modal is displayed and once it is closed, the results of the modal are returned to the Callback function. In turn, the Callback function calls a ScriptableMember method in the Silverlight control and the results of the modal are then displayed in the Callback Result Value textbox of the Silverlight control.

The flow of data this web part provides is as follows:

Web part  >  Silverlight  >  JavaScript  >  SP.UI.ModalDialog  >  JavaScript  >  Silverlight

There is however, one big gotcha with this data flow that tripped me up for quite a while. When control is passed back to the Callback function after the modal has been closed, the Silverlight control appears to be reloaded. When this happens, any data or settings your entered into the web part are lost and the control reloads with its initial configuration. Clearly this is far from ideal…

I noticed however, that this behaviour is not replicated in Firefox. With Firefox, the results are passed back to the JavaScript Callback function, the function calls the ScriptableMember method without reloading the Silverlight control and all of our settings are preserved plus the results from the modal are shown to the user as per our intended behaviour.

This observation led me to this post that describes an issue with Silverlight and IE that causes the Silverlight plugin to be unloaded and reloaded when a Silverlight control is hidden that currently has focus. The solution suggested by this post is to set focus to another object in the DOM prior to hiding the object. Hiding all the object tags on the calling page is precisely what the SharePoint modal dialog framework does – thus it causes the Silverlight control to be unloaded and reloaded.

The following additional line of JavaScript added just prior to launching the modal dialog solves our problem when this technique is used with IE:

image

The source code for the web part and Silverlight control are available on codeplex: http://throwamodal.codeplex.com/

I hope this helps…