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.
|