Creating Survey Questions/Answers for Admin Sections - c#

I am developing an application for my company in which i am stuck at thinking what would be the best approach for doing this.
The company already have a page for survey around 15 questions with multiple choices. Now i have been asked to develop an application so that from admin section they can modify the existing questions and their options, also they can add more questions and options.
I am not sure what would be the best approach for doing this. I was thinking creating a page in admin section where they can see existing questions and answer options, if they modify it i can directly change it in the database and if they add more questions, I can go and create a custom questions fields in the database. For answers option i will not create any fields in the database as i will generate options dynamically like textboxes, checkboxes, radiobuttons etc.. and when user select the answer i will put pnly selected answers in the database.
EDIT
=======
I just want to give admin only 3 options for adding options ( checkbox, radios, textbox )
I am confused as how to create controls dynamically using generics. like admin can pass in the values in the method like this CreateControls(TextBox, NoOfOptions, List)
Please forgive me for not adding any code in my questions as i have not yet started working on this and stuck at the first stage of thinking process.
I am using VS2010, .Net 4.0, SQL server 208 R2 for this application.
Please advice. any working example Link would be appreciated.

I have one idea regarding this.I already done this kind of functionality but in my case each custom question is bind with textbox only.
In you case we can follow these steps :
Admin End :
Specify each control with unique value it may be number or control name.Save this in table with question id.
Client End :
1.) Take repeater.In item template take following controls :
a.)Label (Your custom question)
b.)textboxes (visible false)
c.)checkboxes (visible false)
d.)radiobuttons (visible false) etc.
2.)Bind this repeater with questions table.
3.)Now fire rowdatabound event and set visibility of controls on the basis of question id.
May this help you if you have any doubt please ask .
UPDATE :
Now please check the implementation of whole process which i had discussed yesterday :
XML file use as test database :
<?xml version="1.0" encoding="iso-8859-1"?>
<catalog>
<cd>
<id>1</id>
<title>Question 1</title>
<ctrl>1</ctrl>
</cd>
<cd>
<id>2</id>
<title>Question change</title>
<ctrl>2</ctrl>
</cd>
<cd>
<id>3</id>
<title>Question 3</title>
<ctrl>3</ctrl>
</cd>
<cd>
<id>4</id>
<title>Question 4</title>
<ctrl>2</ctrl>
</cd>
ASPX page :
<asp:Repeater ID="Repeater1" runat="server"
onitemdatabound="Repeater1_ItemDataBound">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Label ID="Label1" runat="server" Text='<%#Eval("id") %>'></asp:Label>
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%#Eval("ctrl") %>' />
</td>
<td>
<asp:Label ID="Label2" runat="server" Text='<%#Eval("title") %>'></asp:Label>
</td>
<td>
<asp:TextBox ID="TextBox1" runat="server" Visible="false"></asp:TextBox>
</td>
<td>
<asp:RadioButton ID="RadioButton1" runat="server" Checked="true" Text="YES" TextAlign="Left" Visible="false" />
<asp:RadioButton ID="RadioButton2" runat="server" Text="NO" TextAlign="Left" Visible="false" />
</td>
<td>
<asp:CheckBox ID="CheckBox1" runat="server" Visible="false" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
CS file :
if (!IsPostBack)
{
DataSet ds = new DataSet();
ds.ReadXml(MapPath("XMLFile.xml"));
Repeater1.DataSource = ds;
Repeater1.DataBind();
}
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
HiddenField ctrl = (HiddenField)e.Item.FindControl("HiddenField1");
if (ctrl.Value == "1")//1 for Textbox
{
TextBox txtCtrl = (TextBox)e.Item.FindControl("TextBox1");
txtCtrl.Visible = true;
}
else if (ctrl.Value == "3")//3 for Radio Button
{
RadioButton rdbYCtrl = (RadioButton)e.Item.FindControl("RadioButton1");
RadioButton rdbNCtrl = (RadioButton)e.Item.FindControl("RadioButton2");
rdbYCtrl.Visible = true;
rdbNCtrl.Visible = true;
}
else if(ctrl.Value == "2")//2 for Chackbox
{
CheckBox chkCtrl = (CheckBox)e.Item.FindControl("CheckBox1");
chkCtrl.Visible = true;
}
}
}
Hope this help you now :-)

