Question

I am trying to create an Exam with multiple pages of questions. The questions are created dynamically in an SQL proc. I have a Repeater in my aspx page with a RadioButtonList I create dynamically in my codebehind.

<asp:Repeater ID="ExamQuestionsRepeater" OnItemDataBound="RepeaterItemEventHandler" runat="server">
            <ItemTemplate>
                <asp:Label ID="QuestionLabel" runat="server"><b><%# Eval("exm_Question") %></b></asp:Label>
                <asp:RadioButtonList ID="QuestionsList" runat="server" RepeatDirection="Vertical">
                </asp:RadioButtonList>
            </ItemTemplate>
            <SeparatorTemplate>
                <tr>
                    <td><hr class="ExamQuestionsSeparatorTemplate"  /></td>
                </tr>
            </SeparatorTemplate>
        </asp:Repeater>

The code behind is the following:

protected void Page_Load(object sender, EventArgs e)
    {
        if (!IsPostBack)
        {
            loadQuestions();
        }
    }

private void loadQuestions()
    {
            DataSet dataSet = getData();

            PagedDataSource pagedDS = new PagedDataSource();
            pagedDS.DataSource = dataSet.Tables[0].DefaultView;
            pagedDS.AllowPaging = true; //indicate that data is paged
            pagedDS.PageSize = 10; //number of questions per page

            //Edit: I noticed I was setting the page index after I bound the repeater
            pagedDS.CurrentPageIndex = CurrentPage;

            ExamQuestionsRepeater.DataSource = pagedDS;
            ExamQuestionsRepeater.DataBind();

            //update previous and next buttons depending on what current page is at
            updateButtons();
        }

    }

I am using the OnItemDataBound event in my repeater to bind my dynamic radio button list

protected void RepeaterItemEventHandler(object sender, RepeaterItemEventArgs e)
    {
        int questionA = 2;
        int questionB = 3;

        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            RadioButtonList questionsRadioButtonList = (RadioButtonList)e.Item.FindControl("QuestionsList");
            DataRow row = ((DataRowView)e.Item.DataItem).Row;

            if (row.ItemArray[questionA] != null && !String.IsNullOrEmpty(row.ItemArray[questionA].ToString()))
            {
                ListItem item = new ListItem();
                item.Text = row.ItemArray[questionA].ToString();
                item.Value = "A";

                questionsRadioButtonList.Items.Add(item);
            }
            if (row.ItemArray[questionB] != null && !String.IsNullOrEmpty(row.ItemArray[questionB].ToString()))
            {
                ListItem item = new ListItem();
                item.Text = row.ItemArray[questionB].ToString();
                item.Value = "B";
                questionsRadioButtonList.Items.Add(item);
            }
        }
    }

    protected void NextButton_Click(object sender, EventArgs e)
    {
        // Set viewstate variable to the next page
        CurrentPage += 1;

        // Reload control
        loadQuestions();
    }

    protected void PreviousButton_Click(object sender, EventArgs e)
    {
        // Set viewstate variable to the previous page
        CurrentPage -= 1;

        // Reload control
        loadQuestions();
    }

My problem is that when I move on to the next page or click on the previous page, the list of questions is always bound to the first 10 questions and the state isn't stored between pages either. What am I missing or what do I need to do to load up the next 10 items when loading the next "page"?

Edited: I got the next items to load up on each page properly. Now the problem is that my view state isn't saving the value of my radio buttons each time the list is loaded. Am I overriding it when I use the RepeaterItemEventHandler? Should I be checking for something in that method?

Was it helpful?

Solution

So I guess I was misunderstanding how the selected values from controls are loaded. I ended up creating a list of the user's answers and saving it into a Session variable. When I loaded up my questions between pages I would check if the question/answer pair existed in that session list and then loaded up the value from there. My RepeaterItemEvenHandler looks like this now and does the trick perfectly:

protected void RepeaterItemEventHandler(object sender, RepeaterItemEventArgs e)
    {
        if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
        {
            RadioButtonList questionsRadioButtonList = (RadioButtonList)e.Item.FindControl("QuestionsList");
            ExamQuestion exam = (ExamQuestion)e.Item.DataItem);

            if (!String.IsNullOrEmpty(exam.exm_AnswerA))
            {
                ListItem item = new ListItem();
                item.Text = exam.exm_AnswerA;
                item.Value = "A";

                questionsRadioButtonList.Items.Add(item);
            }

            //loading the rest of the list items for the radiobuttonlist goes here...

            //here is where I load the answer into the radio button if it was answered before
            if (Session["AnswersList"] == null) throw new Exception("Session variable not set properly: AnswersList");

            var answers = (List<UserAnswer>)(Session["AnswersList"]);

            if (answers.FindIndex(a => a.QuestionID == exam.exm_ID.ToString()) > -1)
            {
                questionsRadioButtonList.SelectedValue = 
                answers.Find(a => a.exm_QuestionID == exam.exm_ID.ToString()).exm_UserAnswer;
            }
        }
    }

This is a link with an easy to follow tutorial that helped with creating my exam if anyone needs that kind of reference: http://www.asp.net/web-forms/videos/building-20-applications/lesson-12-building-a-quiz-engine-2

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top