How to loop in repeater dataitems after page post back - asp.net

I have a button in repeater and I want to loop in data items of repeater in this button click event. Here is my code:
protected void btnPromotionButton_OnClick(object sender, EventArgs e)
{
try
{
foreach (RepeaterItem item in rptPromotionProducts.Items)
{
if (item.DataItem == null)
{
continue;
}...
And here is my repeater:
<asp:Repeater ID="rptPromotionProducts" runat="server" OnItemDataBound="rptPromotionProducts_OnItemDataBound">
<ItemTemplate>
<li>
<asp:HyperLink runat="server" ID="hlProduct" CssClass="product_image">
<asp:Image runat="server" ID="imgWindow" />
</asp:HyperLink>
<div class="product_info">
<h3>
<a href="#">
<%# Eval("Name") %></a></h3>
</div>
<div>
<asp:Button ID="btnPromotionButton" runat="server" Text="Sepete Ekle" OnClick="btnPromotionButton_OnClick" />
</div>
</div>
</li>
</ItemTemplate>
</asp:Repeater>
item.DataItem is always comes null however repeater has rows. Is that possible to loop after page post and back?

Similar questions was already answered here and here.
The short answer for this question is NO. You cannot access the DataItem after postback.
Alternatives to retrieve your data would be use a Hidden Field, a DataSource linked to your Repeater or a session object containing the data.

Related

Connecting Session from a repeater's item to another page doesn't work

I want to take the text in the text box from the particular item in the repeater that was clicked, and use it on the page ViewRecipe2.aspx.
Currently, when you click a button on one of the items, it returns back to the repeater's page, but the repeater does not appear, instead of moving to the page ViewRecipe2.aspx.
This is my repeater in aspx:
<asp:Repeater ID="RepeaterR" runat="server">
<ItemTemplate>
<div class="wrapper">
<table>
<div class="box">
<div class="property-card">
<div class="property-image">
<div class="property-image-title">
</div>
</div>
<div class="property-description">
<asp:Button CssClass="h5" runat="server" ID="Button1" OnClick="Button1_Click" Text=<%# Eval("recipeName")%> BackColor="Transparent" BorderColor="Transparent"/>
<p><%#Eval("avgRating") %> stars</p>
<asp:Image class="img" runat="server" src=<%#Eval("recipePic") %> />
<asp:TextBox ID="hiddenTB" runat="server" Text=<%# Eval("recipeName")%> Visible="false"></asp:TextBox>
</div>
</div>
</div>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
This is the code behind on c#:
protected void Button1_Click(object sender, EventArgs e)
{
RepeaterItem item = (sender as Button).NamingContainer as RepeaterItem;
string VR = (item.FindControl("hiddenTB") as TextBox).Text;
if (VR!=null)
{
Session["selectedRecipe"] = VR;
Response.Redirect("ViewRecipe2.aspx");
}
}
This is ViewRecipe2.aspx:
<asp:TextBox ID="TextBoxP" runat="server"></asp:TextBox>
And the code behind:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
string theRecipeName = (Session["selectedRecipe"]).ToString();
TextBoxP.Text = theRecipeName;
}
}
Well, text box or hidden field is "never" null.
but, you need quotes around that "text" setting of the hidden field.
<asp:TextBox ID="hiddenTB" runat="server"
Text='<%# Eval("recipeName")%>' Visible="false">
</asp:TextBox>
Also, keep in mind, that with visible=false, then the markup is NOT sent nor rendered client side. This means that client side js code can't use that text box, but server side code can just fine grab the textbox, and then the value as you have.
However, while you "should" have those single quotes?
it should still have worked.
I would for testing, remove the Visible="false", and then you can actually see + verify that the value is correct.

how to understand which rows selected in repeater?

I have a slideshow that images load from sql server.
here is my html code:
<!-- Elastislide Carousel -->
<ul id="Ul1" class="elastislide-list">
<asp:Repeater ID="Repeater2" runat="server">
<ItemTemplate>
<li>
<asp:Label ID="lbl" runat="server" Text='<%#Eval("IDMusic") %>' Visible="True"></asp:Label>
<asp:ImageButton ID="ImageButton1" runat="server" ImageUrl='<%#Eval("ImageUrl") %>' Width="250px" Height="250px" OnClick="ImageButton1_Click" />
</li>
</ItemTemplate>
</asp:Repeater>
</ul>
<!-- End Elastislide Carousel -->
<br /><br />
</div>
</div>
Now when, I run Project and user click on one of the imageButtons, I want to understand what is he/she clicked? for example he/she click on second ImageButton, Then I want to save IDMusic into a session and use this session in another page but I don't know how can i get IDmusic user clicked on?
here is my code behind :
protected void ImageButton1_Click(object sender, ImageClickEventArgs e)
{
foreach (RepeaterItem item in Repeater2.Items)
{
Label lbl = (Label)item.FindControl("lbl");
if (lbl != null)
{
Session["selectedmusicID"] = lbl.Text;
}
}
Response.Redirect("music.aspx");
}
There is no easy way to do so while handling click on the image itself. However you can leverage ItemCommand event here, which is a repeater event. Basically when some control is clicked inside the repeater, it generates a command in repeater which you can handle, and you can have item-specific arguments for it.
To define a command and args:
<asp:ImageButton ID="ImageButton1" ... CommandName="Select" CommandArgument='<%#Eval("IDMusic") %>' />
Command name here is custom, choose whatever you like. Now subscribe to the event of the repeater:
<asp:Repeater ID="Repeater2" runat="server"
OnItemCommand="Repeater2_ItemCommand">
And to handle:
protected void Repeater2_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "Select") //just in case you have more than one
{
e.CommandArgument //here is your ID
}
}

