Monday, February 25, 2008

Interop, Interop, and more Interop

Well, we're sure doing our fair share of WinForms and WPF interop! We've really jumped on the WPF bandwagon, but we really like the functionality of our application and aren't willing to give up major parts of it in order to go 'all' WPF.

For instance, our Syntax Editor control (from is only available currently as a WinForms control. Also, my management really likes the Infragistics Grid's functionality that we're using for our selection grid in our formula browser tab. In addition, we really like our tabbed MDI style of windowing, and our tool windows (pinnable tool windows like in VS2005).

Unfortunately, there are several ways in which WinForms doesn't play nice with WPF. Basically, the problem is that when WinForms draws on a window, it 'owns' that space on the screen. However, when WPF draws on a window, it is using DirectX compositing. This makes lots of things in WPF very nice, but in order to allow WinForms controls to 'live' on a WPF window, they must have total control over the space where they 'live'. This means that the WPF controls can not render 'on top of' the WinForms control. This is very well documented behavior and basically the only way the WPF team could figure out to make this work (as far as I can tell).

What does it mean for us? A whole lot of interop. Basically, we want to use WPF everywhere we can and would love to be able to use it for our whole application. Currently, we can't use it for the whole app, and so we must use it where we can and hope for the best later. However, tool windows have this neat 'auto-hide' feature with them. We really liked the WPF 'SandDock' tab & dock controls from DivElements. However, since our WinForms grid is in the main client area of our form layout, we couldn't use a WPF docking control, since when you drug the dockable windows around, or when they tried to 'flyout' from their 'auto-hide' position, they would do so UNDER the WinForms control! That sucks, but it's the only way it can reasonably work.

What's that mean? Our docking controls can only be WinForms controls until we get rid of all the WinForms controls that a flyout would want to fly over (and replace them with WPF equivalents). Now, since our docking and tabs controls (they're the same control for us, since we've switched to Actipro's UIStudio) have to be hosted in WinForms, and you can't have a WinForms host inside a WPF host inside a WinForms host (the interop facilities of WPF only allow WF inside WPF or WPF inside WF, but not 'double' nesting), we MUST use WinForms for our main application (this sucks since it means we lose a bunch of the nice features of WPF, like commands, command bindings, routed events, etc.).

This also means that EVERY WPF control in our app must be hosted inside a WPF element host (interop) control on the WinForms form.

Yuck. That's a hell of a lot of interop.

No comments: