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 }

Tracking Silverlight support in Google Analytics

I think that a lot of people make use of Google Analytics for their site statistics. I am one of those Google Analytics users. You can easily dive into the statistics. Like checking the amount of visitors that have support for Java or Flash. But sadly Google still doesn’t track the support of Silverlight. So I though let’s dive into getting some statistics about Silverlight support in Google Analytics. How to track custom data in Google Analytics? You can easily track custom data. You can do things just like this. A very simple track would be something like: pageTracker._trackPageview("/tracking/tryout"); How to check support for Silverlight? The check for Silverlight support isn’t that difficult as well. You will just need to reference Silverlight.js. And after that there will be a new function available called Silverlight.isInstalled. This function accepts a string which contains the version number. We can use it like this. Silverlight.isInstalled('1.0'); or Silverlight.isInstalled('2.0'); Combined: check for Silverlight support and tracking in Google Analytics The combination of both the Google Analytics tracking with Silverlight support will looks like this (make sure you change the location of Silverlight.js and your Google Analytics tracking code). <script type="text/javascript" src="/Javascript/Silverlight.js"> </script> <script type="text/javascript"> var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); </script> <script type="text/javascript"> var pageTracker = _gat._getTracker("UA-xxxxx-x"); pageTracker._trackPageview(); var hasSilverlight = Boolean(window.Silverlight); var hasSilverlight1 = hasSilverlight && Silverlight.isInstalled('1.0'); var hasSilverlight2 = hasSilverlight && Silverlight.isInstalled('2.0'); if (hasSilverlight1) { pageTracker._trackPageview("/silverlightsupport/v1/support"); } else { pageTracker._trackPageview("/silverlightsupport/v1/nosupport"); } if (hasSilverlight2) { pageTracker._trackPageview("/silverlightsupport/v2/support"); } else { pageTracker._trackPageview("/silverlightsupport/v2/nosupport"); } </script> How does it look like? Content Drilldown - /silverlightsupport/v1 Support: 50% No support: 50% image Content Drilldown - /silverlightsupport/v2 Support: 49% No support: 51% image The statistics say that about 50% of the visits I get have support for Silverlight 1 and 2. But it’s important to know these stats are just from one days data. For real statistics you need at least weeks or maybe even months of data. PS. Sorry for the bad code-snippets. I have always been using the very nice Live Writer plugin from Steve Dunn. But this plugin doesn’t work anymore in the latest version of Live Writer. Update February 25th 2009: Szabi has written an excellent addition to this article.

Book review: NHibernate in Action now in print

imageIt took the authors of NHibernate in Action a very long time to complete this book. It was already in the summer of 2006 that I got involved in the NHibernate in Action book. First steps were basically reviewing the first chapters manuscript. Later on I also reviewed other chapters. About half a year ago, or maybe it was even three quarter of a year ago (time goes fast these days), Manning asked me to do the Technical Proofreading of NHïbernate in Action. In het end the book finally got to print. And yes I really like it. Although I would have been very happy to have this book in the year 2006, I’m glad to have it now. Besides the fact that this is a NHibernate book, it also covers ORM in general. And a lot patterns and concepts discussed in this book apply to other ORMs as well, like Linq2SQL and the Entity Framework.

Add more code analysis to ReSharper

I’m an very enthusiastic ReSharper user before ReSharper 1 was even released. Just using beta’s in that era. One of the nice features ReSharper offers is the code analysis. I really like it, although I’ve used Coding Analysis that was offered by Visual Studio 2005 in the past. I had never used it in Visual Studio 2008, I do not even know if it still exists in Visual Studio 2008. But we have something new now: StyleCop StyleCop StyleCop can be downloaded from MSDN Code Gallery. StyleCop can enforce style rules. This is something that a lot of companies want to be enforced. Besides the fact I really like style to be enforced. It becomes even nicer, StyleCop can be integrated into ReSharper. You will need the StyleCop for Resharper plugin from CodePlex for this integration. I’ve tried it on a personal project and yes I kind of like it. I want to tweak it in some parts, but it’s something that helps enforcing me to add comments for example. Tweaking is very easy. Note: I copied the images from StyleCop for Resharper codeplex site.

Why doesn’t the Setup Project create a valid shortcut in the Send To folder?

Windows does have a very nice feature that’s called the Send To menu in the context menu in Windows Explorer (yes the Desktop is also Windows Exporer) for files and folders. In this menu there reside a few standard options, but you can easily add one yourself. I’ve seen for example lots of developers having their favorite editor being inside the Send To menu. This is possible because most editors (I’m not aware of any that doesn’t) support the filename be passed as a first argument to open the file.

I’ve set this up in the past. It’s very easy, just go to the Send To Folder. Under XP it’s like this: C:\Documents and Settings\username\SendTo . In this folder create a short cut to an application, for example Notepad. From that moment Notepad will appear in the Send To context menu.

I’m currently working on a application that makes use of the Send To feature available in Windows. So I thought let’s do something very easy: Create a short cut in the Send To folder from within a Setup Project. And yes that was very easy. The file-system has support for the special Send To folder.

image

But sadly the shortcut, called “File Versioner”, doesn’t show up. After some investigation I found out the shortcut was in the folder, but it did not show up.

Advertised shortcuts

What’s wrong? Some more investigation was needed, and I found out that shortcuts created by the MSI are Advertised shortcuts. Those are different from the ones you create by hand.

It took me some time until I found out how to change the type of shortcuts. Some developers might already have heard about a tool called Orca. This is a tool that’s part of Windows SDK. Orca enables developers to edit the database tables that are inside of an MSI.

You can make disable Advertised Shortcuts by the following steps:

  1. Start Orca
  2. Open the MSI inside of Orca
  3. Select the table named “Property”
  4. Choose “Add row” from the menu.
  5. Give it the property name “DISABLEADVTSHORTCUTS”
  6. Give it the value “1”

This solved the issue I had. The only sad thing is: you will have to apply this change every build of the MSI…

More about that in another post.