Nested repeater with button

in my page I have two nested repeaters as follows:
<asp:Repeater runat="server" ID="rptStanze" OnItemDataBound="rptStanze_ItemDataBound">
<ItemTemplate>
<div>
<li class="datatable-item">
<asp:LinkButton runat="server" ID="hypGetDetails" Text="Get Details" OnCommand="GetObjectDetails" />
<div class="col2">DATE</div>
<div class="col3">VISITORS</div>
</li>
<li>
<asp:Repeater runat="server" ID="rptDetails" OnItemDataBound="rptDetails_ItemDataBound">
<ItemTemplate>
<div class="subitem">
<div class="col2"><asp:Literal runat="server" ID="ltlDetTitle" /></div>
<div class="col3"><asp:Literal runat="server" ID="ltlDetViews" /></div>
<div class="col4"><asp:Literal runat="server" ID="ltlDetComments" /></div>
</div>
</ItemTemplate>
</asp:Repeater>
</li>
</div>
</ItemTemplate>
</asp:Repeater>
In the first, I have a LinkButton with a method that fills the nested repeater. Concerning the bounding of data I've no problems, but I dunno how to get the correct nested repeater to fill. In the GetObjectDetails method how can I get it?
In your Command handler, one of the parameters is the button that sent the request, commonly referred to as the "sender". Using that, you just need to find the container of the button that was clicked and then find the repeater within that container.
Here is a C# example:
protected void GetObjectDetails(object sender, CommandEventArgs e)
{
LinkButton hypGetDetails = (LinkButton)sender;
RepeaterItem ri = (RepeaterItem)hypGetDetails.NamingContainer;
Repeater rptDetails = (Repeater)ri.FindControl("rptDetails");
}

asp.net ajax like reorder list

I'm trying to create a draggable list to change the order some pictures are displayed in a product page. I wan't to be able to do this in the product edit page (same place where I add the pics and their description). So, when creating I have nothing inserted on the database and since the AJAX toolkit reorderlist only works with a datasource I was specifying the list as the source of the reorderlist and calling the databind method. In the item template of the reorder list I have a textbox to edit the pic description and a img that displays the photo. I can drag the items and the list gets reordered, however when I click save I can't get the updated text on the textbox and the order property on the picture doesn't get updated. I've tried manually getting the items in the reorderlist but they're always null even though the list shows 20 items the DataItem is empty. I've enabled viewstate and didn't help either.
Here's my code:
<ajaxToolkit:ReorderList ID="rdlPhotos" runat="server" SortOrderField="PhotoOrder" AllowReorder="true" PostBackOnReorder="true" ClientIDMode="AutoID" EnableViewState="true" ViewStateMode="Enabled">
<ItemTemplate>
<div>
<%--<eva:PhotoView ID="iPV" runat="server" Photo='<%# Container.DataItem %>' />--%>
<asp:Image ID="imgPhoto" runat="server" ImageUrl='<%# string.Format("http://eva-atelier.net/sparkle{0}", Eval("Path").ToString().Substring(1)) %>' Width="150" Height="150" />
<div class="formGrid">
<label class="formLabel">Title</label>
<asp:TextBox ID="txtTitle" runat="server" Text='<%#Bind("FileTitle") %>' />
<br />
<label class="formLabel">Description</label>
<asp:TextBox ID="txtDescription" runat="server" Text='<%#Bind("FileDescription") %>' />
<br />
</div>
<p>
<asp:Button ID="btnRemove" runat="server" Text="Remover" />
</p>
</div>
</ItemTemplate>
<ReorderTemplate>
<asp:Panel ID="pnlReorder" runat="server" />
</ReorderTemplate>
<DragHandleTemplate>
<div style="width:20px;height:20px;background-color:Red"></div>
</DragHandleTemplate>
</ajaxToolkit:ReorderList>
And below the C# code:
private void AddPhotosView()
{
if (_currentProduct.Photos != null && _currentProduct.Photos.Count > 0)
{
rdlPhotos.DataSource = _currentProduct.Photos;
rdlPhotos.DataBind();
}
}
I'm new to Asp.net I come from a large WPF background, sorry if I'm making basic question :)
Thanks
For updating order of ReorderList items add your handler for it's OnItemReorder event. In this case your handler may looks like this:
protected void ReorderHandler(object sender, ReorderListItemReorderEventArgs e)
{
var movedPhoto = _currentProduct.Photos[e.OldIndex];
_currentProduct.Photos.RemoveAt(e.OldIndex);
_currentProduct.Photos.Insert(e.NewIndex, movedPhoto);
_currentProduct.Photos.Save();
}
For updating FileTitle and FileDescription of single Photo it is easy to use OnUpdateCommand event of ReorderList and a button with attribute CommandName="Update" for each Photo.
And for updating all Photos at once just iterate through rdlPhotos.Items in next manner:
protected void SaveAllHandler(object sender, EventArgs e)
{
foreach (var riItem in rdlPhotos.Items)
{
var id = ((HiddenField)riItem.FindControl("itemID")).Value;
var title = ((TextBox)riItem.FindControl("txtTitle")).Text;
var description = ((TextBox)riItem.FindControl("txtDescription")).Text;
UpdatePhoto(id, title, description);
}
}
Remember that rdlPhotos.Items here are in initial order. And for identifying which Photo should be updated add hidden field with Photo.ID-value to ReorderList's ItemTemplate like this:
<asp:HiddenField runat="server" ID="itemID" Value='<%# Eval("ID") %>' />

