Get dynamic controls and text in Repeater - c#

I have a Repeater which loads some data from a SQL database
<asp:Repeater ID="Repeater" runat="server" OnItemDataBound="Repeater_ItemDataBound">
<ItemTemplate>
<asp:Label ID="QuestionLabel" runat="server" Text=""></asp:Label>
<asp:TextBox ID="AnswerLabel" runat="server"></asp:TextBox>
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="AnswerSubmit" runat="server" Text="Insert"/>
In code behind, i assign to get the questions on another button click to load and bind the Repeater. In ItemDataBound i find the controls and assign the questions to the label.
How should i get the answers that the user enters and store the ID of the question with the answer they enter in a button click event?
At first, I tried this in the button click event
foreach (RepeaterItem item in Repeater.Items)
{
Label QuestionLabel = (Label)item.FindControl("QuestionLabel");
}
but it couldnt find the QuestionLabel. Looking at the page source i believe thats due to the label having a different value (QuestionLabel_0, QuestionLabel_1 etc), so struggling to find a way to approach this?
Edit
protected void QuestionButton_Click(object sender, EventArgs e)
{
Repeater.DataSource = QuestionsByID(ID);
Repeater.DataBind();
}

You see
foreach (RepeaterItem item in Repeater.Items)
{
if (item.ItemType == ListItemType.Item
|| item.ItemType == ListItemType.AlternatingItem)
{
Label QuestionLabel = (Label)item.FindControl("QuestionLabel");
}
}

Related

get selected value by drop down list in a repeater by CommandArgument of link button

I have a repeater that in it has one dropdown list and one linkbutton.
I want to get the selected value of the dropdown list by CommandArgument in linkbutton, but it just knows default value of dropdown list.
My code :
<asp:Repeater runat="server" ID="Repeater1" OnItemDataBound="Page_Load2"OnItemCommand="list_ItemCommand" >
<ItemTemplate>
<asp:DropDownList ID="dlPricelist" CssClass="width100darsad dropdownlist" runat="server" AutoPostBack="true" ViewStateMode="Enabled" >
</asp:DropDownList>
<asp:LinkButton ID="btnAddToCart" runat="server" class="btn btn-success btnAddtoCardSinglepage" CommandArgument='<%#Eval("id") %>' CommandName="addtocard">اضافه به سبد خرید</asp:LinkButton>
<asp:Label ID="xxxxxx" runat="server" Text="Label"></asp:Label>
</ItemTemplate>
</asp:Repeater>
Code behind:
protected void Page_Load2(object sender, RepeaterItemEventArgs e)
{
if (!IsPostBack)
{
string id = Request.QueryString["id"].ToString();
DataSet dsselectcategory = BLLTour.left3join(id.Trim().ToString());
var dlPricelist = (DropDownList)e.Item.FindControl("dlPricelist");
dlPricelist.DataSource = dsselectcategory.Tables[0];
dlPricelist.DataTextField = "pricelistPrice";
dlPricelist.DataValueField = "priceid";
dlPricelist.DataBind();
}
}
protected void list_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "addtocard")
{
foreach (RepeaterItem dataItem in Repeater1.Items)
{
Label xxxxxx = (Label)e.Item.FindControl("xxxxxx");
LinkButton btnAddToCart = (LinkButton)e.Item.FindControl("btnAddToCart");
xxxxxx.Text = ((DropDownList)dataItem.FindControl("dlPricelist")).SelectedItem.Text; //No error
}
}
}
I don't know how I should fix it.
You are using very old technology to show data that's not appropriate.
But if you are serious to use it, you must use FindControll method in ItemTemplate of your repeater control. You should find dropdownlist first, and then cast it to a object to be able to use it's value.

Iterate through repeater

