Host Winforms - based UserControl Apps in Internet Explorer
By Peter A. Bromberg, Ph.D.
Printer - Friendly Version
Peter Bromberg

Some time ago, I wrote an article about autodeployment of .NET assemblies via HTTP and mentioned that some of my developer friends had returned from Redmond screaming “The browser is dead! The Browser is Dead”.



This article builds on the previous one, only this time we will focus on how to put application logic into Windows Forms UserControls and host them directly in the browser. I have put this article in the form of a tutorial, because it so closely parallels the tutorials for populating an updateable DataGrid on a regular .NET Windows Form. In order to complete this tutorial, you will need:

  • Access to a server with the Northwind SQL Server sample database.
  • The .NET Framework installed on the client and the server.

The tutorial is split into several of smaller pieces:


• Creating the Windows Form UserControl.
• Creating and configuring the dataset you will bind the form against. This includes creating a query that populates the dataset from the database.
• Adding the DataGrid control to the form and binding it to data.
• Add code to fill the dataset.
• Add code that sends dataset changes back to the database.
When you have finished the tutorial, you will have a Winforms -based UserControl that can be hosted from your web site in clients' Internet Explorer 5.5 or higher browsers.

Creating the Project and Form

The first step is to create a Windows UserControl

To create the project and form
1. From the File menu, point to New, and then choose Project.
2. In the Project Types pane, choose Visual C# Projects, and then in the Templates pane, choose Windows Control Library.
3. If you already have a solution open, select Close Solution.
4. Assign a name to the project that will be unique and will conform to the naming conventions you use. For example, you might name this project Ctrl1.
5. When you have assigned a name and specified a new solution, click OK.
Visual Studio creates a new project and displays a new form in the Windows Form Designer. Note that the UserControl1 class has a Design surface just like a Winforms project.


Creating and Configuring a Dataset

As with most data-access scenarios in Windows Forms applications, you'll be working with a dataset. A dataset is a container — a cache — that holds the records you are interested in working with. In this tutorial, you will add a dataset to the form. However, because the dataset does not already exist, we will not manually add it to the form. Instead, we will perform the following set of steps:
• Create a data adapter using a wizard. The adapter contains SQL statements used to read and write database information. The wizard helps you define the SQL statements you need. If necessary, the wizard also creates a connection to the database.
• Generate the dataset schema. In this process, we will have Visual Studio create a new typed dataset class based on the tables and columns you are accessing. When you generate the dataset class, you will also add an instance of it to the form.

It is important that you follow all the procedures in this section. Otherwise your User control form will not have the dataset that you will be using in subsequent parts of the tutorial.


Configuring a Data Connection and Data Adapter


To begin, we create a data adapter that contains the SQL statement used to populate the dataset later. As part of this process, we define a connection to access a database. We configure the data adapter using a wizard, which makes it easy to create the SQL statements we need for data access.

Note: When the wizard is done, you must continue to the next section in order to generate a dataset and complete the data access portion of your form.

To create the data connection and data adapter
1. From the Data tab of the Toolbox, drag an SqlDataAdapter object onto the form.
The Data Adapter Configuration Wizard starts, which will help you create both the connection and the adapter.
2. In the wizard, do the following:
a. In the second pane, create or choose a connection pointing to the SQL Server Northwind database.
b. In the third pane, specify that you want to use an SQL statement to access the database.
c. In the fourth pane, create the following SQL statement:
SELECT * FROM customers

For assistance building SQL statements, click Query Builder to launch the Query Builder.

3. The wizard creates a connection (sqlConnection1) containing information about how to access your database. You will also have a data adapter (sqlDataAdapter1) that contains a query defining what table and columns in the database you want to access.
4. After the wizard is complete, generate the dataset based on the SQL query that you created during this procedure.


Creating the Dataset


After we have established the means to connect to the database and specified the information we want (via the SQL command in the data adapter), we can have Visual Studio create a dataset. Visual Studio can generate the dataset automatically based on the query we specified for the data adapter. The dataset is an instance of the DataSet class based on a corresponding XML Schema (.xsd file) that describes the class's elements (table, columns, and constraints).


To generate a dataset


1. From the Data menu, choose Generate DataSet.
Tip If you do not see the Data menu, click in the form; the form must have focus for the menu to appear.
The Generate Dataset dialog box is displayed.
2. Select the New option and name the dataset dsCustomers.
In the list under Choose which table(s) to add to the dataset, the customers table should be selected.
3. Make sure Add this dataset to the designer is checked, and then click OK.
Visual Studio generates a typed dataset class (dsCustomers) and a schema that defines the dataset. You will see the new schema (dsCustomers.xsd) in Solution Explorer.
Tip In Solution Explorer, click Show All Files to see that the schema file's dependent .cs file, which contains the code the defines your new dataset class.
Finally, Visual Studio adds an instance of the new dataset class (DsCustomers) to the form.
At this point we have set up everything we need in order to get information out of the database and into a dataset. We are ready to create a form that will display the data.


Adding a DataGrid Control to Display the Data

In this tutorial, you will add a single control — a DataGrid control — that can display all the records from the dataset at the same time. An alternative would be to use individual controls such as text boxes to display one record at a time. That strategy then requires you to add navigation to the form. For simplicity, therefore, we will use a data grid.
The data grid must be bound to the dataset in order to display the data.


To add a bound DataGrid control to the form surface


1. If you have not already done so, switch to the usercontrol designer view by clicking the tab at the top of the current window.
2. From the Windows Forms tab of the Toolbox, drag a DataGrid control onto the form.
3. Press F4 to display the Properties window.
4. In the DataSource property, select DsCustomers1 as the data source. (Do not choose DsCustomers1.Customers.)
5. In the DataMember property, select customers.
Setting these two properties binds the customers data table in the DsCustomers1 dataset to the grid.
6. Resize the grid so you can see all the columns. Change its height so you will be able to see several customer records.

Populating the DataGrid Control

Although the data grid is bound to the dataset you created, the dataset itself is not automatically filled in. Instead, you must fill the dataset yourself by calling a data adapter method.

To populate the DataGrid control

1. From the Windows Forms tab of the Toolbox, drag a Button control onto the form.
2. Name the button btnLoad and change the caption by setting its Text property to "Load".
3. Double-click the button to create an event-handling method for its Click event.
4. In the method, clear the dataset you created, and then call the data adapter's Fill method, passing it the dataset you want to fill.
The following example shows what the complete method will look like:

private void btnLoad_Click(object sender, System.EventArgs e)
{
dsCustomers1.Clear();
sqlDataAdapter1.Fill(dsCustomers1);
}

What this does is that every time users click the "Load" button, the DataSet is cleared and then reloaded from the server.

Updating the Database

When users make a change in the grid, the control automatically saves the updated record in the dataset. In Windows Forms, the data-binding architecture writes the values of data-bound controls to the data rows they are bound to.
However, when you work with a dataset, updates require two stages. After the data is in the dataset, you still have to send it from the dataset to the database. The data adapter can do this with its Update method, which examines every record in the specified data table in the dataset and, if a record has changed, sends the appropriate Update, Insert, or Delete command to the database automatically. In this example, you will add a button to the form that users can press when they want to send their updates to the database.

To update the database

1. From the Windows Forms tab of the Toolbox, drag a Button control onto the form.
2. Name the button btnUpdate and change the caption by setting its Text property to Save Changes in Database.
3. Double-click the button to create an event-handling method for its Click event.
4. In the method, call the data adapter's Update method, passing it the dataset containing the updates you want to send to the database. Use the MessageBox object to display confirmation text.
The following example shows what the complete method will look like:

private void btnUpdate_Click(object sender, System.EventArgs e)
{
sqlDataAdapter1.Update(dscustomers1);
MessageBox.Show("Database updated!");
}


