Wednesday, March 23, 2011

Sitefinity - Custom Pollbox

I have created a custom PollBox  for Sitefinity to display Poll Questions and Results.

Why Custom PollBox?

Sitefinity  had its Rad Control to display poll questions and poll results.But the default RadChart control to display the results, uses images  to display graphical results.This is fine and working properly when we host our application on a single Web server. If we use Server farm with Load balance, We will get an error "RadChart image not found" and the results box will not display properly.

Even if we set the property 'Use Session" to false, the same error remains on the Web Farm.

Then I came up with a Custom poll box, which displays the poll results in pure html.It avoids the images and the error vanished.

Custom Pollbox Advantages:

1.)As it is showing all poll results in pure html, we have full control on Bar colors and width and heights.We can manipulate these with css.
2.) On the admin Side u can add this user control  by drag and drop as we add the default poll box.
3.) We can select the poll Id as we select it for default PollBox.
4.) We can specify User Blocking time in Hours .If we set this time,  a cookie will be created on the user machine and will block the user to vote again for a specified time in Hours.
5.) We can give our own Bar Colors and Main Colors and Horizontal Width of the Graph.
6.) We can customize this Custom Pollbox according to our requirements.

Screen shots:



Code:

you can download the code files  from the below link

https://docs.google.com/leaf?id=0B0LGUQrVMkGoNzc4ZGFhNzUtNjE4Yy00MDYyLThiYmQtM2E2MjU0YjA4MTc2&hl=en

CustomPollBox.ascx

<%@ Control Language="C#" AutoEventWireup="true" CodeFile="CustomPollBox.ascx.cs" Inherits="UC_CustomPollBox" %>
<div class="pollBox" >
<asp:Repeater runat="server" ID="rptPoll" OnItemDataBound="rptPoll_ItemDataBound" >
<ItemTemplate>
<div class="pollQuestion" >
<asp:Literal ID="litQuestion" runat="server" ></asp:Literal>
</div>
<asp:RadioButtonList ID="rblAnswers" runat="server" ></asp:RadioButtonList>
</ItemTemplate>
</asp:Repeater>

<asp:Repeater runat="server" ID="rptResults" OnItemDataBound="rptResults_ItemDataBound" Visible="false" >
<ItemTemplate>
<div class="pollQuestion" >
<asp:Literal ID="litQuestion" runat="server" ></asp:Literal>
</div>
<asp:Panel ID="pnlGraph" runat="server" ></asp:Panel>
</ItemTemplate>
</asp:Repeater>
<div class="pollBtnContainer" >
<asp:Literal ID="litTotalVotes" runat="server" Visible="false"></asp:Literal>
<asp:PlaceHolder ID="plhVoteButton" runat="server">
<a class="buttonLeftNew btn_BlueLeftNew" onmouseover="javascript:AddUndeline(this.id);" onmouseout="javascript:RemoveUndeline(this.id);" id="btnVoteLink" >
<asp:Button ID="btnVote" runat="server" Text="Submit" CssClass="btnMiddleNew btn_BlueMiddleNew buttonInput" OnClick="btnVote_Clicked" CausesValidation="true" onmouseover="javascript:AddUndeline(this.id);" onmouseout="javascript:RemoveUndeline(this.id);" />
</a>
</asp:PlaceHolder>
</div>
</div>

CustomPollBox.ascx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.ComponentModel;
using Telerik.Cms.Web.UI;
using Telerik.Polls;
using System.Collections;
using System.Drawing;

