do { Engine.BlogAbout(".NET","Silverlight"); } while ( alive );  

Mark Monster

Mark Monster  

Integration of browser’s unloading with Silverlight

It happens very often that people, the users of your application loose their changes because the accidentally closed a browser window or browser tab. Specially because all browsers now support tabs, which is not something all non-technical users completely understand.

There is however something you can use to partly overcome this issue. In the year 2004 there was an article about this on 4guysfromrolla.com. This article explains excellently how to make use of the window.onbeforeunload event in Javascript.

I thought about this a few minutes and got the following example on how to integrate this inside your Silverlight application.

First of all I wanted this window.onbeforeunload Javascript event to call a method inside my Silverlight application. So I wrote a small method that can be called inside Silverlight.

    1 [ScriptableMember]

    2 public string OnBeforeUnload()

    3 {

    4     return "Warning you’re closing…";

    5 }

Besides that it also needs to be registrated in Javascript.

const string scriptableObjectName = "Bridge";

HtmlPage.RegisterScriptableObject(scriptableObjectName, this);

So now we have a method that can be called from Javascript. Let’s start listening to this Javascript event from Silverlight.

string pluginName = HtmlPage.Plugin.Id;

HtmlPage.Window.Eval(string.Format(

    @"window.onbeforeunload = function () {{

                var slApp = document.getElementById(’{0}’);

                var result = slApp.Content.{1}.OnBeforeUnload();

                if(result.length > 0)

                    return result;

            }}", pluginName, scriptableObjectName)

    );

This does work. But do we want to always show a message? Or do we only want to show the message if it’s relevant? I think the choice will be the last, at least for me it will. So what about an IsDirty check? I created a very simple non-real one. Because of the sake of the article, it’s about the message when closing, right?

private bool isDirty = true;

public bool IsDirty

{

    get

    {

        bool tempDirty = this.isDirty;

        this.isDirty = false;

        return tempDirty;

    }

}

Let’s combine this with our OnBeforeUnload method in Silverlight.

[ScriptableMember]

public string OnBeforeUnload()

{

    if (IsDirty)

        return "The page is dirty. Are you sure you want to close?";

    return string.Empty;

}

When you take a close look at my implementation of IsDirty, you’ll see it’s only dirty the first time, the second time it’s not. Now when you try to exit the page by one of the following ways, you’ll get this message:

  • By closing Tab;
  • By closing Window;
  • By changing to a different url;

image

When you press Cancel you will actually stay on the page. The thing is we only have influence on the text in the middle. I have been thinking about different solutions, by using for example a dialog in Silverlight, but sadly this is just not possible. The function window.onbeforeunload only accepts a message that it can show. When nothing is return on the event, it just closes.

For your convenience the complete code of Page.xaml.cs.

    1 public partial class Page : UserControl

    2 {

    3     private bool isDirty = true;

    4     public Page()

    5     {

    6         InitializeComponent();

    7         RegisterOnBeforeUnload();

    8     }

    9 

   10     public void RegisterOnBeforeUnload()

   11     {

   12         //Register Silverlight object for availability in Javascript.

   13         const string scriptableObjectName = "Bridge";

   14         HtmlPage.RegisterScriptableObject(scriptableObjectName, this);

   15         //Start listening to Javascript event.

   16         string pluginName = HtmlPage.Plugin.Id;

   17         HtmlPage.Window.Eval(string.Format(

   18             @"window.onbeforeunload = function () {{

   19                 var slApp = document.getElementById(’{0}’);

   20                 var result = slApp.Content.{1}.OnBeforeUnload();

   21                 if(result.length > 0)

   22                     return result;

   23             }}",pluginName,scriptableObjectName)

   24             );

   25     }

   26 

   27     [ScriptableMember]

   28     public string OnBeforeUnload()

   29     {

   30         if (IsDirty)

   31             return "The page is dirty. Are you sure you want to close?";

   32         return string.Empty;

   33     }

   34 

   35     public bool IsDirty

   36     {

   37         get

   38         {

   39             bool tempDirty = this.isDirty;

   40             this.isDirty = false;

   41             return tempDirty;

   42         }

   43     }

   44 }

11 Responses to “Integration of browser’s unloading with Silverlight”

  1. Silverlight Cream for February 28, 2009 -- #531 Says:

    [...] Integration of browser’s unloading with Silverlight [...]

  2. ToMaHaWk Says:

    On line 19 : document.getElementById(’{0}’);

    should be document.getElementById(’{0}’);

  3. Mark Monster Says:

    Hi ToMaHaWk,

    The thing you’re mentioning has something to do with the editor changes ‘ into ’.

    Thanks.

  4. Jason Jarrett Says:

    Great post. Only issue is the single quote in the javascript copied the wrong character… Worked perfectly for my needs…

    Thanks

  5. kapil bhavsar Says:

    Hi,

    Nice and Quick work around…. but how to do this if Application is Out Of Browser

  6. Mark Monster Says:

    Hi Kapil,

    I don’t know about any solution in the Out-of-Browser case, yet.

  7. Adam Says:

    Hi Mark I have been trying to get this going in Silver 3 but am having difficulties with HtmlPage.Plugin.Id as it returns blank, any ideas?

    Thanks

    Adam

  8. Krishn Says:

    Hello Adam,

    I got the same blank one until I realised how silly it was - Did you actually give a ID to the main page div - that will solve it.

    Hi Mark,

    great article - but am facing yet another problem. I need to call logout when browser closes - if I send a logout message on beforeunload function it is blocked until the string is returned :(

    I was trying to return a blank string - problem is if the user presses ‘cancel’ i cannot logout.

    Is there a way to catch if ‘ok’ or ‘cancel’ is pressed or is there a way to not show ‘cancel’ button at all.

    Any pointers will be very useful

    Cheers
    Krish

  9. Muneer Says:

    Hi,
    How Can we Know whether Browser is Closed are Refreshed in Silverlight Please Help.
    Coz for Both Refresh and Close OnbeforeUnload is Executing. Then How Can we Know whether
    Browser is Closed are Refreshed.i wnt to Clear my Isolatedstorage Settings once the Browser is Closed.
    Thanks and Regards,
    Muneer

  10. Mark Monster Says:

    @Muneer,

    I’m not aware of anyway to find out the difference between close and refresh.

    -
    Mark Monster

  11. Britney Spears Says:

    Hi Mark,

    What a great idea! Thanks for sharing your code. It works like a charm. Of course only after I gave my silverlight object a ID. Thanks Krish! I was wondering what went wrong.

Leave a Reply