There's this repeater...
<asp:Repeater ID="myRepeater" OnItemCommand="rpt1_ItemCommand" runat="server" OnItemDataBound="rpt1_OnItemDataBound">
<HeaderTemplate>
<table width="99%" border="0" cellpadding="0" cellspacing="0">
<tr class="lgrey">
<td>Default</td>
</tr>
</HeaderTemplate>
<ItemTemplate>
<table>
<tr>
<td>
<asp:LinkButton ID="lnk1" Text="Make Default" CommandName="SetDefault" runat="server" Visible="True" CommandArgument='<%#Eval("UserID") %>' CausesValidation="false"></asp:LinkButton>
<asp:Label ID="label1" Text="Yes" runat="server" Visible="False"></asp:Label>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
What I want is that when user clicks on any of the "lnk1" link button in the lsit that repeater renders,
the link should be replaced with the label "label1"..ie when the user clicks on "Make Default" link, it should be replaced
with "Yes" label
Now when I click 2 link buttons, both get their label "Yes" displayed where as I want only one link button to display Yes
ie the one which has been clciked and rest of the items should display "Make Default" link button only.
ie Only ONE item should be displaying "Yes" label...now how do I iterate through the repeater items to set only ONE item
as default and not multiple ??
You can iterate the repeater items collection,
protected void myRepeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
int selectedIndex = e.Item.ItemIndex;
foreach(RepeaterItem item in myRepeater.Items)
{
((LinkButton)item.FindControl("lnk1")).Visible = (item.ItemIndex != selectedIndex);
((Label)item.FindControl("label1")).Visible = (item.ItemIndex == selectedIndex);
}
}
The pros of this option are: 1. no second hit on the database.
Or I would put my logic in the ItemDataBound event instead, store the clicked link button index in a member variable and call DataBind in the command event handler.
private int selectedIndex = -1;
//...
protected void myRepeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
selectedIndex = e.Item.ItemIndex;
myRepeater.DataSource = MyGetDataMethod();
myRepeater.DataBind();
}
In the ItemDataBound handler compare the current index with the stored index and if they match show the label.
protected void myRepeater_ItemDataBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if(e.Item.ItemIndex == selectedIndex)
{
((LinkButton)e.Item.FindControl("lnk1")).Visible = false;
((Label)e.Item.FindControl("label1")).Visible = true;
}
}
}
The cons of this second option are: 1. A second hit on the database. 2. If the user clicks say row two, and some other user inserts a new address record, row 2 may now be something different when you re-bind. Also if you're not using an order by that could change between database calls and your stored selectedIndex could be invalidated thatway too.
So in conclusion I'd go with option one now I've thought it all the way through.

find current element in repeater

How can i get current MainNavigationMenu hyprelink in code behind and check if is current menu clicked then i will change him default CSS.
I try with this code but is always null
HyperLink mainNavigationMenu = siteMapAsBulletedList.FindControl("MainNavigationMenu") as HyperLink;
full repeater code:
<asp:Repeater runat="server" ID="siteMapAsBulletedList" DataSourceID="smdsMenu">
<HeaderTemplate>
<li><asp:HyperLink ID="MainNavigationMenu" runat="server" NavigateUrl='<%#SiteMap.RootNode.Url%>'
Text='<%#SiteMap.RootNode.Title%>'></asp:HyperLink></li>
</HeaderTemplate>
<ItemTemplate>
<li><asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl='<%#Eval("Url")%>' Text='<%#Eval("Title")%>'></asp:HyperLink></li>
</ItemTemplate>
</asp:Repeater>
Are you verifying which type of repeater item you are looking at ?
Attach an ItemDataBound to your repeater and do something like this :
private void rptPanier_ItemDataBound(Object sender , RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Header)
{
var myItem = (Hyperlink)e.Item.FindControl("YourControlName");
}
}
Then you will have a reference on it and you can do whatever you want !
Beware tho, the ItemData item, which can be found in the repeateritemeventargs, is always null when the repeater is creating the header.
Hope this helps !
The repeater has a collection of Items. Each Item is a RepeaterItem, which has an ItemType property. For header items, this value will be "ListItemType.Header". Therefore, you want to perform .FindControl() upon that particular repeater item, not the entire Repeater itself.

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");

Databinding a List to a usercontrol in an Item Template in codebehind

I have a DataList like below:
<asp:DataList runat="server" ID="myDataList">
<ItemTemplate>
<uc:MyControl ID="id1" runat="server" PublicProperty='<%# Container.DataItem %>' />
</ItemTemplate>
</asp:DataList>
The Item Template is simply a registered usercontrol, MyControl. The DataSource for the DataList is a List<List<T>> and MyControl's PublicProperty is passed List<T> which it then peforms its own databinding on. This works fine, but I have a general aversion to databinding in the aspx/c page. What is the most efficent way to set the PublicProperty value in the code behind?
If in line data binding syntax is not good enough for you - you can always hook into the ItemDatabound event of the DataList.
<asp:DataList runat="server" ID="myDataList"
OnItemDataBound="DataList_ItemDataBound">
<ItemTemplate>
<uc:MyControl ID="id1" runat="server" />
</ItemTemplate>
</asp:DataList>
Then, in the code behind of your page/containing control you can add your ItemDataBound event.
protected void DataList_ItemDataBound(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item
|| e.Item.ItemType == ListItemType.AlternatingItem)
{
DataListItem item = e.Item;
//List<string> or whatever your data source really is...
List<string> dataItem = item.DataItem as List<string>;
MyControl lit = (MyControl)item.FindControl("id1");
lit.PropertyName = dataItem;
}
}
For more information on the DataList.ItemDataBound event - Read Here
If you would rather not declare your ItemDataBound delegate inline in the ASPX you could also do it in the code behind - probably in your Page Load event:
myDataList.ItemDataBound += DataList_ItemDataBound;
Hope that helps

Categories

Resources