After a little bit of experimentation, I would not recommend going down that path. First, whether you have to rewrite the application in WPF or not.
You're not the first person who has ever had to face the possibility of rewriting their UI. Microsoft's tools do not discourage you from placing application logic inside your forms (one could argue they encourage it!) When you do this, you will almost always end up coupling application logic with a specific UI. What do I mean? "Application logic" refers to all of the actions that your application takes that has nothing to do with the UI. This is concepts like "select a customer", "save a file", or "send an email". Another way to look at it is to imagine the application with a different UI; the things that it still does are probably application logic.
When you implement your application logic as part of your UI, you end up coupling application logic to that specific UI. For example, when you implement "select a customer" in a form, you will likely see it as "what happens when lstCustomers.SelectedIndex changes". This is suboptimal for a few reasons. The first is the problems it causes when you want to provide multiple ways to change the selection; what if you add a search dialog that presents an alternate mode of selection? This puts you in danger of duplicating code which has its own set of problems. The next big problem happens when you want to change something about your UI. Maybe you bought a third-party ListBox that has more features and you want to replace your current list box with it. If this third-party ListBox has different properties and events than the built-in ListBox, you'll have to rewrite your code. The same can happen if you decide to move from a ListBox to a ListView or some other control. Finally, it's hard to test application logic that's coupled with the UI. Automated tests can help discover bugs and validate that none exist, but it is very difficult to run automated tests against a UI.
The solution would take up too much discussion, but I can summarize. Software engineering has produced presentation model
patterns. These are techniques for separating application logic from the UI in a way that makes it possible to change the UI without changing application logic. A popular pattern for WinForms is the MVC, or Model-View-Controller, pattern. In this pattern, you tend to have three types of classes associated with a form. The Model is the data that the form will work with; you'll likely have many Model classes. The View is something that can display the data; this is the form itself. The Controller contains all of the application logic for a particular View. I'd love to demonstrate, so if you're curious please ask.
Why the heck did I spend 3 paragraphs off-topic like this?
If you were using a presentation model pattern it would be much easier to switch from WinForms to WPF. (This is ignoring the fact that you have no experience with WPF; it's very different.) With a presentation model pattern, "select a customer" would expect the UI to figure out the UI details and provide the selected customer to a controller or other application logic class. This means you can replace the UI with anything that knows how to send the selected customer to the application logic. I've used these patterns to make applications that have both a scriptable console UI and a GUI with great success.
Fine. But what about hosting WPF content in WinForms?
It's doable, but I wouldn't recommend it. First theory, then practice.
To host WPF content in WinForms, you must start by creating a WPF UserControl with the content you want to host. The ElementHost
control (look for the "WPF Interoperability" tab in the toolbox) is a Windows Forms control that can host WPF content. After you place the element host on the form, you set its Child
property to an instance of the WPF user control you created. The designer helps you with this process via smart tags. After you tell the element host what to host, you can work with the hosted content as if it were a control in Windows Forms.
In this example, I created a FadingTextBox
that adds a FadeOut()
to the WPF text box. I hosted this in a user control named FadingTextBoxContainer
and provided a couple of properties to make it easier to use. The ElementHost is configured to have a transparent background in the hopes that when the textbox fades the whole thing will be transparent.
Here's my opinions.
- It's very shaky in the VS 2008 designer. Veterans of hosting ActiveX controls in WinForms won't be surprised at this. Once I dropped the ElementHost, the designer became unreliable. Every time I build the project, the designer quits loading until I close VS and delete some temporary files it creates. If you rely heavily on the designer, you'll have a hard time using this technique. It's much better in VS2010; I am leaving this point here because many people still use VS 2008.
- I have some application stability concerns. The application threw an exception when I closed it a couple of times. I have no idea if this is a fluke or something to be concerned about; you should test extensively if you use it.
- It's still not true transparency. No matter how you slice it, ElementHost is still a Windows Forms control and still subject to the halfway-supported transparency. I'm pleased to see that it works against an image, but as the example shows you can't see controls it overlaps. WPF handles this just fine, in WinForms it takes monumental effort. If you need overlapping, it's still a dead-end.
In short, I think it's shoving a square peg into a round hole. I can't name an application built on GDI or WinForms that uses animation or transparency effectively. It's probably best to just do without the fade.
My original attachment was for VS 2008, I added a VS 2010 project.