Add hidden field to checkboxlist - c#

I have a CheckBoxList, in addition to checkbox and label I have to add a hidden field for each list item in the CheckBoxList. Is there a way to achieve this?
Thanks in advance.

You can achieve this by using a Repeater instead of a CheckBoxList control. On the plus side, this gives you more control over the generated HTML which might come handy anyway if you plan to access the items with jQuery; on the other hand you have to implement methods like retrieving the checked items for yourself.
The following sample shows the basic markup:
<asp:Repeater ID="rpt" runat="server">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:CheckBox ID="chk" runat="server" Text='<%# Eval("Item1") %>' />
<asp:HiddenField ID="hidden" runat="server" Value='<%# Eval("Item2") %>' />
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
In this sample, I have bound the repeater to a list of Tuple<string, string> values. You can retrieve the selected items like this by iterating the items of the repeater and retrieving the CheckBox and HiddenField:
private IEnumerable<Tuple<string, string>> GetSelectedItems()
{
var lst = new List<Tuple<string, string>>();
var items = rpt.Items
.OfType<RepeaterItem>()
.Where(x => x.ItemType == ListItemType.Item
|| x.ItemType == ListItemType.AlternatingItem);
foreach (var item in items)
{
var chk = (CheckBox)item.FindControl("chk");
if (chk.Checked)
{
var hidden = (HiddenField)item.FindControl("hidden");
lst.Add(Tuple.Create(chk.Text, hidden.Value));
}
}
return lst.ToArray();
}

Related

Binding an empty list to a ListView control in ASP.NET

I have an empty list object (lstPersons) that I'm binding to a ListView control (lvPersons). Since lstPersons is empty, it seems to never generate the ul in html. Is there a way to still force the html ul list to render even though lstPersons is empty? Basically rendering an empty ul, and preferably without having to change the LayoutTemplate?
<asp:ListView ID="lvPersons" runat="server" ClientIDMode="Static">
<LayoutTemplate>
<ul id="ulPersons" runat="server" ClientIDMode="static">
<li id="itemPlaceholder" runat="server"></li>
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<asp:Label ID="lblName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name")%>'></asp:Label>
</li>
</ItemTemplate>
</asp:ListView>
List<Person> lstPersons = new List<Person>();
lvPersons.DataSource = lstPersons;
lvPersons.DataBind();
The list exists, but there are no items in it. So if you want something to show up you need to add an empty Person to the list before binding it to the ListView.
List<Person> lstPersons = new List<Person>();
lstPersons.Add(new Person());
lvPersons.DataSource = lstPersons;
lvPersons.DataBind();

identify selected checkboxes in asp listview object

I have been trying to understand the ListView object in ASP but I'm unable to programmatically get the selected checkboxes or iterate through them. Below are the two methods I'm seeing posted the most here on SO, but so far everything I've tried hasn't seemed to work for me.
Any help would greatly be appreciated.
.ASPX Page
<asp:ListView ID="courseListView" runat="server">
<LayoutTemplate>
<table><asp:PlaceHolder runat="server" ID="itemPlaceholder">
</asp:PlaceHolder></table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:CheckBox ID="courseIdchk" Text='<%# Eval("CourseId") %>' runat="server" /></td>
<td><asp:Label ID="courseTitleLbl" Text='<%# Eval("title") %>' runat="server" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
.CS Code Behind
//Method #1
string result = string.Join(", ", courseListView.Controls.OfType<CheckBox>()
.Select(chk => chk.Text));
string result = "";
//Method #2
foreach (CheckBox ctrl in courseListView.Controls.OfType<CheckBox>())
{
result2 += ctrl.Text;
}
Response.Write("<p>The result is " + result);
Response.Write("<p>The result is " + result2);
Response.End();
I'm not near the Visual Studio but off the top of my head I see 2 reasons why it does not iterate.
1. You should bind this ListView to a source in OnLoad method:
if (!IsPostback) {
courseListView.DataSource = GetCourses();
courseListView.DataBind();
}
2. courseListView.Controls does not contain items of type CheckBox, so OfType<CheckBox>() filters out all elements. If you debug and put a breakpoint over foreach (CheckBox ctrl in courseListView.Controls.OfType<CheckBox>()), you will see that CheckBox is one of the subchildren of courseListView., so build your logic depending on which control contain CheckBoxes write the appropriate logic to get it like:
var checkBox = courseListView.Controls.Cast<Control>().First().FindControl("courseIdchk");
Again, the code above assumes that checkbox is a child of a control, which is an only child of your courseListView.
UPDATE
var findCheckedQuery = courseListView.Controls[0]
.Controls
.Cast<Control>()
.Select(ctrl => ctrl.FindControl("chkBox") as CheckBox)
.Where(chk => chk != null && chk.Checked);
result = string.Join(":", findCheckedQuery.Select(x => x.Text).ToArray());
UPDATE2
ASPX:
<asp:Repeater ID="courseListView" runat="server">
<ItemTemplate>
<asp:CheckBox ID="chkBox" data-id="<%#((Course)Container.DataItem).CourseId %>" Text="<%#((Course)Container.DataItem).Title %>" runat="server" />
<br/>
</ItemTemplate>
</asp:Repeater>
<asp:Button runat="server" UseSubmitBehavior="True" Text="Submit"/>
Code-behind:
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
if (!IsPostBack)
{
courseListView.DataSource = GetCourses();
courseListView.DataBind();
}
else
{
var result = string.Empty;
var findCheckedQuery = courseListView
.Controls
.Cast<Control>()
.Select(x => (CheckBox)x.FindControl("chkBox"))
.Where(x => x.Checked)
.Select(x => x.Text);
result = string.Join(", ", findCheckedQuery.ToArray());
}
}