Testing

You can now test your control to make sure it displays Customers data in the grid and that users can make updates.


To test the control

1. Add a new Windows Application project to your solution. Customize the Toolbox by right clicking and choosing “Customize Toolbox”. Navigate to the “.NET Framework Components” tab and choose BROWSE. Find the Ctr1.dll in the bin/debug directory of your User Control project and select it. Click “Open” and then “OK”. Your control icon should now appear on the Toolbox. Drag an instance of the control to your Main form in your Windows Application. Run the project. You should be able to fully debug the project, including the UserControl.
2. Press F5 to run the form.
3. When the form is displayed, click the Load button.
A list of customers is displayed in the grid.
4. Make a change in a record in the grid.
When you move to another record in the grid, the change is preserved. Make a mental note of your change.
5. Click the Load button again.
This reloads the dataset from the database and refreshes the grid. Notice that the change you made in Step 3 was not preserved — because you did not save changes from the dataset to the database.
6. Make a change in a record in the grid again.
7. Click the Save Changes in Database button.
You will see the message box displayed, but there is no change in the grid.
8. Click the Load button once more to re-load data from the database.
This time, the change you made in Step 5 is preserved, because the data was saved in the database.

Hosting your control in Internet Explorer from your web site

There are four steps involved in getting a Windows Forms Control hosted in Internet Explorer:
1. Create the Control
2. Configure Code Access Permissions
3. Create an HTML document with the required object tag
4. Create the virtual directory, copy files and set permissions.


Configuring code access permissions is done in Internet Explorer by choosing Tools/Options, selecting the Security Tab, select the Trusted Sites icon, click the “Sites” button, and add the site where the control is hosted. Then click OK to commit your changes.

The object tag construction is very simple:


<object id="simpleControl1"
classid="http://localhost/Simplecontrol/bin/Ctrl1.dll#Ctrl1.UserControl1"
>
</object>

Note the first part of the classid attribute must be the real http address of the dll. Then there is a “#” sign, followed by the fully qualified namespace and class name of your control. That’s all there is to it.

You can also write client – side script functions to access properties and methods of your control by using param elements ( e.g. , <param name=”color” value =”pink” >) within the object tag. In this case, all our functionality is already built onto the visible control surface, so this will not be necessary.

Your page is now ready to load!

You can try our live sample here:

Note I have left out an insert option because we don’t want people adding huge numbers of records to our poor old Northwind sample database. However, you will see from the values in the Datagrid that people have already been happily updating the existing Customers table records! But this is really the most simple of examples. There are a number of details about configuration files and how apps get updated based on assembly versioning and other items I’ve left out for the sake of simplicity.

If the application doesn’t function after you have updated your Trusted Sites, you may need to alter your security policy by using the Microsoft .NET Framework Wizards/ Trust an Assembly Control Panel applet.

Specifically:

Control Panel/
  Administrative Tools/
	.NET Framework Configuration/
		Configure Code Access Security Policy/
			Adjust Zone Security/

CLick the GREEN "Trusted Sites icon".
Move the slider up to "Full Trust" (very top position).
Click "NEXT" 
Click "FINISH"

If you are interested in how the CLR determines security policy with Internet Explorer, you may find the following KB helpful: http://support.microsoft.com/default.aspx?scid=kb;en-us;311301&FR=1 .

You can create entire applications with WinForms usercontrols that have multiple forms and all different types of controls, and host them on your Intranet or even over the internet. When a newer assembly version is deployed to your server, the runtime checks the version against the cached version and will automatically update the assembly.

Note that if you decide to download the sample solution from the link below, the sqlConnection string, which can be found in the source code, is""data source=(local);initial catalog=Northwind;user id=sa;password=;" and may need to be changed.


Peter Bromberg is a C# MVP, MCP, and .NET consultant who has worked in the banking and financial industry for 20 years. He has architected and developed web - based corporate distributed application solutions since 1995, and focuses exclusively on the .NET Platform.