Background
The quiz application demonstrated here allows users to proceed with multi-choice questions like in an IQ Quiz. The database is a simple XML file. The application is a single web user control. The data holder between the pages is the Session bag (Viewstate[ data ]
).There are three panels within our quiz user control. They are Quiz panel, Review panel and Score Report panel. I have used my own progress bar control within the Score Report...
Database
Our database is a simple XML file:
="1.0" ="utf-8"
<quiz>
<mc>
<question correctAnsNo='1'>Which of the fol....?
</question>
<answer correct='No' ><![CDATA[]]>
</answer>
<answer correct='No' ><![CDATA[]]>
</answer>
<answer correct='Yes'><![CDATA[]]>
</answer>
<answer correct='No' ><![CDATA[]]>
</answer>
</mc>
</quiz>
Using the code
Our quiz user control has four methods:
ShowQuestion(int _qNo)
Review()
ReAnswer()
ShowResult()
The code
First, there are some common member variables:
XmlDocument doc=new XmlDocument();
XPathNavigator nav;
XPathNodeIterator nodeItrator;
ArrayList historyALst=new ArrayList();
ArrayList bookmarkLst=new ArrayList();
char[] perfix=new char[10] {'A','B','C','D','F','G','H','J','K','L'};
int currentQNo;
int totalQNumber;
int totalMarkedQuestion;
int currentMarkedQuestion;
int markLoop;
DateTime startTime;
TimeSpan spentTime;
bool isReview;
bool wasChecked=false;
In the page_load(....)
, do the following:
private void Page_Load(object sender, System.EventArgs e)
{
doc.Load(Server.MapPath("quiz.xml"));
nav=doc.CreateNavigator();
if(!IsPostBack)
{
quizPanal.Visible=true;
startTime=DateTime.Now;
currentQNo=1;
totalQNumber=nav.Select("//mc").Count;
ViewState["startTime"]=startTime;
ViewState["totalQNumber"]=totalQNumber;
ViewState["currentQNo"]=currentQNo;
ViewState["score"]=0;
ShowQuestion(currentQNo);
}
}
Let's render question number as currentQNo : ShowQuestion(currentQNo);
Render a specific multi-choice question. This method takes question number as parameter, and uses this number within different XPath strings to navigate through our XML nodes:
public void ShowQuestion(int _qNo)
{
quizPanal.Visible=true;
answersRBL.Items.Clear();
startTime=(DateTime)ViewState["startTime"];
totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);
spentTime=DateTime.Now.Subtract(startTime);
string xPath="quiz/mc["+_qNo.ToString()+"]";
int counter=1;
string str;
nodeItrator=nav.Select(xPath+"/question");
nodeItrator.MoveNext();
qNoLbl.Text="Q: "+_qNo.ToString()+" / "+totalQNumber.ToString();
questionLbl.Text=_qNo.ToString()+": "+nodeItrator.Current.Value;
spentTimeLbl.Text=spentTime.Minutes.ToString()
+"~"+spentTime.Seconds.ToString();
nodeItrator=nav.Select(xPath+"/answer");
while(nodeItrator.MoveNext())
{
str=counter.ToString();
answersRBL.Items.Add(new ListItem(perfix[counter-1].ToString()
+":"+nodeItrator.Current.Value,str));
if(nodeItrator.Current.GetAttribute("correct","")=="Yes")
{
ViewState["correctAnswer"]=counter;
}
counter++;
}
There are some actions that take place when this method renders bookmarked questions:
isReview=Convert.ToBoolean(ViewState["isReview"]);
if(isReview)
{
bookmarkCKBX.Enabled=false;
Image1.Visible=true;
qNoLbl.ForeColor=Color.Red;
RequiredFieldValidator1.Text="Answer The Question !";
}
currentQNo++;
ViewState["currentQNo"]=currentQNo;
}
After that, the user reviews answers history and is allowed to go back or view score report Review()
:
public void Review()
{
revisionPanal.Visible=true;
int seqance=0;
string _is="No";
bookmarkLst=(ArrayList)ViewState["bookmarkLst"];
historyALst=(ArrayList)ViewState["historyALst"];
totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);
wasChecked=Convert.ToBoolean(ViewState["wasChecked"]);
if(!wasChecked){ markBtn.Enabled=false;}
TableCell c=new TableCell();
TableCell cc=new TableCell();
TableCell ccc=new TableCell();
c.Text="Question No.";
cc.Text="Your Answer";
ccc.Text="Bookmark ?";
TableRow hr=new TableRow();
hr.Cells.Add(c);
hr.Cells.Add(cc);
hr.Cells.Add(ccc);
hr.ForeColor=Color.White;
hr.BackColor=Color.LightSlateGray;
Table1.Rows.Add(hr);
Table1.Font.Bold=true;
for(int i=1;i<=totalQNumber;i++)
{
TableCell c1=new TableCell();
c1.Text=i.ToString();
TableCell c2=new TableCell();
c2.HorizontalAlign=HorizontalAlign.Center;
c2.Text=perfix[Convert.ToInt32(historyALst[i-1])-1].ToString();
TableCell c3=new TableCell();
for(int n=0;n < bookmarkLst.Count;n++)
{
if(Convert.ToInt32(bookmarkLst[n].ToString())==i)
{
_is=" Yes ";
}
}
c3.Text=_is;
c3.HorizontalAlign=HorizontalAlign.Center;
_is=" No ";
TableRow r=new TableRow();
r.Cells.Add(c1);
r.Cells.Add(c2);
r.Cells.Add(c3);
r.ForeColor=Color.SlateGray;
if(seqance % 2 != 0)
{
r.BackColor=Color.Gainsboro;
}
Table1.Rows.Add(r);
eqance++;
}
}
If the user decides to go back, then ReAnswer()
:
public void ReAnswer()
{
quizPanal.Visible=true;
isReview=true;
bookmarkLst=(ArrayList)ViewState["bookmarkLst"];
totalMarkedQuestion=bookmarkLst.Count;
currentMarkedQuestion=Convert.ToInt32(bookmarkLst[0]);
markLoop=1;
ViewState["markLoop"]=markLoop;
ViewState["isReview"]=isReview;
ViewState["totalMarkedQuestion"]=totalMarkedQuestion;
ViewState["currentMarkedQuestion"]=currentMarkedQuestion;
ShowQuestion(currentMarkedQuestion);
}
In the end, call the Score report: ShowResult()
public void ShowResult()
{
resultPanal.Visible=true;
int score=Convert.ToInt32(ViewState["score"]);
totalQNumber=Convert.ToInt32(ViewState["totalQNumber"]);
startTime=(DateTime)ViewState["startTime"];
spentTime=DateTime.Now.Subtract(startTime);
progressBar.Total=totalQNumber*100;
progressBar.Value=score*100;
dateLbl.Text=DateTime.Now.ToUniversalTime().ToShortDateString();
totalQNoREsLbl.Text=totalQNumber.ToString();
totalScoreLbl.Text=(totalQNumber*100).ToString();
scoreLbl.Text=(score*100).ToString();
correctAnswersLbl.Text=score.ToString();
passingScoreLbl.Text=(totalQNumber*100/2).ToString();
timeTakenLbl.Text=spentTime.Hours.ToString()
+"<font color=\"#666699\">:</font>"
+spentTime.Minutes.ToString()
+"<font color=\"#666699\">:</font>"
+spentTime.Seconds.ToString()
+"<font color=\"#666699\" size=\"1\">Hr(s).</font>";
if((score*100/totalQNumber)<50)
{
gradeLbl.ForeColor=Color.Red;
gradeLbl.Text="Failed";
}
else
{
gradeLbl.ForeColor=Color.Green;
gradeLbl.Text="Success";
}
}
Done ..........!