How can I add a custom property to a RadioButtonList items?

How can I add a bound Html5 data- attribute to the items generated with a bound RadioButtonList?
My code looks like this:
<asp:Repeater Id="QuestionList" ...>
<ItemTemplate>
<asp:RadioButtonList DataSource='<%# Eval("Answers") %>'
SelectedValue='<%# Eval("SelectedAnswerId") %>'
DataTextField="Answer"
DataValueField="AnswerId"
Tag='<%# Eval("QuestionId") %>' />
</ItemTemplate>
</asp:Repeater>
var List<Question> questions = GetQuestions();
QuestionList.DataSource = questions;
QuestionList.DataBind();
It is bound to a class structure that looks like this:
public class Question
{
int QuestionId;
string Question;
List<Answer> Answers;
}
public class Answers
{
int AnswerId;
string Answer;
bool SomeFlag;
}
I need to add SomeFlag to the UI for jQuery to use, so the end result is that each item generated should look like this:
<input type="radio" data-flag="true" ... />
Is there a way to add a html data- attribute to the input objects generated from a bound RadioButtonList?
You can use ListItem attributes to add custom attributes to the items in the radio button list. You can check how your html is generated for radio button list and make jquery to get the required data attribute for you.
On server side
ListItem li1 = new ListItem();
ListItem li2 = new ListItem();
li1.Attributes.Add("data-flag", "true");
li2.Attributes.Add("data-flag", "true");
RadioButtonList1.Items.Add(li1);
RadioButtonList1.Items.Add(li2);
Generated html for radio button list
<table id="RadioButtonList1" border="0">
<tr>
<td><span data-flag="true"><input id="RadioButtonList1_0" type="radio" name="RadioButtonList1" value="" /></span></td>
</tr><tr>
<td><span data-flag="true"><input id="RadioButtonList1_1" type="radio" name="RadioButtonList1" value="" /></span></td>
</tr>
</table>
Accessing in jquery
$(':radio[id*=RadioButtonList1]').click(function(){
alert($(this).closest('span').data('flag'));
})
You can set an Attribute in the ItemDataBound event of Repeater, try something like:
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// if it is an item (not header or footer)
if (e.Item.ItemType == ListItemType.Item)
{
// get your radioButtonList
RadioButtonList optionsList = (RadioButtonList)e.Item.FindControl("rblOptionsList");
// loop in options of the RadioButtonList
foreach (ListItem option in optionsList.Items)
{
// add a custom attribute
option.Attributes["data-flag"] = "true";
}
}
}
And remember to set the IDs and Events for your controls
<asp:Repeater Id="QuestionList" ItemDataBound="QuestionList_ItemDataBound" ...>
<ItemTemplate>
<asp:RadioButtonList ID="rblOptionsList" DataSource='<%# Eval("Answers") %>'
SelectedValue='<%# Eval("SelectedAnswerId") %>'
DataTextField="Answer"
DataValueField="AnswerId"
Tag='<%# Eval("QuestionId") %>' />
</ItemTemplate>
</asp:Repeater>
Your best bet if you need to generate the attributes server-side would be to subclass the RadioButtonList control and override the Render method.
If you have a copy of Reflector or a similar product that can show decompiled code, this would be very helpful in determining exactly where the ListItem element is being rendered as a radio button.

Accessing Textboxes in Repeater Control

All the ways I can think to do this seem very hackish. What is the right way to do this, or at least most common?
I am retrieving a set of images from a LINQ-to-SQL query and databinding it and some other data to a repeater. I need to add a textbox to each item in the repeater that will let the user change the title of each image, very similar to Flickr.
How do I access the textboxes in the repeater control and know which image that textbox belongs to?
Here is what the repeater control would look like, with a submit button which would update all the image rows in Linq-to-SQL:
alt text http://casonclagg.com/layout.jpg
Edit:
This code works
Just make sure you don't blow your values away by Binding outside of if(!Page.IsPostBack) like me.. Oops.
<asp:Repeater ID="Repeater1" runat="server">
<ItemTemplate>
<div class="itemBox">
<div class="imgclass">
<a title='<%# Eval("Name") %>' href='<%# Eval("Path") %>' rel="gallery">
<img alt='<%# Eval("Name") %>' src='<%# Eval("Path") %>' width="260" />
</a>
</div>
<asp:TextBox ID="TextBox1" Width="230px" runat="server"></asp:TextBox>
</div>
</ItemTemplate>
</asp:Repeater>
And Submit Click:
protected void Button1_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in Repeater1.Items)
{
TextBox txtName = (TextBox)item.FindControl("TextBox1");
if (txtName != null)
{
string val = txtName.Text;
//do something with val
}
}
}
Have you tried something like following on the button click:-
foreach (RepeaterItem item in Repeater1.Items)
{
TextBox txtName= (TextBox)item.FindControl("txtName");
if(txtName!=null)
{
//do something with txtName.Text
}
Image img= (Image)item.FindControl("Img");
if(img!=null)
{
//do something with img
}
}
/* Where txtName and Img are the Ids of the textbox and the image controls respectively in the repeater.*/
Hope this helps.
.aspx
<asp:Repeater ID="rpt" runat="server" EnableViewState="False">
<ItemTemplate>
<asp:TextBox ID="txtQty" runat="server" />
</ItemTemplate>
</asp:Repeater>
.cs
foreach (RepeaterItem rptItem in rpt.Items)
{
TextBox txtQty = (TextBox)rptItem.FindControl("txtQty");
if (txtQty != null) { Response.Write(txtQty.Text); }
}
Be sure to add EnableViewState="False" to your repeater, otherwise you will get empty string. (That wasted my time, dont waste yours :) )
On postback, you can iterate over the collection of RepeaterItems in repeater.Items. You could then retrieve each TextBox with code such as
TextBox tbDemo = (TextBox)rptr.Items[index].FindControl("textBox");

Using ASP.Net ListView.ExtractItemValues, how do I get the selected item in a RadioButtonList in the ListViewDataItem?

I'm attempting to iterate over the ListViewDataItems in an ASP.Net ListView, and use the ListView.ExtractItemValues to get the values from DataBoundControls. This works fine with ITextControls, but I am having difficulty getting the Selected Item from a RadioButtonList.
Here is my markup:
<asp:ListView ID="lvQuiz" runat="server">
<LayoutTemplate>
<fieldset>
<ul>
<asp:PlaceHolder ID="itemplaceholder" runat="server"></asp:PlaceHolder>
</ul>
</fieldset>
<asp:Button ID="cmdSubmit" runat="server" Text="Submit" OnClick="cmdSubmit_Click" />
</LayoutTemplate>
<ItemTemplate>
<li>
<fieldset>
<legend>
<asp:Label ID="lblQuestionText" runat="server" Text='<%# Bind("Question.QuestionText") %>' />
</legend>
<asp:RadioButtonList ID="rblResponse" runat="server" DataTextField="ResponseText" DataValueField="Id"
DataSource='<%# Bind("Question.PossibleResponses") %>'>
</asp:RadioButtonList>
</fieldset>
</li>
</ItemTemplate>
And here is the code where I am trying to extract the values:
var Q = (Quiz)Session["Quiz"];
foreach (var item in lvQuiz.Items)
{
var itemValues = new OrderedDictionary();
lvQuiz.ExtractItemValues(itemValues, item, true);
var myQuestion = Q.UserResponses.Keys
.Where(x => x.QuestionText == itemValues["Question.QuestionText"])
.Single();
Q.UserResponses[myQuestion] = itemValues["Question.PossibleResponses"].SelectedItem
}
My problem lies with that last line there. "Question.PossibleResponses" is bound to the RadioButtonList, but the value for itemValues["Question.PossibleResponses"] returns a list of ALL my RadioButtonList's options. How do I tell which one the user selected?
Well, I ended up implementing an extension method for Control that implements a Recursive FindControl, as outlined in Steve Smith blog post on Recursive FindControl. As I only had two bindable controls that I cared about (Label and a ListControl), this ended up being good enough. Tightly coupled to the UI, but I don't know what else to do.

Categories

Resources