public partial class UC_CustomPollBox : System.Web.UI.UserControl
{
[Description("Gets or sets the ID of the poll which will be displayed")]
[Bindable(true)]
[WebEditor("Telerik.Polls.WebControls.PollBoxEditor, Telerik.Polls")]
[DisplayName("Poll ID")]
public Guid PollID { get; set; }

[PersistenceMode(PersistenceMode.Attribute)]
[Description("Chart background main color")]
[NotifyParentProperty(true)]
[TypeConverter(typeof(ColorConverter))]
[DefaultValue(typeof(Color), "240, 248, 255")]
[DisplayName("Main Color")]
public Color MainColor { get; set; }

[NotifyParentProperty(true)]
[DefaultValue(150f)]
public float Width { get; set; }

[Description("Chart plot area main color")]
[NotifyParentProperty(true)]
[TypeConverter(typeof(ColorConverter))]
[PersistenceMode(PersistenceMode.Attribute)]
[DefaultValue(typeof(Color), "153, 209, 248")]
[DisplayName("Bar Color")]
public Color BarColor { get; set; }

[Description("Block user to resubmit the poll (in hours)")]
[DisplayName("Block Time")]
public int BlockTime { get; set; }

PollManager pollManager;


protected void Page_Load(object sender, EventArgs e)
{
pollManager = new PollManager();

if (BarColor.A == 0 && BarColor.B == 0 && BarColor.G == 0 && BarColor.R == 0)
BarColor = Color.FromArgb(153, 209, 248);

if (MainColor.A == 0 && MainColor.B == 0 && MainColor.G == 0 && MainColor.R == 0)
MainColor = Color.FromArgb(240, 248, 255);
if (Width == 0)
Width = 150;

if (BlockTime == 0)
BlockTime = 120;

if(!IsPostBack)
{
if (PollID != null)
{
double total = pollManager.GetPollById(PollID).VoterNumber;
if (Request.Cookies[PollID.ToString()] != null && total > 0)
{
DisplayPollResults();
}
else
BindQuestionsRepeater();
}
}
}

protected void rptPoll_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
PollQuestion question = e.Item.DataItem as PollQuestion;
List<PollAnswer> answersList = PollHelper.GetAnswersByQuestionID(question.ID);
RadioButtonList rblAnswers = e.Item.FindControl("rblAnswers") as RadioButtonList;

Literal litQuestion = e.Item.FindControl("litQuestion") as Literal;
litQuestion.Text = question.Text;

rblAnswers.DataSource = answersList;
rblAnswers.DataTextField = "Text";
rblAnswers.DataValueField = "ID";
rblAnswers.DataBind();

}
}

protected void btnVote_Clicked(object sender, EventArgs e)
{
foreach (RepeaterItem item in rptPoll.Items)
{
RadioButtonList rblAnswers = item.FindControl("rblAnswers") as RadioButtonList;
if (!string.IsNullOrEmpty(rblAnswers.SelectedValue))
{
pollManager.IncrementAnswerCount(new Guid(rblAnswers.SelectedValue), 1);
}
}

IPollItem poll = pollManager.GetPollById(PollID);
if (poll != null)
{
poll.VoterNumber++;
pollManager.UpdatePoll(poll);
}
DisplayPollResults();
SetCookie();
Response.Redirect(Request.RawUrl);
}

private void BindQuestionsRepeater()
{
rptPoll.DataSource = PollHelper.GetQuestionsByPollID(PollID);
rptPoll.DataBind();
}

private void DisplayPollResults()
{
rptPoll.Visible = false;
plhVoteButton.Visible = false;
rptResults.Visible = true;

rptResults.DataSource = PollHelper.GetQuestionsByPollID(PollID);
rptResults.DataBind();
}

protected void rptResults_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
PollQuestion question = e.Item.DataItem as PollQuestion;
List<PollAnswer> answersList = PollHelper.GetAnswersByQuestionID(question.ID);

Literal litQuestion = e.Item.FindControl("litQuestion") as Literal;
litQuestion.Text = question.Text;

Panel chartPanel = e.Item.FindControl("pnlGraph") as Panel;
chartPanel.Controls.Add(LoadGraph(question));
}


private Table LoadGraph(PollQuestion questionItem)
{
double total = pollManager.GetPollById(PollID).VoterNumber;
litTotalVotes.Text = string.Format("Total Votes: {0}", total);
litTotalVotes.Visible = true;
IList<PollAnswer> answersList = PollHelper.GetAnswersByQuestionID(questionItem.ID);

Table table = new Table();
table.CssClass = "pollBoxTable";

double iWidth = 0;
Unit uWidth = 0;
string sWidth = (int)Width + "px";
table.Width = Unit.Pixel((int)Width);

if (sWidth.IndexOf("%") > -1)
{
iWidth = Convert.ToInt32(sWidth.Substring(0, sWidth.IndexOf("%")));
iWidth = iWidth / 10;
}
else
{
if (sWidth.IndexOf("px") > -1)
{
iWidth = Convert.ToInt32(sWidth.Substring(0, sWidth.IndexOf("px")));
}
else
{
iWidth = Convert.ToInt32(sWidth);
}
iWidth = iWidth / 100;
}

for (int i = 0; i < answersList.Count; i++)
{
TableRow tr = new TableRow();

TableCell td1 = new TableCell();
tr.Cells.Add(td1);


Panel container = new Panel();
container.BackColor = MainColor;
container.BorderColor = Color.White;
container.BorderWidth = Unit.Pixel(1);

Label lblBar = new Label();
double dblPercentage = (answersList[i].VoteCount/total) * 100;
lblBar.Width = Unit.Pixel(Convert.ToInt32(dblPercentage * iWidth));
lblBar.Height = Unit.Pixel(20);
lblBar.BackColor = BarColor;
lblBar.Text = answersList[i].VoteCount.ToString();
lblBar.CssClass = "chartBar";

Label lblPercentage = new Label();
lblPercentage.Text = answersList[i].Text + "&nbsp;/&nbsp;" + Math.Round(dblPercentage, 2).ToString() + "%<br/>";
td1.Controls.Add(lblPercentage);


td1.Controls.Add(container);
container.Controls.Add(lblBar);


table.Rows.Add(tr);
}

return table;
}

