Professional VB 2005 with .NET 3.0 (Programmer to Programmer)
In the case of WPF hosting Windows Forms controls, you might choose to do this if you have an existing application that relies on certain controls that have not yet been implemented in WPF. For example, the following list of controls are not supported in WPF in .NET 3.0:
-
BindingNavigator
-
DateTimePicker
-
FontDialog
-
LinkLable
-
NotifyIcon
-
PrintPreviewDialog
-
ColorDialog
-
ErrorProvider
-
HelpProvider
-
MaskedTextBox
-
PageSetupDialog
-
PropertyGrid
-
DataGridView
-
FolderBrowserDialog
-
ImageList
-
MonthCalendar
-
PrintDocument
In addition to this list of controls that aren’t directly supported, still other controls may behave differently in this release. For example, the ComboBox control in WPF doesn’t provide built-in support for AutoComplete. In other cases, such as the HelpProvider (F1 Help), a control isn’t supported because the WPF provides an alternative implementation. Even if you have an application in which the existing user interface takes advantage of one of the preceding control’s features, it is understandable that you might be interested in integrating your existing investment in the next version of your application.
As noted, this isn’t an ideal scenario, and it’s likely that with the next release of Visual Studio and its companion .NET upgrade, tentatively named .NET 3.5, the control you need will be available. However, in this initial WPF release there is a real possibility that if you have heavily leveraged a DataGridView control, you will want to reuse your existing control as opposed to attempting to design a custom replacement.
To walk through this process, create a new WPF Windows Application called WPFInterop. This process is described in Chapter 17, so once you have that application, go straight back to the File menu and use the Add option to add a second project to this solution. This time, pick a Windows Control Library called EmbeddedControl. Again, Visual Studio will execute the template to create a new project. At this point you will have access to a new control called UserControl1. Go to the designer for this new user control and add a Button and a DataGridView control to the design surface, as shown in Figure 18-4.
Figure 18-4 shows one way to arrange these controls. For the purposes of this demonstration, these controls are static so you can add the columns shown in the grid manually through Visual Studio. Resize the grid to fit within the display area of your user control. This demonstration focuses on display characteristics, so there is no need to edit the default code-behind or provide an action for the click event of the button.
Having created a new UserControl1, build the project so that the EmbeddedControl has been compiled, and then close this window. The next step is to update your WPF project with the appropriate references. Three references need to be added. From the Project Settings window, select the References tab. Add a reference to the .NET assembly System.Windows.Forms. Then, using the Browse button, navigate to the Reference Assemblies directory mentioned earlier in this chapter. Go to the .NET 3.0 folder to add a reference to WindowsFormIntegration.dll. Finally, add a new project reference to the EmbeddedControl project. After adding all three references, close the Project Settings window and recompile the project.
Having created a new user control and added the references, open the Window1.xaml file that’s created with this template. In that XAML file you’ll see the “Window” declaration. This declaration in Visual Studio imports two namespaces, as discussed in Chapter 17. You need to add two additional references. The first is for the Windows Forms namespace, which you should alias “wf.” In the code block that follows, this namespace references System.Windows.Forms and includes a second attribute, assembly, that references the name of the assembly file:
<Window x: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wf ="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:uc ="clr-namespace:EmbeddedControl;assembly=EmbeddedControl" Title="WPFInterop" Height="300" Width="300">
The second imported namespace is used to reference your EmbeddedControl project. In this case, alias this namespace as “uc.” This reference to your local project follows the same format as the reference to the System.Windows.Forms namespace. The full reference is shown in the preceding code block.
After adding these references, switch to design view and add a button to the upper-right corner of the display. This button will illustrate the fact that although WPF and Windows Forms share the same control, the display of that control is very different. After adding this control, return to the XAML view within Visual Studio (see Figure 18-5). Add the following lines to the default grid after the declaration of the button control:
<WindowsFormsHost Margin="0,90,0,0"> <uc:UserControl1 x:Name="ButtonGrid"></uc:UserControl1> </WindowsFormsHost>
These three lines declare a new WindowsFormsHost control and place it 90 pixels below the top edge of your grid. The remaining sides of the control are bound to your window’s borders. Within this WindowsFormsHost control is an instance of UserControl1 named ButtonGrid.
Until you switch from the XAML window back to your display, you probably won’t see that the Visual Studio designer has a problem interpreting this XAML. As shown in Figure 18-5, the design window now shows a very useful “Whoops!” screen. This doesn’t mean that your application won’t compile and run, but that the designer can’t interpret it.
In case you have a compilation problem or are uncertain of the contents of the XAML file shown in Figure 18-5, the full Window1.xaml file is shown in the following code block:
<Window x: xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:wf ="clr-namespace:System.Windows.Forms;assembly=System.Windows.Forms" xmlns:uc ="clr-namespace:EmbeddedControl;assembly=EmbeddedControl" Title="WPFInterop" Height="300" Width="300"> <Grid> <Button Height="23" HorizontalAlignment="Left" Margin="29,43,0,0" Name="Button1" VerticalAlignment="Top" Width="75">Button</Button> <WindowsFormsHost Margin="0,90,0,0"> <uc:UserControl1 x:Name="ButtonGrid"></uc:UserControl1> </WindowsFormsHost> </Grid> </Window>
At this point you can run the application. You should see the results shown in Figure 18-6.
The first item that should jump out at you is that the EmbeddedControl has lost the Windows XP visual styling. Referring back to Figure 18-6, you can confirm that this styling was present in the designer for this control. However, the integration library has limitations, much like those found in the new design tools you are using in Visual Studio 2005. To resolve this issue, go to the code-behind file for your Window1.xaml file, Window1.xaml.vb. Within the New method, either before or after the call to InitializeComponent(), add the following line of code:
System.Windows.Forms.Application.EnableVisualStyles()
Rerun the application. The visual styling is now correct. However, you should also be able to see that the way WPF and Windows Forms renders this style on a similar control is still different. Thus, you’ll want to ensure that you minimize the number of similar controls you reference on different sides of the host boundary. In this case, you simply needed to manually reset the display settings for your control to indicate that it should use the XP styling; however, this visual provides an excellent introduction to the next topic.
Категории