|
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;

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 }
|
March 8th, 2009 at 03:45
[...] Integration of browser’s unloading with Silverlight [...]
March 23rd, 2009 at 16:31
On line 19 : document.getElementById(’{0}’);
should be document.getElementById(’{0}’);
April 3rd, 2009 at 14:20
Hi ToMaHaWk,
The thing you’re mentioning has something to do with the editor changes ‘ into ’.
Thanks.
June 17th, 2009 at 21:44
Great post. Only issue is the single quote in the javascript copied the wrong character… Worked perfectly for my needs…
Thanks
August 21st, 2009 at 09:45
Hi,
Nice and Quick work around…. but how to do this if Application is Out Of Browser
August 21st, 2009 at 09:58
Hi Kapil,
I don’t know about any solution in the Out-of-Browser case, yet.
September 16th, 2009 at 16:10
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
September 24th, 2009 at 16:31
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
October 19th, 2009 at 08:56
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
October 19th, 2009 at 09:30
@Muneer,
I’m not aware of anyway to find out the difference between close and refresh.
-
Mark Monster
November 12th, 2009 at 12:01
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.