I have a Repeater like this
<asp:Repeater runat="server" DataSourceID="HeaderFooterSqlDataSource">
<HeaderTemplate>
<table border="0" width="100%">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<input runat="server" id="SelectRadio" type="radio"
name="HeaderFooter" onclick='SelectAndSetHeaderFooter(this);" %>' />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Now here when this Repeater is rendered the name attribute of my input radio "SelectRadio" gets auto generated but name attribute for all the radiobuttons in my repeater should be same so that they can work like a group & get checked / unchecked automatically according to other elements in that group, So how can I overcome this situation ??
Edit
I got the solution my self, Actually I have defined my input radio control as runat="server" because I thought otherwise Eval() binding wouldn't work but I was wrong Eval() binding does work without runat="server" , So when I remove that attribute name doesn't generated automatically and everything is fine now, But thanx to all for sparing time for my question.
Instead of hacking this you should use the built-in RaidoButtonList control.
<asp:RadioButtonList id="RadioButtonList1" runat="server">
<asp:ListItem>Item 1</asp:ListItem>
<asp:ListItem>Item 2</asp:ListItem>
<asp:ListItem>Item 3</asp:ListItem>
<asp:ListItem>Item 4</asp:ListItem>
<asp:ListItem>Item 5</asp:ListItem>
<asp:ListItem>Item 6</asp:ListItem>
</asp:RadioButtonList>
You want to look into the asp:RadioButton control (http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.radiobutton.aspx).
In particular the GroupName property on this control can be used to "specify a grouping of radio buttons to create a mutually exclusive set of controls"
So roughly speaking:
<asp:RadioButton runat="server" id="SelectRadio"
GroupName="HeaderFooter" %>' />
Edit: It seems that in this particular situation GroupName doesn't do what it is designed for. http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.radiobutton.groupname.aspx discusses it in the community content at the end but it boils down to the fact that it uses its current NamingContainer still as part of its name rather than just using the groupname you have given it. Thanks to the mysterious user1429080 for bringing that to my attention in comments.
The reason your radio buttons are not acting as a group is because you have runat="server" which will cause the name and id attributes to be prepended with parents' ids. The following will cause the radio buttons to behave as a cohesive group (note the lack of runat="server"):
ascx code:
<asp:Repeater ID="uxRadioSelections" runat="server">
<HeaderTemplate>
<table border="0" width="300px">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<input type="radio" value='<%# Eval("Name") %>' name="HeaderFooter" onclick="alert(this.value);"><%# Eval("Name") %></input>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
code behind:
protected void Page_Load(object sender, EventArgs e)
{
string[] names = new string[] {"Alvin", "Simon", "Theodore"};
uxRadioSelections.DataSource = names.Select(x => new { Name = x });
uxRadioSelections.DataBind();
}
However, the following will NOT perform as a cohesive group:
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
Test
<asp:Repeater ID="uxRadioSelections" runat="server">
<HeaderTemplate>
<table border="0" width="300px">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:RadioButton Text='<%#Eval("Name") %>' runat="server" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
</asp:Content>
Due to the naming conventions you alluded to, these individual radio buttons will not find each other. ASP.NET uses RadioButtonLists to overcome this:
ascx code:
<asp:RadioButtonList ID="uxRadioButtons" runat="server">
</asp:RadioButtonList>
code behind:
protected void Page_Load(object sender, EventArgs e)
{
string[] names = new string[] {"Alvin", "Simon", "Theodore"};
uxRadioButtons.DataTextField = "Name";
uxRadioButtons.DataValueField = "Name";
uxRadioButtons.DataSource = names.Select(x => new { Name = x });
uxRadioButtons.DataBind();
}
This does not give you as granular control, but will provide easy server-side access to the selections. If all you need is javascript-related functionality and increased formatting flexibility, the first format may (which is nearly identical to what you provided) is your best bet. Good luck!
Another option is to set the ClientIDMode as 'static' which will set its value to that of the ID specified. Since it is a repeater control, all the items generated will thus have the same generated ID. So you simply set:
<asp:RadioButton runat="server" id="SelectRadio" GroupName="HeaderFooter" ClientIDMode="static">' />
This means that all generated controls will have the same ID specified i.e. "SelectRadio". This may or may not be problematic and you should be careful that this is exactly what you want.
Just a note, ClientIDMode is a feature of ASP.Net 4.0. More info here: ClientIDMode in ASP.NET 4.0 and here: MSDN. I hope this helps.
Update 1:
You can get more insights from this question asked before on StackOverflow. (It's jQuery though).
Related
Below is code that I'm aiming for. I need a custom user control that can be data bound to, but also contain other content (so just a raw repeater wont suffice). The end goal is something along the lines of:
<MyControls:Control1 runat="server" id="Control1">
<headertemplate>
<tr>
<td>ID</td>
<td>Username</td>
</tr>
</headertemplate>
<itemtemplate>
<tr>
<td><%#((User)Container.DataItem).ID %></td>
<td><%#((User)Container.DataItem).Username %></td>
</tr>
</itemtemplate>
</MyControls>
And:
var users = GetUsersList();
Control1.DataSource = users;
Control1.DataBind();
And looks like this:
<%# Control Language="C#" AutoEventWireup="true" CodeBehind="MyControl1.ascx.cs" Inherits="Controls.MyControl1" %>
<asp:PlaceHolder runat="server" ID="Wrapper">
<h2>Results</h2>
<table>
<%=HeaderTemplate%>
<%
if(ItemTemplate.AnyItems()){
foreach(var item in ItemTemplate){
}
}
else
{
%>Nothing here<%
}
%>
</table>
<MyControls:AnotherControl runat="server" />
</asp:PlaceHolder>
I've found a page on ScottGu's Blog that appears to show what I want:
https://weblogs.asp.net/scottgu/Supporting-Templates-with-ASP.NET-User-Controls
But the linked to tutorial 404's now! All other examples I've found don't seem to be well written and very hard to pick apart.
Any help on how to achieve the above would be much appreciated.
It looks like you are getting 2 different Controls mixed up. UserControl and Repeater (I think).
To bind data in to a Control inside a UserControl, you need to make that Control accessible from the parent. You can do this by creating a public property inside the UserControl.
public Repeater myRepeater
{
get
{
return Repeater1;
}
set
{
Repeater1 = value;
}
}
UserControl ascx with the Repeater Control
<table border="1">
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<tr>
<td>ID</td>
<td>Username</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("ID") %></td>
<td><%# Eval("Username") %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
<br />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<br />
<asp:Button ID="Button1" runat="server" Text="Button" />
<br />
<asp:Label ID="Label1" runat="server" Text="Label"></asp:Label>
Now you have access to Repeater1 in the parent due to the public property.
Control1.myRepeater.DataSource = users;
Control1.myRepeater.DataBind();
And leave the control on the aspx parent empty.
<MyControls:Control1 runat="server" id="Control1"></MyControls>
I want to create asp:Table where I can add rows using asp:Repeater like:
<asp:Table runat="server" ID="tblRepeater">
<asp:Repeater runat="server">
<ItemTemplate>
<asp:TableRow runat="server">
<asp:TableCell runat="server" Text=""></asp:TableCell>
<asp:TableCell runat="server" Text=""></asp:TableCell>
</asp:TableRow>
</ItemTemplate>
</asp:Repeater>
</asp:Table>
But when I try to do this It gives me error:
System.Web.UI.WebControls.TableRowCollection must have items of type 'System.Web.UI.WebControls.TableRow'.
'asp:Repeater' is of type 'System.Web.UI.WebControls.Repeater'.
Am I doing somethig wrong or it is impossible to use Repeater in Table?
I'm not sure if your example is slimmed down or represents your actual use case, but in this case you'd be better of using either a GridView which will generate a table structure based off of a given Data Source, or creating the <table> structure yourself and then placing a repeater inside it:
<table>
<asp:Repeater runat="server">
<ItemTemplate>
<tr>
<td><asp:TextBox runat="server" /></td>
<td><asp:TextBox runat="server" /></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
Here, I found once the code to hide a repeater column easily. It works great like this.
<ItemTemplate>
<tr>
<td><asp:Label runat="server" ID="label1" /></td>
<% if (MustBeVisible) { %>
<td"><asp:Label runat="server" ID="label2" /></td>
<% } %>
</tr>
</ItemTemplate>
But now, I need to apply a CLASS to the TableRow and make it runat="server" in order to apply a color condition in the ItemDataBound but when I add the attribute of runat="server" I have a conflict at runtime and a warning.
ASP.NET runtime error: Code blocks are not supported in this context
The idea is, for example, to evaluate in the ItemDataBound the label1, if it's true must apply a Class on TR to make it grey.
Any idea of the best approach or how to resolve this?
Approach 1:
First, Define a bool property, say ShouldBeGreyed in your data-item class (if possible). This property should return whether the data-item will be greyed out or not.
Then, Use this in your repeater markup:
<ItemTemplate>
<tr<%# ((bool)Eval("ShouldBeGreyed"))?"class='grey'":"" %>>
...
</ItemTemplate>
Approach 2:
First, define a method in code-behind, say ShouldBeGreyed, like this:
protected bool ShouldBeGreyed(object item)
{
// cast to your data-item
var dataItem = (<class-of-your-data-item>)item;
// Determine if it should be greyed out
// bool shouldBeGreyed = ...
...
return shouldBeGreyed;
}
Now use this in your repeater markup:
<ItemTemplate>
<tr<%# ((bool)ShouldBeGreyed(Container.DataItem))?"class='grey'":"" %>>
...
</ItemTemplate>
Use something like this.. Write the method in the Visible portion of the label.
<td><asp:Label runat="server" ID="label2" Visible="<%# MustBeVisible() %>" /></td>
if you want the td to be invisible/visible use this
<td runat="server visible="<%# MustBeVisible() %>"><asp:Label runat="server" ID="label2" /></td>
If you made the <td id="tablerow" runat="server"/> could you use do something like:
tablerow.Attributes.Add("class", className);
Trying to bind a value in code behind to aspx page.
<div>
<table>
<tr>
<th>Item</th>
</tr>
<tr>
<td><asp:Label ID="Label1" runat="server" Text='<%# Eval("ItemId")%>'/></td>
</tr>
</table>
</div>
Code behind:
int ItemId = 3;
NOTE: I have tried:
<%=ItemId%> AND <%:ItemId%>
But no joy! What am I doing wrong? All I want to do is to bind to a single value.
<asp:Label ID="Label1" runat="server" Text='<%# ItemId %>'/>
This is the proper format on the page, but you also need to execute a data binding event in your codebehind:
int ItemId = 3;
this.DataBind();
Although philreed has it right that since you are already using a label, you might as well just update the label.Text property with your value, rather than go through the data binding process. Using the <%# ItemId %> is best for when you want to stick a random data value in the middle of regular page markup, not an ASP control, like so:
<div>
The number you picked is <%# ItemId %>.
</div>
It still needs the DataBind() in your codebehind when doing this.
If its only ever the single value, why not use this in your code behind?
Label1.Text = ItemId.ToString();
and remove the <%# Eval("ItemId")%> from your markup.
<asp:Label ID="Label1" runat="server" Text='<%# ItemId %>'/>
I have a set textboxes where the user enters something and I use them when they click Submit. I need to add a button that lets them add another identical set of textboxes on the fly, enter data into those and then when the submit button is pressed I need to grab the value from both sets. The amount of added sets of items can be unlimited.
What's the best way to handle something like this in ASP.NET/C#?
I've looked around and have basically only gotten that you can try to use JQuery on the front end which leaves the backend a mess or you can try to use a GridView and rebind it every time with new items which can get messy.
Any better/easier way to do this?
Thanks for the help.
Use a Repeater control for the first set of text boxes, and have it repeat for each extra listing.
Here's my comment control repeater. It's a little arcane, as it was the first control I ever made in asp.net, but it should get you going.
<asp:Repeater runat="server" ID="repeater"
onitemdatabound="repeater_ItemDataBound"
>
<HeaderTemplate>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
</HeaderTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
<ItemTemplate>
<tr id="trContents" runat="server"><td>
<table id="tableComment" runat="server"
width="100%" style="border-color:Black; border-width:1px; border-style:solid;background-color:#EEEE99">
<tr><td id="tdHeader" runat="server"
style="border-color:Black; border-width:1px; border-style:solid;padding: 5px">
<table width="100%" id="tableHeader" runat="server">
<tr>
<td>
<asp:Label ID="headerText" runat="server"
Text="<%# GetHeader((CommentRecord)Container.DataItem) %>" />
</td>
<td style="text-align:right"> <%-- OnClientClick="aspnetForm.target ='_blank';" --%>
<asp:Button ID="btnEdit" runat="server" Text="Edit"
PostBackUrl="<%$ AppSettings:TextEditor %>"
/>
<asp:Button ID="btnReply" runat="server" Text="Reply"
PostBackUrl="<%$ AppSettings:TextEditor %>"
/>
</td>
</tr>
</table>
</td></tr>
<tr><td style="border-color:Black; border-width:1px; border-style:solid;background-color:#FFFFF0;padding: 10px">
<%# ((CommentRecord)Container.DataItem).Text %>
</td></tr>
<tr><td>
<table width="100%"><tr>
<td style="text-align:left">
<asp:Button ID="btnDelete" runat="server" Text="Delete"
CausesValidation="False" />
</td>
<td style="text-align:right">
<asp:Label ID="footer" runat="server" Text="<%# GetFooter((CommentRecord)Container.DataItem) %>" />
</td>
</tr></table>
</td></tr>
</table>
<asp:PlaceHolder ID="placeHolder" runat="server" />
</td></tr>
</ItemTemplate>
</asp:Repeater>
What I usually do in these cases is have Javascript that handles the client-side dynamic creation of additional textboxes, then before I submit the values, have all the data collected into a JSON object and save the JSON string into a <asp:HiddenField> control that ASP.NET can read and parse. This isn't a perfectly clean approach, but it is the best thing I have found so far.
I would create the textboxes using jQuery (assigning them a unique id) and then get the values on the server from the Request.Form key/value collection. This would be a rather simple solution.
I would recommend going the GridView way, and bind it to a DataSource object, e.g. ObjectDataSource. Clicking the add button should add an empty row to the data source, and this empty row will automatically be drawn by the GridView. When everything works you can wrap in an UpdatePanel to achieve smooth refresh when adding rows.