Introduction
Windows Forms applications can be effective in hosting electronic forms. Microsoft Office InfoPath was developed with Microsoft Office 2003, and is now an integral part of the Microsoft Office System. Its user interface is relatively straightforward, where the form designer usually picks a Layout “Table with a Title” in order to contain tables within that outer table. This establishes the look and feel. Then, controls can be dragged and dropped onto the surface. Below is a very basic example of a form:
The first part added was a “Table with a Title”. Directly underneath, where sample text lay, I placed a section object. As the cursor blinked on that section, I went back to layout and chose “custom table”, where I inserted five columns and three rows. And so on. The purpose of this article is to explain how an electronic form can be loaded onto a Windows Form interface. I will assume that the reader has a downloaded and workable copy of Visual Studio 2008 SP 1, and that the user downloads a trial copy of InfoPath 2007. It is well worth the time spent. The form that will be loaded in our example is a downloaded Status Report form.
It should be clear that the form will be embedded in the Windows Form, and that the Windows Form will host the InfoPath 2007 application. To host an InfoPath Form in a Windows application, you have to use the InfoPath FormContent
control. So, the first thing to do is fire up InfoPath 2007 and either use one of the templates or create a simple form similar to that of the above. Save that form and publish it to a network location, say, c:\temp\Status.xsn. Finish the publishing wizard and close InfoPath.
Now, fire up Visual Studio 2008 and create a Windows Forms application in C#. Right-click the toolbox and select “Choose items”. Browse to the %program files\Microsoft Office\Office 12 directory. Find Microsoft.Office.InfoPath.FormControl.dll and double-click it. Click OK in the Choose Toolbox Items dialog. Drag the FormControl
control to the Windows Form. Underneath the FormControl
, drag and drop a button, which will call “Load Form”, a label,, which we’ll call “Load From”, and a text box control underneath the label.
Now the easiest part to get out of the way is the button event handler. So we double-click the button, Load Form, and insert the event handler:
formControl1.NewFromFormTemplate(@"c:\temp\status.xsn");
Now you’ll wire the form to accept the Submit event from the embedded form. Add the following after the partial class declaration to add the interface to your form:
Microsoft.Office.Interop.InfoPath.ISubmitToHostEventHandler
This interface declaration comes right after the Form. Right-click it and select “Implement interface”. Here is the entire file:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Xml;
using System.Xml.XPath;
using Microsoft.Office.InfoPath;
using System.Text;
using System.Windows.Forms;
namespace EmbeddedForm
{
public partial class Form1 : Form,
Microsoft.Office.Interop.InfoPath.ISubmitToHostEventHandler
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
formControl1.NewFromFormTemplate(@"c:\temp\status.xsn");
}
#region ISubmitToHostEventHandler Members
public int SubmitToHostEventHandler(object sender,
string adapterName, out string errorMessage)
{
XPathNavigator xnav= formControl1.XmlForm.MainDataSource.CreateNavigator();
xnav = xnav.SelectSingleNode("/my:myFields/my:SomeOtherValue",
formControl1.XmlForm.NamespaceManager);
textBox1.Text = xnav.InnerXml;
errorMessage = "";
return 1;
}
#endregion
private void Form1_Load(object sender, EventArgs e)
{
formControl1.SetSubmitToHostEventHandler(this);
}
}
}
Notice that I imported other namespaces, like the XML
namespace and the InfoPath
namespace. InfoPath is XML-centric. Here is the Designer form code:
namespace EmbeddedForm
{
partial class Form1
{
private System.ComponentModel.IContainer components = null;
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
private void InitializeComponent()
{
System.ComponentModel.ComponentResourceManager resources =
new System.ComponentModel.ComponentResourceManager(typeof(Form1));
this.formControl1 = new Microsoft.Office.InfoPath.FormControl();
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.textBox1 = new System.Windows.Forms.TextBox();
((System.ComponentModel.ISupportInitialize)(this.formControl1)).BeginInit();
this.SuspendLayout();
this.formControl1.Enabled = true;
this.formControl1.Location = new System.Drawing.Point(12, 33);
this.formControl1.Name = "formControl1";
this.formControl1.OcxState = ((System.Windows.Forms.AxHost.State)
(resources.GetObject("formControl1.OcxState")));
this.formControl1.Size = new System.Drawing.Size(558, 434);
this.formControl1.TabIndex = 0;
this.button1.Location = new System.Drawing.Point(56, 500);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(75, 23);
this.button1.TabIndex = 1;
this.button1.Text = "Load Form";
this.button1.UseVisualStyleBackColor = true;
this.button1.Click += new System.EventHandler(this.button1_Click);
this.label1.AutoSize = true;
this.label1.Location = new System.Drawing.Point(365, 485);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(57, 13);
this.label1.TabIndex = 2;
this.label1.Text = "Load From";
this.textBox1.Location = new System.Drawing.Point(321, 516);
this.textBox1.Name = "textBox1";
this.textBox1.Size = new System.Drawing.Size(100, 20);
this.textBox1.TabIndex = 3;
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(595, 548);
this.Controls.Add(this.textBox1);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.Controls.Add(this.formControl1);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load);
((System.ComponentModel.ISupportInitialize)(this.formControl1)).EndInit();
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private Microsoft.Office.InfoPath.FormControl formControl1;
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
private System.Windows.Forms.TextBox textBox1;
}
}
We now build the solution, and then type the path to the InfoPath 2007 form: @"C:\temp\status.xsn".
When downloading the zip files, extract them into a named Projects folder. If you don’t use the “Status Report” form, then remember to change the path parameter in the source code. Make a temp folder after you download InfoPath 2007, and place one of the sample forms in that temp subfolder. InfoPath form files have a .xsn file extension.