Vertical Airspace

Sometimes when you’re working in WPF, you’ll come across an issue that just stops you dead in your tracks. The kind of issue that makes you wonder how in the hell this problem can still exist in version 4+ of a product. Well, today I’m going to talk about one of those, namely Airspace.

Odds are that you haven’t heard of airspace, it’s one of those weird issues that you don’t need to know about until you need to know about it. Here’s the best simple explanation I could find about it. Basically, the problem rears its head when you’re trying to host a WinForms control inside a WPF hosting window or vice-versa. What happens is that the WinForms control has to be on the topmost layer, no matter what. Even if you try to change the z-index of another control, the WinForms control will always be on top. In reality, this means you can’t show any modal dialogs on top of any WinForms controls.

OK, OK, I know, you’re probably thinking this won’t affect me, it doesn’t really matter, I never use any WinForms controls inside my super-shiny-awesome WPF apps. Welp, maybe you’re right, but maybe, just maybe you’re going to use the WebBrowser control!

horrified

The WebBrowser control is a WinForms control (they don’t like to publicize that fact) that’s basically been wrapped for WPF.

I found this out myself just a few weeks ago, when I tried to throw some Markdown preview into my application. I thought the easiest thing to do would be to just throw in a standard-issue WebBrowser and render to it. Little did I know the rabbit hole I was about to fall into. All worked great until I tried to put my dialog on top of the browser and it just didn’t. I can’t show the original example here, but I threw together a quick example of what happened.

airspacebad

The highlighted box above has a bunch of standard WPF controls, while the WebBrowser takes up most of the space. When I hit the settings button it’s supposed to show a dialog on top of the entire window and darken the background a little bit. As you can see, the dialog can’t be seen as it’s covered by the WebBrowser but you can see the top part has the darkened background.

I did a little searching on how to fix the problem, thinking it would be an easy fix, which led me here and to a false solution here which stated it would be fixed in WPF 4.5, but it never came to be. I guess the official solution is waaaaay more complicated than it looks. Some people recommended just hiding the WinForms control when showing a dialog, which, in theory would work, but is not very subtle, especially if it’s not a full-screen dialog.

I went further into the internet and came across both CEFSharp and Awesomium which both seem super powerful and useful, but also over-powered for what I needed. Add to the fact that both have a lot of JS native code calls to do the more complicated parts, and I was starting to get a little scared off.

Finally, after some thinking, I decided I should try and fix the problem that I’m actually having, that I can’t show a dialog on top, so I came up with a pretty hacky little workaround that I wanted to share with everyone.

AirspacePanel aims to fix this problem by allowing you to host any content you like inside of it, and swapping out the content for a screenshot of the content when you need to place a modal dialog on top of it. This swap is done by using the dependency property FixAirspace. Here’s an example –

xmlns:asf="clr-namespace:AirspaceFixer;assembly=AirspaceFixer"

<asf:AirspacePanel FixAirspace="{Binding FixAirspace}">
    <WebBrowser x:Name="Browser" />
</asf:AirspacePanel>

The entire project (in all it’s tiny glory) is available here on github which contains a sample project if you just want to see it. Here’s the screenshot from above all fixed with AirspacePanel.

airspacegood

You can also find it in Nuget through Visual Studio.

If anyone does give it a shot, let me know what you think. For me, it fixes a small annoyance, but I’d like to hear some other opinions.

Advertisements