referencing control IDs from code behind that is in a repeater - c#

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.

Related

Control 'DataLoading1_gdvDataGroups_ctl01_ctl00' of type 'DataControlLinkButton' must be placed inside a form tag with runat=server

I'm trying to export the contents of an ASP.NET gridView control to an Excel spreadsheet. To do this I've been using the code on this page.
When it gets to the RederControl(hw) line though my code blows up. I get an error like:
GridView must be placed inside a form tag with runat=“server” even after the GridView is within a form tag
To solve this I found this answer. However the main answer does not work and I think it is because my code is in an .ascx user control. With that in mind I tried the solutions in the second highest rated answer.
This time I get error relating to the DataControlLinkButtons similar to the title of this question.
My gridview contains hyperlinks inside in the cells of one column. I tried to remove them from their parent control prior to rendering with the following code (as per the second answer on that page)
List<int> gridIndexes=new List<int>();
for (int i = 1; i < gdvDataGroups.Controls[0].Controls.Count-1; i++)
{
gridIndexes.Add(gdvDataGroups.Controls.IndexOf(gdvDataGroups.Controls[0].Controls[i].Controls[8].Controls[1]));
gdvDataGroups.Controls.Remove(gdvDataGroups.Controls[0].Controls[i].Controls[8].Controls[1]);
}
but it didn't work for me and I got the same error.
Any ideas of how to approach this?
The gridView is as follows (with only the relevant 9th column included):
<asp:GridView ID="gdvDataFiles" SkinID="MediumSpace" runat="server" AutoGenerateColumns="False"
ShowHeader="true" Width="100%" OnPageIndexChanging="gdvDataFiles_PageIndexChanging"
AllowPaging="True" PageSize="20">
<Columns>
<asp:TemplateField HeaderText="Details" ItemStyle-Width="80px" ItemStyle-HorizontalAlign="Center">
<ItemTemplate>
<asp:HyperLink ID="HyperLink1" runat="server" Text='<%# Eval("RequestPKID") == null ? "Not available" : "View" %>'
NavigateUrl='<%# Eval("RequestPKID") == null ? "" : Eval("RequestPkid", "../Pages/BOLoadDetails.aspx?fileid={0}") %>'
Style="padding-top: 4px; display: block" />
</ItemTemplate>
</asp:TemplateField>
</Columns>
<EmptyDataTemplate>
No data file loads found
</EmptyDataTemplate>
</asp:GridView>
Ok turns out that I needed to disable the sorting on the grid prior to rendering the spreadsheet. I think it was the sort control buttons that were causing the problem.

Cant change text/value of textbox inside repeater

Hello and thanks for taking your time to help me.
I'm trying to change the text of a textbox thats located inside my repeater.
<asp:Repeater runat="server" ID="rpCategories">
<HeaderTemplate>
<ul id="nav_down" class="nav_down">
</HeaderTemplate>
<ItemTemplate>
<li><%# Eval("Title") %></li>
</ItemTemplate>
<FooterTemplate>
<li></li>
<li>Contact</li>
<li><a id="cart_logo"></a>
<asp:Panel runat="server" ID="pnlBasket">
<asp:textbox runat="server" id="txtTotalCount" Enabled="false" CssClass="ltTotalCount"></asp:textbox>
</asp:Panel>
</li>
</ul>
</FooterTemplate>
</asp:Repeater>
It's the asp:textbox with the id="txtTotalCount" that I want to change the text of.
Here is my C# code:
TextBox ltTotalCount = (TextBox)FindControl("lblTotalCount");
ltTotalCount.Text = "1";
But if I run the code I get this error : Object reference not set to an instance of an object.
Would be so happy if someone could tell me what I'm doing wrong.
Becuase lblTotalCount is inside a parent control - the repeater, you have to reference it through the repeater.
You should be able to just add the id of your repeater before FindControl, like this...
TextBox ltTotalCount = (TextBox)rpCategories.FindControl("lblTotalCount");
You have to specify the repeater as the parent control to look for the text box and also since it's repeater its quite possible to have more than one text box with that Id so you have to specify which repeater item to look into like so:
TextBox ltTotalCount = rpCategories.Items[0].FindControl("txtTotalCount") as TextBox;
This will return the textbox in the first row of the repeater.
And you should use the Id value not the CssClass value
The ID is probably being 'enhanced' to prevent duplicate IDs in the rendered HTML. You can verify this by looking at the html.
You can add this to the textbox: ClientIDMode="Static" to make the ID stay the same.
You are getting the error because FindControl is returning a null but you are trying to access it anyway.
[Edit] Someone pointed out that this shouldn't work. I agree, here is what does work:
Control FooterTemplate = rpCategories.Controls[rpCategories.Controls.Count - 1].Controls[0];
TextBox MyTextBox = FooterTemplate.FindControl("txtTotalCount") as TextBox;

Creating Survey Questions/Answers for Admin Sections

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.

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.

asp.net web user control with loop

Totally new to webforms user controls, I am bit confused, on how to create a user control and fill some data on it.
for(int i = 0; i < Price.EpList.Count(); i++)
{
Price.EpList[i].Amount.ToString();
Price.EpList[i].Code.ToString();
Price.EpList[i].Desc.ToString();
Price.EpList[i].ID.ToString();
}
EpList is a list that contains info that i want to display in webpage on tabular format with checkboxes on each row.
Take a look at the Repeater Control. You don't have to loop through your list, you just bind the list to the repeater and define the html template you want for each repeated item.
http://www.w3schools.com/aspnet/aspnet_repeater.asp
EDIT: That article uses Visual Basic, so here's the C# translation:
Assuming this repeater:
<asp:Repeater runat="server" ID="uxEpList">
<ItemTemplate>
<%--Html goes here--%>
<%# Eval("Amount")%>
<%# Eval("Code")%>
<%# Eval("Desc")%>
<%# Eval("ID")%>
</ItemTemplate>
</asp:Repeater>
In code behind:
uxEpList.DataSource = Price.Eplist;
uxEpList.DataBind();
If you need to nest a repeater inside another one (using the Desc property from your comment) you can do it like this, by setting the DataSource property declaratively (note the single quotes):
<asp:Repeater runat="server" ID="uxEpList">
<ItemTemplate>
<asp:Repeater Datasource='<%# Eval("Desc")%>' runat="server">
<ItemTemplate>
//etc...

Categories

Resources