Dynamicly created repeater and ItemCommand event problem

A strange problem.
On my page i have a placeholder where I create a repeater on run time.
In ItemTemplate i have a button that invokes repeater_ItemCommand event.
I put a breakpoint on first line of repeater_ItemCommand event, when the button is triggered the event is invoked as planned, but after RebindRepeaters() is finished, when i click on the button again repeater_ItemCommand event is not invoked!
Only if i click on the button one again it invokes, in other scenarios(this is simple version of my page, in original page i have updatepanel that complex everything) it never invokes!
My aspx code:
<form id="form1" runat="server">
<div id="talk">
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
</div>
My Code-behind:
protected void Page_Init(object sender, EventArgs e)
{
RebindRepeaters();
}
void RebindRepeaters()
{
PlaceHolder1.Controls.Clear();
CreateRepeater(PlaceHolder1);
}
void CreateRepeater(Control container)
{
Repeater repeater1 = new Repeater();
repeater1.ItemCommand += new RepeaterCommandEventHandler(repeater_ItemCommand);
repeater1.ItemTemplate = Page.LoadTemplate("CommentsTemplate.ascx");
container.Controls.Add(repeater1);
repeater1.DataSource = Comment.GetCommentsP(8, 0);
repeater1.DataBind();
}
void repeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
switch (e.CommandName)
{
case "Edit":
RebindRepeaters();
break;
}
}
The CommentsTemplate.ascx:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="CommentsTemplate.ascx.cs" Inherits="CommentsTemplate" %>
<ul>
<li>
<div class="show">
<div class="c">
<asp:LinkButton ID="lbtnTitle" runat="server" Text='<%#Eval("EncodedTitle")%>'
CausesValidation="false" CommandName="VoteUp" OnClientClick="viewHide(this);return false;" CommandArgument='<%#Eval("ID")%>'></asp:LinkButton>
<p class="d"><%#Eval("AddedBy")%>,<%#Eval("AddedDate")%></p>
<div class="CommentBody"><%# Eval("EncodedBody") %>
</div>
</div>
<div class="userpanel">
<asp:Panel runat="server" ID="panAdmin" Visible='<%# UserCanEdit %>' style="float:left;">
<asp:ImageButton runat="server" ID="btnSelect" CommandName="Edit" CommandArgument='<%# Eval("ID") %>'
CausesValidation="false" AlternateText="Edit comment" ImageUrl="~/Images/Edit.gif" />
<asp:ImageButton runat="server" ID="btnDelete" CommandName="Delete" CommandArgument='<%# Eval("ID") %>'
CausesValidation="false" AlternateText="Delete comment" ImageUrl="~/Images/Delete.gif"
OnClientClick="if (confirm('Are you sure you want to delete this comment?') == false) return false;" />
</asp:Panel>
</div>
</div>
</li>
</ul>
If you need more info just ask.
Could you try overidding createChildcontrols and add the RebindRepeaters call there instead of in Page_Init? And make sure to give your repeater an explicit ID:
Repeater repeater1 = new Repeater();
repeater1.ID = "repeater1";
Without an id the asp.net event handling won't know where the event was called from.
Dynamic controls have to be re-added on every postback in order for their events to fire. A new control tree is being created on the postback and the dynamic control is no longer in it, therefore ASP.NET can't evaluate the change in order to fire the event.
EDIT: I was able to fire the event each click by removing RebindRepeaters(). You were binding it twice, once here and once in (Page_Init):
void repeater_ItemCommand(object sender, RepeaterCommandEventArgs e)
{
switch (e.CommandName)
{
case "Edit":
//RebindRepeaters();
break;
}
}

Resources