/// <summary>
/// Returns the width set as pixels or percentage
/// </summary>
/// <param name="width"></param>
/// <returns></returns>
private Unit GetWidth(string width)
{
Unit retVal = new Unit(0);
try
{
int iWidth = 0;
if (width.IndexOf("%") > -1)
{
iWidth = Convert.ToInt32(width.Substring(0, width.IndexOf("%")));
retVal = Unit.Percentage(iWidth);
}
else
{
if (width.IndexOf("px") > -1)
{
iWidth = Convert.ToInt32(width.Substring(0, width.IndexOf("px")));
}
else
{
iWidth = Convert.ToInt32(width);
}
retVal = Unit.Pixel(iWidth);
}
return retVal;
}
catch { return retVal; }
}

/// <summary>
/// Sets a cookie. Prevents multiple entries from a computer
/// </summary>
private void SetCookie()
{
HttpCookie cookie = new HttpCookie(PollID.ToString(), DateTime.Now.ToString());
cookie.Expires = DateTime.Now.AddHours(BlockTime);
Response.Cookies.Set(cookie);
}


}

App_Code/PollHelper.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;

/// <summary>
/// Summary description for PollHelper
/// </summary>
public class PollHelper
{
//public static PollHelper PollHelper = new PollHelper();
    public PollHelper()
    {
        
    }

public static List<PollQuestion> GetQuestionsByPollID(Guid pollID)
{
List<PollQuestion> pollQuestions = new List<PollQuestion>();
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Sitefinity"].ConnectionString);
using (connection)
{
try
{
connection.Open();
SqlCommand commad = new SqlCommand(string.Format("select * from dbo.sf_Polls_QuestionData where PollID = @PollID"), connection);
SqlParameter parameter = new SqlParameter("PollID", System.Data.SqlDbType.UniqueIdentifier);
parameter.Value = pollID;
commad.Parameters.Add(parameter);
SqlDataReader reader = commad.ExecuteReader(System.Data.CommandBehavior.CloseConnection);

while (reader.Read())
{
pollQuestions.Add(new PollQuestion((Guid)reader["ID"], (string)reader["Text"], (Guid)reader["PollID"]));
}
}
finally
{
connection.Close();
}
}
return pollQuestions;
}

public static List<PollAnswer> GetAnswersByQuestionID(Guid questionID)
{
List<PollAnswer> pollAnswers = new List<PollAnswer>();
SqlConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings["Sitefinity"].ConnectionString);
using (connection)
{
try
{
connection.Open();
SqlCommand commad = new SqlCommand(string.Format("select * from dbo.sf_Polls_AnswerData where QuestionID = @QuestionID"), connection);
SqlParameter parameter = new SqlParameter("QuestionID", System.Data.SqlDbType.UniqueIdentifier);
parameter.Value = questionID;
commad.Parameters.Add(parameter);
SqlDataReader reader = commad.ExecuteReader(System.Data.CommandBehavior.CloseConnection);

while (reader.Read())
{
pollAnswers.Add(new PollAnswer((Guid)reader["ID"], (string)reader["Text"], (Guid)reader["QuestionID"], (int)reader["VoteCount"]));
}
}
finally
{
connection.Close();
}
}

return pollAnswers;
}

}

public class PollQuestion
{
private Guid iD;
private string text;
private Guid pollID;

public Guid ID
{
get
{
return iD;
}
set
{
iD=value;
}
}

public Guid PollID
{
get
{
return pollID;
}
set
{
pollID=value;
}
}

public string Text
{
get
{
return text;
}
set
{
text=value;
}
}

public PollQuestion()
{
}

public PollQuestion(Guid ID,string Text,Guid PollID)
{
this.iD = ID;
this.pollID = PollID;
this.text = Text;
}
}


public class PollAnswer
{
private Guid iD;
private string text;
private Guid questionID;
private int voteCount;

public Guid ID
{
get
{
return iD;
}
set
{
iD = value;
}
}

public Guid QuestionID
{
get
{
return questionID;
}
set
{
questionID = value;
}
}

public string Text
{
get
{
return text;
}
set
{
text = value;
}
}

public int VoteCount
{
get
{
return voteCount;
}
set
{
voteCount = value;
}
}

public PollAnswer()
{
}

public PollAnswer(Guid ID, string Text, Guid QuestionID,int VoteCount)
{
this.iD = ID;
this.questionID = QuestionID;
this.text = Text;
this.voteCount = VoteCount;
}
}








 

No comments: