i'm want to have a repeater generate a bunch of checkboxes, e.g.:
<tr><td><input type="checkbox" name="t" value="11cbf4deb87" /> <input type="checkbox" name="a" value="33cbf4deb87" />stackoverflow.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cbf4deb88" /> <input type="checkbox" name="a" value="33cbf4deb87" />microsoft.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11cd3f33a89" /> <input type="checkbox" name="a" value="33cbf4deb87" />gmail.com</td></tr>
<tr><td><input type="checkbox" name="t" value="1138fecd337" /> <input type="checkbox" name="a" value="33cbf4deb87" />youporn.com</td></tr>
<tr><td><input type="checkbox" name="t" value="11009efdacc" /> <input type="checkbox" name="a" value="33bf4deb87" />fantasti.cc</td></tr>
Question 1: How do i individually reference each checkbox when the repeater is running so i can set the unique value?
Do i data-bind it with something like:
<itemtemplate>
<tr>
<td>
<input type="checkbox" name="t"
value="<%# ((Item)Container.DataItem).TangoUniquifier %>" />
<input type="checkbox" name="a"
value="<%# ((Item)Container.DataItem).AlphaUniquifier %>" />
<%# ((Item)Container.DataItem).SiteName %>
</td>
</tr>
</itemtemplate>
Or am i supposed to set it somehow in the OnItemDataBound?
<asp:repeater id="ItemsRepeater"
OnItemDataBound="ItemsRepeater_OnItemDataBound" runat="server">
...
<itemtemplate>
<tr>
<td>
<input id="chkTango" type="checkbox" name="t" runat="server" />
<input id="chkAlpha" type="checkbox" name="a" runat="server" />
<%# ((Item)Container.DataItem).SiteName %>
</td>
</tr>
</itemtemplate>
...
</asp:repeater>
protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
// if the data bound item is an item or alternating item (not the header etc)
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// get the associated item
Item item = (Item)e.Item.DataItem;
//???
this.chkTango.Value = item.TangoUniquifier;
this.chkAlpha.Value = item.AlphaUniquifier;
}
}
But if i'm supposed to reference it in the code-behind, how do i reference it in the code-behind? Am i supposed to reference it using the (server-side) id property of an <INPUT>
control? i realize that the ID of a control on the server-side is not the same as the ID that will be present on the client.
Or do i have to do something where i have to find an INPUT control with a name of "t" and another with a name of "a"? And what kind of control is a CheckBox that allows me to set it's input value?
protected void ItemsRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
// if the data bound item is an item or alternating item (not the header etc)
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// get the associated item
Item item = (Item)e.Item.DataItem;
CheckBox chkTango = (CheckBox)e.Item.FindControl("chkTango");
chkTango.Value = item.TangoUniquifier;
CheckBox chkAlpha = (CheckBox)e.Item.FindControl("chkAlpha");
chkAlpha.Value = item.AlphaUniquifier;
}
}
Question 2: When the user later clicks SUBMIT, how do i find all the checked checkboxes, or more specifically their VALUES?
Do i have to FindControl?
protected void DoStuffWithLinks_Click(object sender, EventArgs e)
{
// loop through the repeater items
foreach (RepeaterItem repeaterItem in actionItemRepeater.Items)
{
Item item = repeaterItem.DataItem as Item;
// grab the checkboxes
CheckBox chkAlpha = (CheckBox)repeaterItem.FindControl("chkAlpha");
CheckBox chkTango = (CheckBox)repeaterItem.FindControl("chkTango");
if (chkAlpha.Checked)
{
item.DoAlphaStuff(chkAlpha.Name);
}
if (chkTango.Checked)
{
item.DoTangoStuff(chkTango.Name);
}
}
}
Is the repeater items DataItem still there on a click event handler?
Use the server control instead of making an input control runat=server
<asp:CheckBox id="whatever" runat="Server" />
When you set the value in your ItemDataBound, you use FindControl
CheckBox checkBox = (CheckBox)e.Item.FindControl("whatever");
checkBox.Checked = true;
When you get the items, you also use FindControl from the item in a foreach construct. Also, depending on how you databound it, the DataItem may no longer be there after a postback.
foreach (RepeaterItem item in myRepeater.Items)
{
if (item.ItemType == ListItemType.Item
|| item.ItemType == ListItemType.AlternatingItem)
{
CheckBox checkBox = (CheckBox)item.FindControl("whatever");
if (checkBox.Checked)
{ /* do something */ }
}
}
- Many people are tempted to 'safe cast' using the
as
operator withFindControl()
. I don't like that because when you change the control name on the form, you can silently ignore a development error and make it harder to track down. I try to only use theas
operator if the control isn't guaranteed to be there.
Update for: Which CheckBox is which? In the rendered html you'll end up having all these checkbox name like
ctl00_cph0_ParentContainer_MyRepeater_ctl01_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl02_MyCheckbox
ctl00_cph0_ParentContainer_MyRepeater_ctl03_MyCheckbox
You don't care what the names are because the foreach item.FindControl() gets them for you, and you shouldn't assume anything about them. However, when you iterate via foreach, you usually need a way to reference that back to something. Most of the time this is done by also having an asp:HiddenField control alongside each CheckBox to hold an identifier to match it back up to the correct entity.
Security note: there is a security issue with using hidden fields because a hidden field can be altered in javascript; always be conscious that this value could have been modified by the user before the form was submitted.
You might find it easier to use a CheckBoxList control.
In the simple case, you would set the DataTextVield and the DataValueField to the name and value as pulled from your datasource (assuming you're populating from a datasource) and then bind it to create the items.
Probably less work on your part than creating the checkboxes in a repeater.
Here is some specific code for how to handle the hidden field:
MARKUP:
<asp:HiddenField ID="repeaterhidden" Value='<%# DataBinder.Eval(Container.DataItem, "value")%>' runat="server" >
C#:
{
HiddenField hiddenField = (HiddenField)item.FindControl(repeaterStringhidden);
{ /* do something with hiddenField.Value */
}
I believe this KB gave me the best answer:
http://msdn.microsoft.com/en-us/library/1d04y8ss.aspx
to my own lack of luck, this seems to be available for the .net 4.0 version only (and I'm still stuck at 3.5 SP1).
quoting (bold is mine):
When a control is inside a data-bound control that generates repeated instances of the control, ASP.NET generates UniqueID and ClientID values for each instance of the control. The UniqueID value is generated by combining the naming container's UniqueID value, the control's ID value, and a sequential number. This is the case in controls such as the DataList, Repeater, GridView, and ListView controls.
ASP.NET generates ClientID values in a similar manner when the ClientIDMode property is set to AutoID. This can make it difficult to reference the control in client script, because you typically cannot predict the values of the sequential numbers that are used. If you want to access data-bound controls from client script, you can set the ClientIDMode property to Predictable. This makes it easier to predict what the ClientID values will be.
When you set the ClientIDMode to Predictable, you can also set the ClientIDRowSuffixDataKeys property to the name of a data field that is unique, such as the primary key in a database table. This causes ASP.NET to generate a client ID that will be easier to predict and reference in client script if you can predict data key values.
So, in version 3.5, I'm doing it using hidden fields:
foreach (RepeaterItem item in rptClientes.Items)
{
Panel pnl = (Panel)item.FindControl("divCliente");
Control c = pnl.FindControl("hdnID");
if (c is HiddenField)
{
if (((HiddenField)c).Value == hdnClienteNome.Value)
pnl.BackColor = System.Drawing.Color.Beige;
}
}
来源:https://stackoverflow.com/questions/179938/asp-net-how-to-access-repeater-generated-form-input-elements