
Implementing the Windows Forms Host Application
The Windows Forms host application uses an ElementHost object to host the WPF page on the form. The application handles the page's OnButtonClick event to receive the data from the form. The application also has a set of option buttons that you can use to modify the page's appearance. The following screen shot shows the rendered form.
Windows Presentation Foundation page hosted in a Windows Forms application
.png)
Creating the Project
To start the project:
Launch Visual Studio, and open the New Project dialog box.
Select C# Projects with the Windows Forms Application template.
Name the new project WFHost, and place it in the same top-level folder that contains the MyControls project. Click OK to create the project.
You also need to add a reference to the DLL that contains the WPF page:
Click the project name in Solution Explorer, and select Add Reference.
Click the Browse tab, and navigate to the folder that contains MyControls.dll.
Select MyControls.dll, and click OK to add the DLL to the list of references.
In Solution Explorer, add a reference to the WindowsFormsIntegration assembly, which is named WindowsFormsIntegration.dll.
Implementing the Form's User Interface Design
Open the Windows Forms Designer, and lay out the form as it appears in the illustration shown in the Implementing the Windows Forms Host Application:
Expand the default form to accommodate the controls and the WPF page.
Add a System.Windows.Forms..::.Panel control to the upper-right corner of the form to hold the WPF page.
Add six sets of System.Windows.Forms..::.RadioButton controls, as shown in the illustration.
Add five System.Windows.Forms..::.Label controls to the lower-right corner of the form, as shown in the illustration. These controls act as labels for the data returned by the WPF control.
Add a Label control to the right of each Label control added in the previous step. Set the Text property of each control to "". These controls display the data returned by the WPF control.
Add another Label control to serve as a title for the group of controls from the last two steps. Because this Label is intended to serve as the title for the group, make the font size two points larger than the controls in the group.
Initializing the Form
You generally implement the hosting code in the form's Load event handler. In the Windows Forms Designer, double-click the form to create a Load event handler method. The following code example includes the sample's Load event handler, a handler for the WPF page's Loaded event, and declarations for several global variables that are used later. Replace the code in Form1.cs with the following.
partial class Form1 : Form
{
private ElementHost ctrlHost;
private MyControls.Page1 wpfAddressCtrl;
System.Windows.FontWeight initFontWeight;
double initFontSize;
System.Windows.FontStyle initFontStyle;
System.Windows.Media.SolidColorBrush initBackBrush;
System.Windows.Media.SolidColorBrush initForeBrush;
FontFamily initFontFamily;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
ctrlHost = new ElementHost();
ctrlHost.Dock = DockStyle.Fill;
panel1.Controls.Add(ctrlHost);
wpfAddressCtrl = new MyControls.Page1();
wpfAddressCtrl.InitializeComponent();
ctrlHost.Child = wpfAddressCtrl;
wpfAddressCtrl.OnButtonClick +=
new MyControls.Page1.MyControlEventHandler(
avAddressCtrl_OnButtonClick);
wpfAddressCtrl.Loaded += new RoutedEventHandler(
avAddressCtrl_Loaded);
}
void avAddressCtrl_Loaded(object sender, EventArgs e)
{
initBackBrush = (SolidColorBrush)wpfAddressCtrl.MyControl_Background;
initForeBrush = wpfAddressCtrl.MyControl_Foreground;
initFontFamily = wpfAddressCtrl.MyControl_FontFamily;
initFontSize = wpfAddressCtrl.MyControl_FontSize;
initFontWeight = wpfAddressCtrl.MyControl_FontWeight;
initFontStyle = wpfAddressCtrl.MyControl_FontStyle;
}
The Form1_Load method in the preceding code example shows the general procedure for hosting a WPF control:
Create a new ElementHost object.
Set the control's Dock property to DockStyle..::.Fill.
Add the ElementHost control to the Panel control's Controls collection.
Create an instance of the WPF page.
Host the page on the form by assigning the page to the ElementHost control's Child property.
The remaining two lines in the Form1_Load method attach handlers to two page events:
OnButtonClick is a custom event that is fired by the page when the user clicks the OK or Cancel button. You handle the event to get the user's response and to collect any data that the user filled in.
Loaded is a standard event that is raised by a WPF page when it is fully loaded. The event is used here because the sample needs to initialize several global variables using properties from the page. At the time of the form's Load event, the page is not fully loaded and those values are still set to null. You need to wait until the page's Loaded event occurs before you can access those properties.
The Loaded event handler is shown in the preceding code example. The OnButtonClick handler is discussed in the next section.
Handling OnButtonClick
The OnButtonClick event occurs when the user clicks the OK or Cancel button.
The event handler checks the event argument's IsOK field to determine which button was clicked. The lbldata variables correspond to the invisible Label controls that were discussed earlier. If the user clicked the OK button, the data from the page's TextBox controls is assigned to the corresponding Label control. If the user clicked Cancel, the Text values are set to null.
Add the following code to Form1.cs. You can now compile and run the application.
void avAddressCtrl_OnButtonClick(
object sender,
MyControls.MyControlEventArgs args)
{
if (args.IsOK)
{
lblAddress.Text = "Street Address: " + args.MyStreetAddress;
lblCity.Text = "City: " + args.MyCity;
lblName.Text = "Name: " + args.MyName;
lblState.Text = "State: " + args.MyState;
lblZip.Text = "Zip: " + args.MyZip;
}
else
{
lblAddress.Text = "Street Address: ";
lblCity.Text = "City: ";
lblName.Text = "Name: ";
lblState.Text = "State: ";
lblZip.Text = "Zip: ";
}
}
Modifying the Windows Presentation Foundation Page's Appearance
The RadioButton controls on the left side of the form enable the user to change the WPF page's foreground and background colors as well as several font properties. The background color is exposed by the ElementHost object. The remaining properties are exposed as custom properties of the page.
Double-click the RadioButton controls on the form to create templates for the corresponding CheckedChanged event handlers. Extract the code from the following handlers, and add it to the corresponding handlers in Form1.cs.
private void radioBackgroundOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = initBackBrush;
}
private void radioBackgroundLightGreen_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightGreen);
}
private void radioBackgroundLightSalmon_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Background = new SolidColorBrush(Colors.LightSalmon);
}
private void radioForegroundOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = initForeBrush;
}
private void radioForegroundRed_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Red);
}
private void radioForegroundYellow_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_Foreground = new System.Windows.Media.SolidColorBrush(Colors.Yellow);
}
private void radioFamilyOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = initFontFamily;
}
private void radioFamilyTimes_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = new FontFamily("Times New Roman");
}
private void radioFamilyWingDings_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontFamily = new FontFamily("WingDings");
}
private void radioSizeOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = initFontSize;
}
private void radioSizeTen_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = 10;
}
private void radioSizeTwelve_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontSize = 12;
}
private void radioStyleOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontStyle = initFontStyle;
}
private void radioStyleItalic_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontStyle = System.Windows.FontStyles.Italic;
}
private void radioWeightOriginal_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontWeight = initFontWeight;
}
private void radioWeightBold_CheckedChanged(object sender, EventArgs e)
{
wpfAddressCtrl.MyControl_FontWeight = FontWeights.Bold;
}