Hey guys,
I'm redoing some code that was written by a previous coder. Basically, we have a poll, where we see the question (an optional question image) and 2-10 answers (with their optional images). There's also a ticker that ticks every 5 seconds. There's tons of ajax programmed in which causes the RadioButtonList and the button label (lblMessage) to refresh every 5 seconds. The images and the answer text are loaded into the list items of the RadioButtonList. So every 5 seconds or anytime a different radio button is selected, the images are repainted. Which makes the website really hard to look at more than a minute or two.
We do need the ajax for the radiobuttonlist due to the timer, unless there's another way to go around this. If the poll ends and the user selects a different answer, it will disable the radio buttons and notify that the poll is over. So I'm wondering if there's anyway to separate the images from the RadioButtonList, or another way to keep the images from repainting without losing functionality.
and here is the code behind
Thanks for your time!
Derrick
I'm redoing some code that was written by a previous coder. Basically, we have a poll, where we see the question (an optional question image) and 2-10 answers (with their optional images). There's also a ticker that ticks every 5 seconds. There's tons of ajax programmed in which causes the RadioButtonList and the button label (lblMessage) to refresh every 5 seconds. The images and the answer text are loaded into the list items of the RadioButtonList. So every 5 seconds or anytime a different radio button is selected, the images are repainted. Which makes the website really hard to look at more than a minute or two.
We do need the ajax for the radiobuttonlist due to the timer, unless there's another way to go around this. If the poll ends and the user selects a different answer, it will disable the radio buttons and notify that the poll is over. So I'm wondering if there's anyway to separate the images from the RadioButtonList, or another way to keep the images from repainting without losing functionality.
<%@ Page Title="ViaConnect-Quick Poll" Language="C#" MasterPageFile="~/Student/StudentInterfaceMaster.Master"
AutoEventWireup="true" CodeBehind="QuickPoll.aspx.cs" Inherits="ViaStudent.Student.QuickPoll" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Web.UI" TagPrefix="telerik" %>
<%@ Register Assembly="Telerik.Web.UI" Namespace="Telerik.Charting" TagPrefix="telerik1" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<
asp:Content
ID
=
"Content1"
ContentPlaceHolderID
=
"head"
runat
=
"server"
>
<
script
type
=
"text/javascript"
>
$(document).ready(function () {
$('#nav-primary-quick').addClass('selected');
});
</
script
>
<
script
type
=
"text/javascript"
language
=
"javascript"
>
var fooElement = document.getElementById("questionText");
</
script
>
</
asp:Content
>
<
asp:Content
ID
=
"Content2"
ContentPlaceHolderID
=
"ContentPlaceHolder1"
runat
=
"server"
>
<
style
type
=
"text/css"
>
.answer_container1
{
padding:0;
margin:10px;
font-size:12px;
width:100%;
}
.lblClass
{
width:662px;
}
</
style
>
<
telerik:RadWindowManager
ID
=
"RadWindowManager1"
runat
=
"server"
/>
<
telerik:RadAjaxManager
ID
=
"RadAjaxManager1"
runat
=
"server"
>
<
AjaxSettings
>
<
telerik:AjaxSetting
AjaxControlID
=
"TimerActiveTime"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"lblTimerActiveTime"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"rdoQuickAnswer"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"imgBtnRefresh"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"lblMessage"
/>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
</
AjaxSettings
>
<
AjaxSettings
>
<
telerik:AjaxSetting
AjaxControlID
=
"rdoQuickAnswer"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"panelQuickPoll"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"lblCheckAnswer"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"rdoQuickAnswer"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"lblMessage"
/>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
</
AjaxSettings
>
<
AjaxSettings
>
<
telerik:AjaxSetting
AjaxControlID
=
"imgBtnRefresh"
>
<
UpdatedControls
>
<
telerik:AjaxUpdatedControl
ControlID
=
"panelQuickPoll"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"rdoQuickAnswer"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"imgBtnRefresh"
/>
<
telerik:AjaxUpdatedControl
ControlID
=
"lblMessage"
/>
</
UpdatedControls
>
</
telerik:AjaxSetting
>
</
AjaxSettings
>
</
telerik:RadAjaxManager
>
<
div
class
=
"body_left_container"
>
<
div
class
=
"body_title_bg_box"
>
<
div
class
=
"body_title_left_bg"
></
div
>
<
div
class
=
"body_title_middle_bg font_16_blue"
>
<
div
class
=
"quickpoll_left_title"
>Quick Poll: </
div
>
<
div
class
=
"left"
>
<
asp:Timer
ID
=
"TimerActiveTime"
runat
=
"server"
OnTick
=
"TimerActiveTime_Tick"
Interval
=
"5000"
/>
<
asp:Label
ID
=
"lblTimerActiveTime"
runat
=
"server"
/>
</
div
>
</
div
>
<
div
class
=
"body_title_right_bg"
></
div
>
</
div
>
<
div
class
=
"question_container_1 font_18"
>
<
asp:Label
ID
=
"lblTypeOfAssesment"
runat
=
"server"
/></
div
>
<
div
class
=
"quiz_body_inner_box_2"
>
<
asp:Panel
ID
=
"panelQuestionText"
CssClass
=
"question_container"
runat
=
"server"
>
<
asp:Label
ID
=
"lblQuestionText"
runat
=
"server"
/>
<
div
class
=
"question_icon_1"
>
<
telerik:RadToolTip
ID
=
"questionToolTip"
runat
=
"server"
Animation
=
"Fade"
EnableShadow
=
"False"
Position
=
"TopCenter"
RenderInPageRoot
=
"true"
>
<
asp:Image
ID
=
"imgQuestionToolTip"
runat
=
"server"
/>
</
telerik:RadToolTip
>
<
asp:Image
ID
=
"imgQuestion"
runat
=
"server"
/>
</
div
>
</
asp:Panel
>
<
asp:Panel
ID
=
"panelAnswer"
CssClass
=
"answer_container1"
runat
=
"server"
>
<
asp:RadioButtonList
ID
=
"rdoQuickAnswer"
CssClass
=
"lblClass"
runat
=
"server"
CellPadding
=
"0"
CellSpacing
=
"10"
RepeatLayout
=
"Table"
OnSelectedIndexChanged
=
"rdoQuickAnswer_SelectedIndexChanged"
AutoPostBack
=
"true"
/>
<
div
class
=
"quiz_body_inner_box_2 font_16_grey"
>
<
asp:Label
ID
=
"lblMessage"
CssClass
=
"error_message"
runat
=
"server"
></
asp:Label
>
</
div
>
</
asp:Panel
>
<
div
id
=
"resultLabel"
runat
=
"server"
class
=
"font_14 bold"
visible
=
"false"
></
div
>
</
div
>
<
div
class
=
"quiz_test_box"
></
div
>
</
div
>
</
asp:Content
>
and here is the code behind
using
System;
using
System.Collections.Generic;
using
System.Data;
using
System.Drawing;
using
System.Linq;
using
System.Text;
using
System.Web;
using
System.Web.UI;
using
System.Web.UI.HtmlControls;
using
System.Web.UI.WebControls;
using
System.Xml;
using
Telerik.Charting;
using
Telerik.Charting.Design;
using
Telerik.Charting.Styles;
using
Telerik.Web.UI;
using
ViaData;
using
ViaData.Entities;
using
ViaLibrary;
namespace
ViaStudent.Student
{
public
partial
class
QuickPoll : Navigation
{
private
ViaEntities contextVia =
new
ViaEntities();
private
int
studentClassId;
private
int
assessmentId;
private
DateTime startTimeUTC;
private
int
isCompletedCode;
private
int
assessmentQuestionId;
private
int
questionId;
private
string
questionText;
private
bool
questionHasMedia;
private
string
pollElapsedTime;
// Time elapsed since Quick Poll was published
private
bool
validPollExists =
true
;
// Is there a Quick Poll associated with this student/class
private
bool
isPollActive;
// If a Quick Poll exists, is it an active poll
int
rdoQuickAnswerIndex;
// rdoQuickAnswer selected index
protected
void
Page_Load(
object
sender, EventArgs e)
{
SetQuickPollDetails();
// Set ViewState variables
if
(!Page.IsPostBack)
{
if
(validPollExists)
{
SetCompletedStatus();
// Set isPollActive global variable
BindQuestionText();
// Sets question text label and image
BindRdoQuickAnswer();
// Sets RadioList options and images
SetMessages();
// Sets lblMessage text with student response info
}
else
{
TimerActiveTime.Enabled =
false
;
imgQuestion.Visible =
false
;
lblTimerActiveTime.Text =
"No Quick Polls exist for this class"
;
}
}
else
// Set global variables from ViewState
{
if
(validPollExists)
{
studentClassId = Convert.ToInt32(ViewState[
"StudentClassId"
]);
assessmentId = Convert.ToInt32(ViewState[
"AssessmentId"
]);
startTimeUTC = Convert.ToDateTime(ViewState[
"StartTimeUTC"
]);
assessmentQuestionId = Convert.ToInt32(ViewState[
"AssessmentQuestionId"
]);
questionId = Convert.ToInt32(ViewState[
"QuestionId"
]);
questionText = ViewState[
"QuestionText"
].ToString();
questionHasMedia = Convert.ToBoolean(ViewState[
"QuestionHasMedia"
].ToString());
}
}
if
(validPollExists)
{
ViewState[
"RdoQuickAnswerIndex"
] = rdoQuickAnswer.SelectedIndex;
rdoQuickAnswerIndex = rdoQuickAnswer.SelectedIndex;
TimeSpan timeElapsed = DateTime.UtcNow - startTimeUTC;
// Time elapsed since poll was started
pollElapsedTime = timeElapsed.ToString(
"hh':'mm':'ss"
);
// String format of timeElapsed
SetCompletedStatus();
if
(isPollActive)
lblTimerActiveTime.Text = pollElapsedTime;
else
lblTimerActiveTime.Text =
"Completed"
;
}
}
#region Private Methods
// Set global variables
private
void
SetQuickPollDetails()
{
student_class studentClass = (student_class)Session[
"studentClass"
];
// studentClass.student_class_id;
studentClassId = studentClass.student_class_id;
// StudentBase Session["studentClass"]
// Returns IList of Quick Polls: active first, then past poll, else empty list
var aqId = (from aq
in
contextVia.GetQuickPollByStudentClassId(studentClassId)
select aq).ToList();
if
(aqId.Count > 0)
// If at least one active or completed quick poll exists
{
validPollExists =
true
;
// If poll is active
if
(aqId[0].is_completed == (
int
)Enums.CompletedCode.Published)
isPollActive =
true
;
else
lblTimerActiveTime.Text =
"Completed"
;
// Set global variables from db or controls
assessmentId = aqId[0].assesment_id;
assessmentQuestionId = aqId[0].assesment_question_id;
isCompletedCode = Convert.ToInt32(aqId[0].is_completed);
startTimeUTC = Convert.ToDateTime(aqId[0].start_time);
questionId = Convert.ToInt32(aqId[0].question_id);
questionText = aqId[0].question_text.ToString();
questionHasMedia = Convert.ToBoolean(aqId[0].has_media);
// Set ViewState® variables from global variables
ViewState[
"StudentClassId"
] = studentClassId;
ViewState[
"AssessmentId"
] = assessmentId;
ViewState[
"AssessmentQuestionId"
] = assessmentQuestionId;
ViewState[
"StartTimeUTC"
] = startTimeUTC;
ViewState[
"IsCompletedCode"
] = isCompletedCode;
ViewState[
"QuestionId"
] = questionId;
ViewState[
"QuestionText"
] = questionText;
ViewState[
"QuestionHasMedia"
] = questionHasMedia;
}
else
// If no active or completed polls exist
{
validPollExists =
false
;
}
}
// Displays the question text
private
void
BindQuestionText()
{
lblQuestionText.Text = questionText;
lblQuestionText.Visible =
true
;
if
(questionHasMedia)
{
BindQuestionImage();
}
else
{
imgQuestion.Visible =
false
;
imgQuestionToolTip.Visible =
false
;
}
}
// Displays question image if one is present
private
void
BindQuestionImage()
{
var qpQuestionImage = (from qpi
in
contextVia.question_media
where qpi.question_id == questionId
select qpi).FirstOrDefault();
string
imageUrl =
"~/UserControls/Picture.ashx?s=40&QID="
+ questionId;
// Small image
string
imageUrlTT =
"~/UserControls/Picture.ashx?s=150&QID="
+ questionId;
// Larger, mouseover image
imgQuestion.Visible =
true
;
imgQuestionToolTip.Visible =
true
;
imgQuestion.ImageUrl = System.Web.HttpUtility.HtmlDecode(imageUrl);
questionToolTip.TargetControlID = imgQuestion.ID;
imgQuestionToolTip.ImageUrl = System.Web.HttpUtility.HtmlDecode(imageUrlTT);
imgQuestionToolTip.Height = 150;
imgQuestionToolTip.Width = 150;
}
// Populates RadioButtonList, rdoQuickAnswer
private
void
BindRdoQuickAnswer()
{
// Get all answers for this question (table answer_mcq)
IList<answer_mcq> qpAnswers = DBUtility.GetAssessmentOptions(questionId);
// Get IList of all student responses (each changed answer creates a new response) to this question
IList<response> studentResponse = DBUtility.GetStudentResponses(studentClassId, assessmentQuestionId);
// Clear rdoQuickAnswer item list. Avoids creating duplicates when Page_Load is hit twice
rdoQuickAnswer.Items.Clear();
for
(
int
i = 0; i < qpAnswers.Count; i++)
// For each student response to this question
{
// Create a list item setting the question id as the value and the question text as the text
ListItem listItem =
new
ListItem();
listItem.Text = qpAnswers[i].option_text;
listItem.Value = qpAnswers[i].mcq_id.ToString();
rdoQuickAnswer.Items.Add(listItem);
string
optionText = listItem.Text;
// Variable to hold question text
if
(Convert.ToBoolean(qpAnswers[i].has_image))
{
// Image path using the answer id as a query string value
string
imageUrl =
"~/UserControls/Picture.ashx?s=40&AIUID="
+ qpAnswers[i].mcq_id;
// Create image object dynamically using imageUrl string
System.Web.UI.WebControls.Image answerImg =
new
System.Web.UI.WebControls.Image();
// Create full URL from string URL and assign it to the image object
answerImg.ImageUrl = Page.ResolveUrl(imageUrl);
// Apply HTML and CSS formatting to the ListItem text to properly display the image
listItem.Text += (
"<div style=\"width: 50px; margin: 5px -20px 15px 0px; valign: middle;\"><img src='"
+ answerImg.ImageUrl +
"' /></div>"
);
rdoQuickAnswer.Items[i].Text = listItem.Text;
}
else
{
// If no image, set style for the ListItem for consistency
listItem.Text = optionText +
"<div style=\"width: 50px; margin: 5px 0px 15px 0px; valign: middle;\"></div>"
;
}
}
if
(!isPollActive)
rdoQuickAnswer.Enabled =
false
;
// If student has selected an option at least once
if
(studentResponse.Count > 0)
{
// Get most recent student response
string
answerMcq = studentResponse[0].mcq_answer_id.ToString().ToLower();
// Set rdoQuickAnswer selected option to the student's most recent answer selection
for
(
int
i = 0; i < rdoQuickAnswer.Items.Count; i++)
{
if
(rdoQuickAnswer.Items[i].Value.ToLower().CompareTo(answerMcq) == 0)
rdoQuickAnswer.SelectedIndex = i;
}
}
}
// Determines if poll is active
private
void
SetCompletedStatus()
{
isPollActive = DBUtility.IsAssessmentActive(assessmentId);
}
// Sets lblMessage text
private
void
SetMessages()
{
SetCompletedStatus();
// Get IList of all student responses (each changed answer creates a new response) to this question
IList<response> studentResponse = DBUtility.GetStudentResponses(studentClassId, assessmentQuestionId);
if
(studentResponse.Count > 0)
// If student has responded
{
if
(isPollActive)
{
lblMessage.Text =
"Currently selected answer is: "
+ rdoQuickAnswer.SelectedItem.Text;
}
else
{
lblTimerActiveTime.Text =
"Completed"
;
lblMessage.Text =
"Poll Completed: You selected: "
+ studentResponse[0].answer_text;
}
}
else
// If student has not responded
{
if
(isPollActive)
lblMessage.Text =
"You have not responded to this poll"
;
else
lblMessage.Text =
"You did not respond to this poll"
;
}
}
#endregion Private Methods
#region Control Events
protected
void
rdoQuickAnswer_SelectedIndexChanged(
object
sender, EventArgs e)
{
SetCompletedStatus();
if
(isPollActive)
{
int
index = Convert.ToInt32(ViewState[
"RdoQuickAnswerIndex"
]);
ListItem li = rdoQuickAnswer.Items[index];
int
mcqId = Convert.ToInt32(li.Value);
string
mcqAnswerText = li.Text;
int
responseCount = (from r
in
contextVia.responses
where r.student_class_id == studentClassId
&& r.assesment_question_id == assessmentQuestionId
select r.response_id).Count();
if
(responseCount == 0)
InsertNewResponse(mcqId);
else
UpdateResponse(mcqId);
int
selectedIndex = rdoQuickAnswer.SelectedIndex;
lblMessage.Text =
"Currently selected answer is : \""
+ mcqAnswerText +
"\""
;
rdoQuickAnswer.SelectedIndex = Convert.ToInt32(ViewState[
"RdoQuickAnswerIndex"
]);
SetMessages();
}
else
{
rdoQuickAnswer.Enabled =
false
;
}
}
// Adds a response to the database if it is the student's first response
private
void
InsertNewResponse(
int
mcqId)
{
// Get answer from DB based on currently selected mcq_id
var answerMcq = (from amcq
in
contextVia.answer_mcq
where amcq.mcq_id == mcqId
select amcq).FirstOrDefault();
// New student response object
response qpResponse =
new
response();
// Set response object's fields
qpResponse.assesment_question_id = assessmentQuestionId;
qpResponse.student_class_id = studentClassId;
qpResponse.answer_text = answerMcq.option_text;
qpResponse.is_correct = answerMcq.is_correct;
qpResponse.mcq_answer_id = answerMcq.mcq_id;
qpResponse.response_Date_Time = DateTime.UtcNow;
// Save response to DB
contextVia.responses.AddObject(qpResponse);
contextVia.SaveChanges();
}
//Updates a student's response choice if one currently exists
private
void
UpdateResponse(
int
mcqId)
{
// Get answer from DB based on currently selected mcq_id
var answerMcq = (from amcq
in
contextVia.answer_mcq
where amcq.mcq_id == mcqId
select amcq).FirstOrDefault();
var latestResponse = (from r
in
contextVia.responses
where r.student_class_id == studentClassId
&& r.assesment_question_id == assessmentQuestionId
orderby r.response_id descending
select r).FirstOrDefault();
latestResponse.mcq_answer_id = mcqId;
latestResponse.answer_text = answerMcq.option_text;
latestResponse.is_correct = answerMcq.is_correct;
latestResponse.response_Date_Time = DateTime.UtcNow;
contextVia.SaveChanges();
}
// TimerActiveTime: 5 second tick interval
protected
void
TimerActiveTime_Tick(
object
sender, EventArgs e)
{
SetCompletedStatus();
if
(isPollActive)
{
TimeSpan tickSpan = TimeSpan.Parse(lblTimerActiveTime.Text);
tickSpan = tickSpan.Add(TimeSpan.Parse(VConstants.QUICK_POLL_FREQUENCY));
lblTimerActiveTime.Text = tickSpan.ToString();
}
else
{
SetMessages();
TimerActiveTime.Enabled =
false
;
rdoQuickAnswer.Enabled =
false
;
lblTimerActiveTime.Text =
"Completed"
;
}
}
// Refresh chart control (currently unused)
protected
void
imgBtnRefresh_Click(
object
sender, ImageClickEventArgs e)
{
}
// Chart control (currently unused)
protected
void
chartQuickPoll_Customize(
object
sender, EventArgs e)
{
}
#endregion Control Events
}
}
Thanks for your time!
Derrick