Did you know that there's no grid-like control in WPF 1.0? This post will show you how to get around that limitation. But first, may I say that the recently-released Orcas September CTP bits offers a great improvement at design-time when writing WPF applications. Instead of those three clunky tabs for .xaml, [Designer], and .xaml.cs that we had back in the June CTP, you now get the first glimpse of Microsoft's new cool “Split” view, which will become a part of ASP.NET in the Orcas timeframe!
Very cool stuff. Modifying the designer surface updates the underlying XAML immediately. But modifying the XAML requires that you click the design surface before the update takes place, the same as how Dreamweaver's split view works. Still very useful. The up-down thing between the two tabs swaps their place, and the horizontal vs vertical split things are found on the right. You can of course make either surface larger or smaller by dragging the “thumb” in the middle.
So anyway, on with the topic at hand: how to use “Crossbow” with the September CTP bits. Crossbow lets you use old-school WinForms controls in WPF with the WindowsFormsHost control, and also the other way around, using WPF controls in a WinForms app using the ElementHost control. As mentioned in the picture above, you have to add references to these two assemblies:
System.Windows.Forms (since that refers to the controls we're building a wrapper for.)
WindowsFormsIntegration (which holds the WindowsFormsHost control we'll use.)
With those two references in place, you can now use the special WPF control called WindowsFormsHost (found in the System.Windows.Forms.Integration namespace) as a kind of “placeholder” for a single WinForms control. This opens up an area where the WinForms control gets rendered as part of WPF. Why would you want to do such a thing? If you have invested in creating a WinForms app then you can incrementally change over to WPF. Plus some WinForms controls are not yet found over in WPF. For instance, there is no control in WPF that acts like the very popular DataGrid or DataGridView. So this example shows how you can add one to a WPF app using 100% declarative code.
If you've used Crossbow in the past, This build changes a little the way you implement the WindowsFormsHost. Now instead of the <Mapping> tags you previously had to put at the top of the XAML, that's all handled as special namespce syntax in the <Window> or <Canvas> root element. As shown in the sample snippet of code in the image above, you have to add these two namespace declaration attributes to that element:
And then you can make use of the new namespace and add in a WindowsFormsHost, and a single WinForms control inside, like this:
<wfi:WindowsFormsHost Height="100" Width="200">
Intellisense won't do anything for you with this build, but at least the declarative code will work as expected. And when you click on the designer surface, you should see the sample DataGrid jump to life, filling up that 200x100 pixel area. In your code-beside you can then programmatically reference the WinForms control just like you normally would, for instance after InitializeComponent() in the constructor you could use these few lines to show some simple content in the DataGrid:
DataTable dt = new DataTable();
myDG.DataSource = dt;
And then the end result would look like this:
The checkbox is a WPF control, and of course the DataGrid is a WinForms control. In this sort of way it's very easy to keep the rich functionality of old WinForms controls, and add in new slick animation and other WPF features in your apps. You can wire up events and reference all the objects on the page with the same code you normally would, so altogether it “just works”.
For more information about Crossbow, check out Mike Hender's blog.