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 WizardStep
s 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 WizardStep
s 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 WizardStep
s 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!