Prettiest way to do this is to write a webcontrol. PLace it inside the ItemTemplate of teh Repeater. The repeater will do the databinding job, where as the webcontrol will render the question and the answer fields for each questions.
What I can imagine at the momment is, your datasource (that is bound to ther repeater must have at least:
QuestionID - This is to identify the question
Question - this contains the question
ResponseType - this is just a flag to determine whether to render textbox, radio or checkbox as the answer field/s
The webcontrol must have at least these properties:
QuestionID
Question
ResponseType
UserAnswer
Choices - collection of choice
During itemdatabound event of the repeater, get the webcontrol instance in the itemtemplate. assign the questionid and question from the bound DataItem to the respective webcontrol properties. Then check the AnswerType. if it's either radio or checkbox, retrieve the choices from the db/xml for this particular questionid, and assign it to the webcontrol Choices property.
Now at the webcontrol's RenderContents event:
write the question
if AnswerType is textbox, write textarea or textbox element
if AnswerType is either radio or checkbox, iterate the Choices property to render the respective input tags.
Anyway, if you use this approach, the admin can set unlimited number of choices for each questions. Each question can have flexibility. Image can be attached to questions, even as the choices like those IQ test.
However, there are a lot more to code in the webcontrol like, maintaining data on postbacks, fieldvalidation, etc.

Related

ASP.NET Listview->Click Row->Perform action

I need some help with the following.
I have a list view that I fill with code-behind:
Linq->Sql:
ListView1.DataSource = from x in database.ITEMS
select x;
ListView1.DataBind();
Content of ITEMS:
ID
Name
Quantity
I only show the name of the fields:
<tr>
<td>
<asp:Label ID="nameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
</tr>
Assuming I have 25 rows in the database, I fill the list view with 25 rows. Next is what I need help with. The user needs to click one of the 25 names (complete row) and redirects to a page where the content of that row is showed. So lets say someone clicks on "Cars", he'll be redirected and he will see: You have selected Cars, Cars has an ID of 19 and a Quantity of 6.
I have browsed the Internet already but I am having trouble finding solutions that I can understand. I am kind of a noob when it comes to list views and other data displaying methods.
My 2 questions:
How do I start a event when I click a row (and not a button or a link in that row)?
When I click a row and start a event, how can I check which one was clicked?
I hope someone can explain to me how this is done in a user friendly noob kind of way or redirect me to a tutorial discussing my issue's and also in a user friendly way. Thanks in advance.
Ok - I am not sure if this is the best way to go with this (I'll be interested what other think)... but this will work .
Update your listview to something like this:
<script type="text/javascript">
// simple redirect to your detail page, passing the selected ID
function redir(id) {
window.location.href = "mydetailpage.aspx?id=" + id;
}
</script>
<table>
<asp:ListView ID="ListView1" runat="server">
<ItemTemplate>
<tr onclick="redir('<%# Eval("ID") %>');">
<td>
<asp:Label ID="nameLabel" runat="server" Text='<%# Eval("Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:ListView>
</table>
Then create another page to show your detail (e.g. mydetailpage.aspx) - this should requery your database and show the other fields, given the id passed in the querystring.
you can define onclick attribute to call javascript function on tr element like this :
onclick="yourfunction('<%# Eval("Name") %>');"
Then you can put anything in your javascript function like redirect to another page

Looping thru all radiobuttonlists on page

I have a survey composed of nested repeater objects of questions that are within subjects. Everything is populated dynamically via the database. Each question has a radiobuttonlist of answers. There can be one or many questions per subject. When the user complete the form and click submit, how does my click function loop through all controls, find each radiobuttonlist and its' selected answer?
<div id="qDiv" runat="server" >
<asp:Repeater runat="server" ID="rptSubject" OnItemDataBound="rptSubject_ItemDataBound">
<ItemTemplate>
<h2><%#DataBinder.Eval(Container.DataItem, "Subject")%></h2>
<asp:Repeater runat="server" ID="rptQuestion" OnItemDataBound="rptQuestion_ItemDataBound">
<ItemTemplate>
<p><%# DataBinder.Eval(Container.DataItem, "Question")%></p>
<asp:RadioButtonList ID="rblAnswers" runat="server"></asp:RadioButtonList>
</ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
</div>
protected void submitButton_Click(object sender, EventArgs e)
{
???
}
As well as the selected answer, can I also get access to the repeaters values question & subject in the click function?
Use the Page.FindControl(string) method to find server controls based on a known ID pattern.

Set C# Inline Expressions in ASP.NET Controls On Server-Side

Is it possible to programatically insert C# Inline Expressions as the values for ASP.NET Controls in your server-side code?
I'm currently using a DataList to display a lot of data in a table. I want to be able to dynamically change the columns of that table, so I need to be able to edit what controls are in its ItemTemplate.
However, in addition to editing the controls in the ItemTemplate, I need to be able to alter the value that is binded to each control in the template, because I want to dynamically change what is being displayed.
So what I currently have is a static table that doesn't change:
<asp:DataList ID="dataList" runat="server" OnSelectedIndexChanged="dataList_OnSelectedIndexChanged" DataSourceID="peopleData">
<ItemTemplate>
<table>
<tr>
<td>
<asp:LinkButton ID="NameLink" OnClientClick="onPageUpdate()" CommandName="Select" Text='<%# Eval(this.Name) %>' ForeColor='<%# Eval("this.NameColor") %>' runat=Server" />
</td>
<td>
<asp:Label Text='<%# Eval("this.Values[\"Age\"]") %>' ForeColor='<%# Eval("this.ValueColors[\"Age\"]") %>' runat="Server">
</td>
// OTHER COLUMNS WITH DIFFERENT DATA
</tr>
</table>
</ItemTemplate>
</asp:DataList>
// OBJECT DATA SOURCE CODE
I know how to dynamically add Controls to the ASPX web page. However, I don't know how to add the inline expressions.
I've tried doing the following but it doesn't work because of the type mismatches:
Label label = new Label();
label.Text = "<%# Eval(\"this.Values[\\\"Age\\\"]\") %>";
label.ForeColor = "<%# Eval(\"this.ValueColors[\\\"Age\\\"]\") %>";
Is there a way of achieving this or doing something similar?
My only other option that I can think of right now is to scrap using the DataList and ItemTemplate and just generate each row myself.. That's a lot more coding versus just using the ItemTemplate.
Not sure if this would help you, but look at http://msdn.microsoft.com/en-us/library/system.web.ui.databinder(v=vs.100).aspx
It is showing using of the hand-written exposure of properties. If your property were always call "magic" and you return the appropriate value for magic within your code would that get you what you need?

How to get selected items of Listbox control?

I am developing an application in ASP.NET & c#. I have a Grid view in my page. In that I have a Listbox control and by default Enabled property set by false. I am trying to enable & disable that control from javascript / jQuery on Checkbox control.
My ASP Code:
<asp:GridView ID="gvWhom" runat="server" AutoGenerateColumns="False" DataSourceID="odsWhom"
GridLines="None" Width="100%" OnRowDataBound="gvWhom_RowDataBound">
<Columns>
<asp:TemplateField>
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr style="height: 25px;">
<td width="20%">
<asp:CheckBox ID="chkCriteria" runat="server" Text='<%#Eval("TargetType") %>' />
</td>
<td width="80%">
<asp:ListBox ID="lbCriteria" runat="server" CssClass="ddl" Width="150px" Height="50px"
Enabled="false" SelectionMode="Multiple"></asp:ListBox>
</td>
</table>
</ItemTemplate>
<HeaderStyle Height="2px" />
</asp:TemplateField>
</Columns>
</asp:GridView>
Javascript Code:
function disableDropDown(chkCriteria, lbCriteria) {
if (document.getElementById(chkCriteria).checked) {
document.getElementById(lbCriteria).removeAttribute('disabled');
}else{
document.getElementById(lbCriteria).value = -1;
document.getElementById(lbCriteria).disabled = true;
}
return true;
}
C# Code:
protected void gvWhom_RowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
ListBox lbCriteria = (ListBox)e.Row.FindControl("lbCriteria");
CheckBox chkCriteria = (CheckBox)e.Row.FindControl("chkCriteria");
chkCriteria.Attributes.Add("onchange", "javascript:return disableDropDown('" + chkCriteria.ClientID + "', '" + lbCriteria.ClientID + "')");
}
}
Using above code I am able to enable / disable the Listbox control. But when I enable the control and select multiple items and submitting the form I am not able to find selected items of Listbox.
How can I fetch selected items of Listbox? or Is there any other way to enable - disable the listbox control and get the selected items in c# code?
This is mostly a guess, but it's worth a try...
You're disabling the control on the server-side here:
<asp:ListBox ID="lbCriteria" runat="server" CssClass="ddl" Width="150px" Height="50px"
Enabled="false" SelectionMode="Multiple"></asp:ListBox>
That Enabled="false" may be indicating to ASP.NET that it doesn't need to track this control, that changes won't be made to it. That might be why it's not getting the data back when you post back to the server.
Let's try keeping the control enabled from the server's (ASP.NET's) perspective, and maintaining the enabling/disabling in the UI entirely on the client's (JavaScript's) side. Essentially removing ASP.NET's built-in framework from making decisions for you regarding what data to track.
Start by enabling the control in the server-side control markup:
<asp:ListBox ID="lbCriteria" runat="server" CssClass="ddl" Width="150px" Height="50px"
SelectionMode="Multiple"></asp:ListBox>
The rest is handled by JavaScript. You already have some JavaScript code which you say enables/disabled the control on the client-side for you, correct? So all you need to do now is call that same JavaScript for every instance of the control when the page first loads in the browser to disable the controls client-side. This is the part you want:
document.getElementById(lbCriteria).value = -1;
document.getElementById(lbCriteria).disabled = true;
Now, it looks like you're binding your JavaScript events from the server-side code, which is where I won't be able to help as much because that method isn't particularly intuitive to me. (It's mixing JavaScript and C#, which feels a bit backwards.) So I'm not entirely sure the approach you'd take there.
Essentially you want to invoke those two lines of JavaScript for every instance of the control, and you want it to happen as soon as the page loads in the browser.
In jQuery I'd do something like this:
$(function () {
$('select.ddl').attr('disabled', 'disabled');
});
This would run when the DOM is loaded and would add the disabled attribute (with a value of "disabled" to every select with the class ddl.

referencing control IDs from code behind that is in a repeater

This week I had a problem of trying to determine what control to use to be able to display data from multiple data sources in a non-grid looking way. Thanks to this forum, I have learned that the best way will be to use a Repeater with different controls such as labels and tables inside the repeater. Not quite sure exactly how I will get it all implemented yet but the first thing I need to learn is how to change the text from the code behind of a table and a Label that I will have inside the repeater. I have read up and found that the following should work. but it doesnt.
for (int i = 0; i <= Repeater1.Items.Count - 1; i++)
{
Label labelCustomerID = (Label)Repeater1.Items[i].FindControl("labelCustomerID");
labelCustomerID.Text = "from code Behind";
}
my declarative syntax is this:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="SqlDataSource1">
<ItemTemplate>
<hr/>
<asp:Label runat="server" ID="labelCustomerId" />
<div style="padding-left:150px">
<asp:Label runat="server" ID="labelCustomerName" />
<asp:Label runat="server" ID="labelCustomerAddress" />
<asp:Label runat="server" ID="labelCityState" />
</div>
<asp:GridView runat="server" ID="gridViewRecordData">
</asp:GridView>
<hr/>
</ItemTemplate>
</asp:Repeater>
Thanks to EdB I have gotten this far. Not still sure how I am gonna fill the gridview with one record of data but first things first... I need to be able to change a label's text. If i can get that done I am sure the rest will fall into place.
Please help me! :)
dell
Try with this code :
for (int i = 0; i <= Repeater1.Items.Count - 1; i++)
{
if(Repeater1.Items[i].ItemType == ListItemType.Item || Repeater1.Items[i].ItemType == ListItemType.AlternatingItem)
{
Label labelCustomerID = (Label)Repeater1.Items[i].FindControl("labelCustomerID");
labelCustomerID.Text = "from code Behind";
}
}
I think you are referencing the repeater before it is populated.

Categories

Resources