Introduction
This article demonstrates how to load controls and attach event handlers inside an ASP.NET 2.0 Wizard control at run-time. The demo is a simple quiz program that prompts users to enter how many questions they would like to load into the Wizard control. The number of questions entered determines the WizardSteps to create at run-time and how many set of controls to create for the Wizard control.
The demo will display an Image control that displays a flag, followed by a RadioButtonList with three choices for the user to select. When a user clicks on the Finish button, the program calculates the total correct answers. The demo is developed using ASP.NET 2.0 with data stored in a SQL Server 2005 table.
Fig. 1 below prompts the user for the number of questions to load in the Wizard control.

Fig. 2 below shows the wizard loaded with five questions. Each question (i.e., a WizardStep) is loaded with an Image control and a RadioButtonList with pre-defined choices. The image and RadioButtonList choices are stored in a SQL Server table.

The user makes the proper selection in the RadioButtonList and clicks the Next button to move onto the next WizardStep. The user can also click on the SideBar and navigate to other WizardSteps in a non-sequential manner.
Fig. 3 below shows how when the Finish button is clicked, a score is calculated by looping through prior user selections in the Wizard control.

Easy enough….now let’s talk about the code behind these screens. Fig. 1 prompts users for an input, and uses a Server.Transfer() to move to the screen in Fig. 2. In the design screen of Fig. 2, only a PlaceHolder control and a Label control are needed. The PlaceHolder control is used to host the Wizard control created at run-time. The Label control is used to display the calculated score. The following code is implemented in the Page_Load event of Fig. 2.
using System;
using System.Data;
using System.Data.SqlClient;
using System.Configuration;
using System.Collections;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using Microsoft.ApplicationBlocks.Data;
using System.ComponentModel;
public partial class TestWizardControl1 : System.Web.UI.Page
{
string thisConnectionString =
ConfigurationManager.ConnectionStrings[
"PracticeDataConnectionString"].ConnectionString;
System.Data.DataSet thisDataSet = new System.Data.DataSet();
protected void Page_Load(object sender, EventArgs e)
{
Wizard WizardControl = new Wizard();
WizardControl.Height = Unit.Pixel(150);
WizardControl.Width = Unit.Pixel(200);
WizardControl.Style["Top"] = "111px";
WizardControl.Style["Left"] = "333px";
WizardControl.Style["Position"] = "absolute";
int j = Convert.ToInt16(Session["HowManySteps"]) - 1;
for (int i = 0; i <= j; i++)
{
WizardStepBase newStep = new WizardStep();
newStep.ID = "Step" + (i + 1).ToString();
WizardControl.WizardSteps.Add(newStep);
}
WizardControl.FinishButtonClick += new
WizardNavigationEventHandler(WizardControl_FinishButtonClick);
PlaceHolder1.Controls.Add(WizardControl);
thisDataSet = SqlHelper.ExecuteDataset(
thisConnectionString, "Wizard_Retrieve");
for (int i = 0; i < WizardControl.WizardSteps.Count; i++)
{
int A = i + 1;
Image ImageControl = new Image();
ImageControl.ID = "Image" + A.ToString();
ImageControl.Width = Unit.Pixel(120);
ImageControl.Height = Unit.Pixel(75);
WizardControl.WizardSteps[i].Controls.Add(ImageControl);
Image IMG = (Image)
WizardControl.WizardSteps[i].FindControl("Image" + A.ToString());
IMG.ImageUrl = thisDataSet.Tables[0].Rows[i][0].ToString().Trim();
RadioButtonList RadioButtonListControl = new RadioButtonList();
RadioButtonListControl.ID = "RadioButtonList" + A.ToString();
WizardControl.WizardSteps[i].Controls.Add(RadioButtonListControl);
RadioButtonList RBL = (RadioButtonList)
WizardControl.WizardSteps[i].FindControl(
"RadioButtonList" + A.ToString());
RBL.Width = Unit.Pixel(180);
RBL.Height = Unit.Pixel(100);
RBL.Items.Clear();
for (int x = 1; x < 4; x++)
{
RBL = (RadioButtonList)
WizardControl.WizardSteps[i].FindControl(
"RadioButtonList" + A.ToString());
RBL.Items.Add(new ListItem(
thisDataSet.Tables[0].Rows[i][x].ToString().Trim()));
}
RBL.SelectedIndexChanged += new EventHandler(RBL_SelectedIndexChanged);
}
}
public void RBL_SelectedIndexChanged(object sender, EventArgs e)
{
RadioButtonList RBL = (RadioButtonList)sender;
if (HiddenField1.Value != string.Empty)
{
HiddenField1.Value = HiddenField1.Value.ToString() +
"/" + RBL.SelectedValue.ToString();
}
else
{
HiddenField1.Value = RBL.SelectedValue.ToString();
}
}
public void WizardControl_FinishButtonClick(object sender, EventArgs e)
{
Wizard WZ=(Wizard)sender;
char[] DelimiterChar = { '/' };
string[] Answer = HiddenField1.Value.Split(DelimiterChar);
thisDataSet = SqlHelper.ExecuteDataset(thisConnectionString,
"Wizard_Retrieve");
int score = 0;
for (int i = 0; i < WZ.WizardSteps.Count; i++)
{
if (thisDataSet.Tables[0].Rows[i][4].ToString().Trim()
== Answer[i].Trim())
{
score = score + 1;
}
}
lblMessage.Text = "Your score is " + score.ToString() +
" out of a total of " +
(WZ.WizardSteps.Count).ToString();
}
}
In short, this is just a simple demo to show a way of using the Wizard control. You will have to download the flags from the web (the CIA World Fact Book is a good source for flags), or you can type in your own quiz questions to make the demo an online survey or an online test. To further improve the above demo, you can implement the Page.RegisterHiddenField() method, along with the IPostBackDataHandler interface, and call the Page.RegisterRequiresPostBack() to show the selections in previous WizardSteps when the web page that hosts the control is posted back to the web server. Also, flag images or text questions and the RadioButtonList options can all be packaged into a resource file instead of retrieving them as records from a SQL Server table.
In the meantime, hope you enjoy the article and find the example above useful and adaptable in your programming scenario. Thanks!