How to get the CommandArgument of an ImageButton inside a Repeater - asp.net

I have a repeater which structured like this
<asp:Repeater ID="RpAccBind" runat="server" OnItemDataBound="RpAccBind_ItemDataBound">
<ItemTemplate>
<tr id="acsryRow" runat="server">
<td data-th="Product">
<div class="prodImgMain">
<img src="../instrumentimages/<%# Eval("ProductImage") %>" alt="<%# Eval("ProductName")%>" />
</div>
</td>
<td data-th="Description">
<div class="prodDescriptionContainer">
<ul>
<li>
<span class="prdRow"><%# Eval("ProductName") %></span>
</li>
</ul>
</div>
<div class="quantityIconWrap form-group">
<span class="number-wrapper">
<asp:TextBox Text='<%# Eval("Quantity") %>' ID="txtqty" CssClass="form-control" runat="server" size="3" Width="50" onkeyup="this.value=this.value.replace(/[^0-9]/g,'');" OnTextChanged="txtQtyTextChanged" AutoPostBack="true"></asp:TextBox>
</span>
<span>
<asp:ImageButton ID="lnkAscRemove" runat="server" class="btn" OnClick="lnkRemoveClick" CommandArgument='<%# Eval("ProductId")%>' ImageUrl="../images/deleteIcon.png"></asp:ImageButton>
</span>
</div>
</td>
<td data-th="Amount" style="padding-right: 5%;">
<div class="amountColMain">
<ul>
<li><span><strong><span id="litConPrice" runat="server">$<%# Eval("ConsumerPrice") %></span></strong></span></li>
</ul>
</div>
</td>
<td></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
Now, whenever the txtQty is 0, i want to have the productid in respect of the imagebutton clicked. Right Now, i am using something like
long productId = Convert.ToInt64(((ImageButton)((RepeaterItem)txtQty.Parent).FindControl("lnkAscRemove")).CommandArgument);
It is giving me an error of unable to cast HtmlTableCell to RepeaterItem
Any Kind of help will be appreciated. Thanks in advance

To use CommandName and CommandArgument, you need to use a Command event, not a Click.
<asp:ImageButton ID="lnkAscRemove" runat="server" OnCommand="lnkAscRemove_Command"
CommandArgument='<%# Eval("ProductId")%>'
Code behind
protected void lnkAscRemove_Command(object sender, CommandEventArgs e)
{
Label1.Text = e.CommandArgument.ToString();
}
Update
If you want to get the ProductId from a TextBox, you could add it as a custom property and then read it in code behind.
<asp:TextBox Text='<%# Eval("ProductId") %>' ID="txtqty" runat="server" AutoPostBack="true"
OnTextChanged="txtqty_TextChanged" ProductId='<%# Eval("ProductId") %>'></asp:TextBox>
Code behind
protected void txtqty_TextChanged(object sender, EventArgs e)
{
TextBox tb = sender as TextBox;
Label1.Text = tb.Attributes["ProductId"];
}

The Repeater has an ItemCommand that watches for button events inside the Repeater elements. The CommandName and CommandArgument is passed to the event.
Also of importance is the Item which represents the Repeater Item that the button was clicked in. Then you can use the FindControls method to find related server controls object for the same RepeaterItem in which the button was clicked.
protected void MyRepeater_ItemCommand(Object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "edit") {
SetEditorTo(e.CommandArgument);
}
RepeaterItem row = e.Item;
Textbox tQty = row.FindControls("txtqty");
}

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.

Binding ListView Field to Value in Code-Behind

I'm displaying fields from a DB call in a ListView. I had to re-code my database query because of an issue with repeating groups. I also didn't want to have to deal with nested ListViews. So now I am trying to set the header to the value of radio button list selection. I was trying to write a custom method to return that value but could not remember the syntax.
How can I set the header in the LayoutTemplate from the code-behind so that it doesn't repeat?
<LayoutTemplate>
<div class="resultsGrid">
<strong><%# GetHeader() %></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
I was able to solve this as follows:
<asp:ListView ID="resultsList" ItemPlaceholderID="resultsPlaceHolder"
OnItemCreated="ResultsList_ItemCreated" runat="server">
<LayoutTemplate>
<div class="resultsGrid">
<strong><asp:Label ID="headerLabel" runat="server"></asp:Label></strong>
<asp:PlaceHolder runat="server" ID="resultsPlaceHolder">
</asp:PlaceHolder>
</div>
</LayoutTemplate>
<ItemTemplate>
// rest of data
</ItemTemplate>
</asp:ListView>
And in the code-behind:
protected void ResultsList_ItemCreated(object sender, ListViewItemEventArgs e)
{
if (e.Item is ListViewItem)
{
Label tempLabel = resultsList.FindControl("headerLabel") as Label;
tempLabel.Text = ViewState["ParkName"].ToString();
}
}

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

