The blog of dlaa.me

Revisiting the Code Not Taken [Updated analysis of two ways to create a full-size Popup in Silverlight]

Earlier this year I wrote about two approaches for creating a Popup to overlay the entire Silverlight plug-in. I began by showing the technique most people start with and then demonstrated a rather surprising side-effect of that approach. Here's the relevant screen shot:

A quirk of handling the Resized event on Silverlight 3

Unless you've read the original post, the problem may not be obvious - here's what I said at the time:

But something is still wrong in the image above... If you look carefully, you can see that the browser zoom is set at 50% - yet somehow the image is sized correctly despite us not doing any work to handle the browser's zoom setting yet. How can that be? Hold on, Sherlock, there's another clue in the image: look at the size of the buttons. Yeah, those buttons are not the size they should be for the 50% zoom setting that's active (refer back to the previous image if you don't believe me). Those buttons are at the 100% size - wha??

Aside: Hey, don't feel bad, it weirded me out, too. :)

It turns out that when you attach an event handler to the Resized event, Silverlight 3 disables its support for browser zoom. The reason being that Silverlight 3 assumes the application has chosen to handle that event because it wants full control over the zoom experience (via ZoomFactor and Zoomed, perhaps). Now that's really kind of thoughtful of it and everything - but in this case it's not what we want. In fact, that behavior introduces a somewhat jarring experience because the graphics visibly snap between 50% and 100% as the Resized event handler is attached and detached.

 

Well, that was then and this is now: I'm pleased to report that Silverlight 4 does not have the troublesome "hooking Resized disables browser zoom" behavior! Consequently, projects targeting Silverlight 4 are free to hook the Resized event without worrying that their browser zoom behavior will be compromised. Yay!

Aside: Of course, projects targeting Silverlight 3 (or previously compiled for it) and running on Silverlight 4 will continue to see the same Silverlight 3 behavior. This is because Silverlight 4 maintains backward compatibility with previous versions to avoid "breaking the web" when a new version comes out. Specifically, applications written for version N of Silverlight are expected to run the same on version N+M - even when there have been changes to the relevant functionality after version N was released.

 

Now that it's possible, I've updated the sample to demonstrate the desired behavior on Silverlight 4 by making the following tweak to the Application.Current.Host.Content portions:

EventHandler rootResized = delegate
{
    child.Width = root.ActualWidth / root.ZoomFactor;
    child.Height = root.ActualHeight / root.ZoomFactor;
};

Everything else remains the same, and now the Application.Current.Host.Content approach works almost as well as the Application.Current.RootVisual approach I recommended previously (though the image still flickers when changing the browser zoom):

Correctly sizing the Popup to cover the plug-in

 

With both approaches nearly equivalent on Silverlight 4, you might wonder if I'd like to revise my earlier recommendation to prefer the RootVisual-based approach... Well, I would not! I still feel the RootVisual approach is simpler and easier to understand, so I'll continue to use it myself and recommend it to others. However, there's no longer a compelling reason not to use the Content-based approach, so I'm cool if that's your personal preference. :)

 

[Click here to download the complete source code for the original sample (a Visual Studio 2010 (Beta 2) project targeting Silverlight 3)]

[Click here to download the complete source code for the new sample (a Visual Studio 2010 project targeting Silverlight 4)]