How to get item click event in asp.net repeater control?

I am using a repeater control to show some data on my page.
The repeater item template has an image and a label field.
I want that when i click the image , I get an event containing the id field of my data item.
How can I achieve this ?
Actually when I click the image i want to go to another page and want to show detailed information of my data item, in repeater i m just showing short information.
My repeater looks like this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<asp:Image ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' />
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
I want to get PhotoID in the event when i click the image.
My photo class looks like this:
public class PhotoDC
{
public byte[] ImagebyteArray { get; set; }
public string Name { get; set; }
public int PhotoID { get; set; }
}
I have been doing winform programming just started web, maybe it is easy but i m struggling to find a solution.
I somehow managed to show hand cursor when i hover the image though.
Try this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<asp:ImageButton ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' OnCommand="Image_Click" CommandName="ImageClick" CommandArgument='<%# Eval("PhotoID") %>' />
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
protected void Image_Click(object sender, CommandEventArgs e)
{
if (e.CommandName == "ImageClick"){
//e.CommandArgument --> photoid value
//Do something
}
}
You can use ItemCommand of repeater control
like this -
protected void itemRepeater_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
if (e.CommandName == "img_Click") // check command is cmd_delete
{
// get you required value
int CustomerID = Convert.ToInt32(e.CommandArgument);
//Write some code for what you need
}
}
}
Personally I think the simplest way to handle something like this is to simply use the ItemTemplate to generate a regular html link, rather than do any thing in the code-behind. Something like this:
<asp:Repeater ID="itemRepeater" runat="server" OnItemCreated="itemRepeater_ItemCreated" >
<ItemTemplate>
<tr>
<td colspan="2">
<a href="/Details.aspx?id=<%=DataBinder.Eval(Container.DataItem, "PhotoID")%>">
<asp:Image ID="phImage" runat="server" ImageUrl='<%#"~/ImageHandler.ashx?id=" + DataBinder.Eval(Container.DataItem, "PhotoID")%>' />
</a>
</td>
<td>
<asp:Label ID="lblImageName" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Name") %>' />
</td>
</tr>
</ItemTemplate>
I know this isn't strictly the question you asked, but IMHO it's the best approach to accomplish the task.

ListView fields not getting posted

I know I've done something like this before, but I have no idea why it isn't working now. I have a ListView with some textboxes. I want to read the text out of those boxes when I click a button (linkbutton, whatever).
<asp:ListView runat="server" ID="lv_bar" EnableViewState="true">
<LayoutTemplate>
<table>
<tr>
<th>Foo</th>
</tr>
<tr runat="server" id="itemPlaceholder"></tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><asp:LinkButton ID="lb_delete" CausesValidation="false" runat="server" Text="Del" /></td>
<td><asp:TextBox id="txt_foo" runat="server" /></td>
</tr>
</ItemTemplate>
</asp:ListView>
<asp:LinkButton ID="lb_add" CausesValidation="false" runat="server" Text="Add" />
And then here's the relevant code-behind stuff:
protected void Page_Load(object sender, EventArgs e)
{
lb_chapter_add.Click += lb_chapter_add_Click;
if (!IsPostBack)
{
lv_chapters.DataSource = new List<Foo>() { new Foo() { Name = "harbl"} };
lv_chapters.DataBind();
}
}
void lb_add_Click(object sender, EventArgs e)
{
foreach (ListViewDataItem item in lv_bar.Items)
{
var txt_foo = (TextBox)item.FindControl("txt_foo");
Response.Write("foo: " + txt_foo.Text);
}
Response.Write("<br />the end");
Response.End();
}
But what I see when I enter some text into txt_foo and click lb_add is just "the end". What am I doing wrong here?
The problem it that you are using a a non persistent object as DataSource.
Due to clicking the button, you generate a postback and lv_chapters does not contain any items. Set a breakpoint in the line where the foreach is and you will see that lv_chapters.Items in null, or that it's Count property returns 0.

Resources