ASP.NET - ImageButton within a Repeater refuses to raise a click event - c#

No matter what combination I try, the button (ibtnDeleteDiaryEntry) simply will not raise an event although it does seem to do postback as it should. ViewState is turned on by default, read elsewhere that it is sometimes problematic. Also, I've used the Repeater's OnItemCommand property as required. Any kind of help is appreciated.
EDIT: It seems that the problem is somehow connected to the jQuery UI's Accordion Widget. The repeater is located within a div that is used to initialize the accordion. If I remove the div tags surrounding the repeater, the OnItemCommand event gets called. Very weird.
Markup:
<asp:Repeater ID="repAccordion" OnItemCommand="repAccordion_OnItemCommand" runat="server">
<ItemTemplate>
<h3> <%# "Date: " + Eval("date", "{0:d}") %>
<span class="deleteButtonContainer">
<asp:ImageButton ID="ibtnDeleteDiaryEntry" CommandArgument='<%# Eval("diary_entry_id") %>' CommandName="Delete" AlternateText="ibtnDeleteDiaryEntry" ImageUrl="images/remove_item.png" runat="server" />
</span>
</h3>
<div>
<table>
<tr>
<td>
<asp:Label ID="lblText" runat="server" ForeColor="#AA0114" Text="Text:"></asp:Label>
</td>
</tr>
<tr>
<td>
<%# Eval("text") %>
</td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
Code-behind:
protected void Page_Load(object sender, EventArgs e)
{
_db = new PersonalOrganizerDBEntities();
_diary_entryService = new Diary_EntryService();
_userService = new UserService();
if (!IsPostBack)
{
LoadItems();
}
}
public void LoadItems()
{
long currentUserId = (long) Session["userId"];
User currentUser = _userService.GetById(currentUserId);
Diary_Entry[] diaryEntriesArray =
_diary_entryService.GetAll().Where(current => current.diary_id == currentUser.user_id).ToArray();
if (diaryEntriesArray.Length == 0)
{
noItems.Text = "You currently have no diary entries.";
noItems.Visible = true;
}
else
{
noItems.Visible = false;
}
repAccordion.DataSource = diaryEntriesArray;
repAccordion.DataBind();
}
protected void repAccordion_OnItemCommand(object sender, RepeaterCommandEventArgs e)
{
Response.Write("test");
}

If it doesn't work I would recommend removing OnItemCommand from repeater and adding OnClick event for ImageButton instead. In OnClick event in code behind you can cast 'sender' to ImageButton and read CommandArgument value to get diary_entry_id.

Related

Sending data from a button inside a repeater control to code-behind

I've got a button inside a repeater control, and I need to send some identifying information from the button to the onClick event so I know which ID has been clicked. My asp.net code (in part) looks like this:
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_ItemDataBound">
<ItemTemplate>
<div class="bevelBox"><h3><b><%#Eval("AlbumName") %> Photo Gallery</b></h3></div>
<asp:Repeater ID="PhotoRepeater" runat="server" onitemcommand="PhotoRepeater_ItemCommand" OnItemDataBound="PhotoRepeater_DataBinding">
<HeaderTemplate>
<div class="bevelBox">
<Table>
<tr>
<td style="width:160px"><h3>Concert Photo</h3></td>
<td style="width:535px"></td>
<td><asp:Button ID="btnAddPhoto" runat="server" OnClick="btnAddPhoto_Click" Text="Add Yours" CommandArgument='<%#Eval("AlbumID") %>' UseSubmitBehavior="false" /></td>
</tr>
</Table>
</div>
Someone told me I could use the CommandArgument command to get this data to the code-behind.
On the C# side, I have this:
protected void btnAddPhoto_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string ggg = btn.CommandArgument.ToString();
mdlAddPhoto.Enabled = true;
mdlAddPhoto.Show();
}
I put a break point on the "string gggg" line, just to see what is being passed back. There's nothing indicating the <%#Eval("AlbumID") %> is being passed back.
Can anyone tell me how I can get this ID data passed back to the C# side?

How to pass variable from textbox to code behind back to same page

I have a webs form page and I have a text box which once clicked passes a variable to the code behind and then back into another element of that page and I cannot get it to work.
This is the closest I have got.
<asp:Panel ID="Search" runat="server" Visible="true">
<tr>
<td>
<asp:Label ID="lblSearch" runat="server" Text="Search"></asp:Label>
</td>
<td>
<asp:TextBox ID="search" runat="server" />
</td>
<td>
<asp:RequiredFieldValidator ID="valSearch" runat="server"
ControlToValidate="movieSearch" Text="Please enter text" />
</td>
<td>
<asp:Button ID="btnSubmit" runat="server" Text="Save"
OnClick="btnSubmit_Click" />
</td>
</tr>
</table>
</asp:Panel>
<asp:Panel ID="pnlSearchResult" runat="server" Visible="false">
<script>
var search = '<%=Server.UrlDecode(Request.QueryString["Data"]) %>';
</script>
</asp:Panel>
And the code behind:
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (IsValid)
{
pnlSearch.Visible = false;
pnlSearchResult.Visible = true;
Response.Redirect("search.aspx?Data=" + Server.UrlEncode(search.Text));
}
}
Also this does not change the visibility of the two panels for some reason.
I would appreciate any guidance I am very new to asp and c#.
The panel's visibility is not changing because you're forcing a new GET request to the page with this: -
Response.Redirect("search.aspx?Data=" + Server.UrlEncode(search.Text));
(I'm assuming your page is called 'search.aspx')
There's no need to do this. Remove this line.
Secondly, I see you want to force the textbox's Text value into a Javascript variable. Replace this
var search = '<%=Server.UrlDecode(Request.QueryString["Data"]) %>';
with this
var search = '<%= search.Text %>';
Write below code on page event.
Another more important point is you first panel Id is "Search" not "pnlSearch" on aspx page so please correct it
protected void Page_Load(object sender, EventArgs e)
{
if (Request.QueryString["Data"] != null)
{
Search.Visible = false;
pnlSearchResult.Visible = true;
}
}
I recommend solution without using Response.Redirect.
Code Behind Submit Button click:
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (IsValid)
{
pnlSearch.Visible = false;
pnlSearchResult.Visible = true;
}
}
In Markup:
<asp:Panel ID="pnlSearchResult" runat="server" Visible="false">
<script>
var searchTxt = document.getElementById('search');
if(searchTxt.value != null && searchTxt.value != ''){
//do your stuff
}
</script>

Showing buttons if list view is empty

I have a list view which retrieves the data from sql data source. I am trying to make two buttons(Yes and No) and a label outside the list view visible only if the list view is not empty. The process is: a person enter the information into text boxes and click the button retrieve, if the entered data exists in the database, the list view shows certain information.
I have the following code:
protected void btnExistingRetrive_Click(object sender, EventArgs e)
{
if (lstExisting.Items.Count>0 )
{
lblIsITYou.Visible = true;
btnYes.Visible = true;
btnNo.Visible = true;
}
}
By default buttons and the label are not visible.
The problem is when i click on retrieve button it shows me the list view with the information but buttons a the label are still not visible. They became visible only when i double click the retrieve button. Please tell me what is my mistake?
Thank you
Use the ListView EmptyDataTemplate
<asp:ListView ID="ContactsListView"
DataSourceID="ContactsDataSource"
runat="server">
<LayoutTemplate>
<table runat="server" id="tblProducts">
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr runat="server">
<td>
<asp:Label ID="FirstNameLabel" runat="Server" Text='<%#Eval("FirstName") %>' />
</td>
<td>
<asp:Label ID="LastNameLabel" runat="Server" Text='<%#Eval("LastName") %>' />
</td>
</tr>
</ItemTemplate>
<EmptyDataTemplate>
<table class="emptyTable" cellpadding="5" cellspacing="5">
<tr>
<td>
<asp:Image ID="NoDataImage"
ImageUrl="~/Images/NoDataImage.jpg"
runat="server"/>
</td>
<td>
No records available.
</td>
</tr>
</table>
</EmptyDataTemplate>
</asp:ListView>
do you bind listview before checking the items count?
Do this on postback instead of in the event.
In your Page_Load do something like this:
protected void Page_Load(object sender, EventArgs e)
{
bool visible = (lstExisting.Items.Count > 0); // assuming it's never null
lblIsITYou.Visible = visible;
btnYes.Visible = visible;
btnNo.Visible = visible;
}
If the above creates complications then do as I said first with postback:
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
bool visible = (lstExisting.Items.Count > 0); // assuming it's never null
lblIsITYou.Visible = visible;
btnYes.Visible = visible;
btnNo.Visible = visible;
}
}

Refreshing UpdatePanel after click event of a Button inside a modalpopup inside a UserControl

I have a page with a listbox and a user control placed inside an update panel like this:
<%# Register TagPrefix="uc1" TagName="CMessage" Src="~/Controls/CMessage.ascx" %>
<ajaxToolkit:ToolkitScriptManager runat="server" ID="ToolkitScriptManager1" EnableScriptGlobalization="true" EnableScriptLocalization="true" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:ListBox ID="lbox" runat="server"></asp:ListBox>
<asp:Button ID="btnDelete" OnClick="btnDelete_Click" runat="server" Text="Delete selected item" Enabled="True"></asp:Button>
<uc1:CMessage ID="CMessage1" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
The page codebehind is like this:
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
lbox.Items.Add("test1");
lbox.Items.Add("test2");
}
}
protected void btnDelete_Click(object sender, EventArgs e)
{
CMessage.MessageConfirm("Delete item?", "Yes", "No", DeleteItem);
}
protected void DeleteItem()
{
lbox.Items.Remove(lbox.SelectedItem);
CMessage.Message("Item deleted succesfully!");
}
The user control is like this:
<%# Control Language="C#" AutoEventWireup="true" CodeFile="CMessage.ascx.cs" Inherits="Controles.CMessage" %>
<table id="tableMessage" runat="server" style="display: none" class="modalPopup">
<tr>
<td>
<asp:Label ID="lb5" runat="server" Text="Message"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Label ID="lbMessage" runat="server"></asp:Label>
</td>
</tr>
<tr>
<td>
<asp:Button ID="btnOk" runat="server" Text="Ok" OnClick="btnOk_Click" />
<asp:Button ID="btnCancel" runat="server" Text="Cancel" OnClick="btnCancel_Click" />
</td>
</tr>
</table>
<asp:Button ID="btnOKError" runat="server" Text="OK" style="display: none" />
<ajaxToolkit:ModalPopupExtender ID="ModalPopupMessage" runat="server" TargetControlID="btnOKError" PopupControlID="tableMessage" OkControlID="btnOKError" CancelControlID="btnOKError"></ajaxToolkit:ModalPopupExtender>
The usercontrol codebehind is like this:
public partial class CMensaje : UserControl
{
public delegate void FunctionButtonPressed();
private FunctionButtonPressed FunctionButtonPressedOk
{
get { return (FunctionButtonPressed)Session["FunctionButtonPressedOk"]; }
set { Session["FunctionButtonPressedOk"]= value; }
}
protected void btnOk_Click(object sender, EventArgs e)
{
ModalPopupMenssage.Hide();
if (FunctionButtonPressedOk!= null)
{
FunctionButtonPressedOk();
}
}
protected void btnCancel_Click(object sender, EventArgs e)
{
ModalPopupMessage.Hide();
}
public void Mensaje(string message)
{
lbMessage.Text = message;
FunctionButtonPressedOk= null;
btnCancel.Visible = false;
ModalPopupMessage.Show();
}
public void MessageConfirm(string message, FunctionButtonPressed FunButtonOkx)
{
lbMessage.Text = message;
FunctionButtonPressedOk= FunBotonAceptarx;
btnCancel.Visible = true;
ModalPopupMensaje.Show();
}
}
Everything works, the popup is shown, the function to call from the page is passed to the usercontrol to trigger it if the user presses ok and triggers correctly etc. But in that last function DeleteItem() the changes done to the page (in this example the item removed from the listbox and the notification message launched) doesnt work.
Its like the updatepanel doesnt refresh. I cant call manually UpdatePanel1.Update() because i have the updatemode as always. In theory in this part of the pagecycle it should refresh the pages with the changes...
I tried adding in the user control pageload the OK button as a PostBackTrigger of the UpdatePanel with no avail and as an AsyncPostBackTrigger.
Keep in mind that this is an slimmed down version of the page and the user control so people can focus on the problem at hand so if you need any more details ask me...
The code flow is like this:
User clicks in the delete item button and triggers the
btnDelete_Click() in the page (first postback)
btnDelete_Click() calls the usercontrol CMessage.MessageConfirm passing DeleteItem as
argument
At the usercontrol MessageConfirm() shows the modalpopup and saves
the argument function DeleteItem() in order to call it later(end of
first postback)
After displaying the modalpopup the user clicks its Ok button and
triggers the btnOk_Click() in the usercontrol (second postback)
At the usercontrol btnOk_Click() calls the DeleteItem() function
that was saved previously
At the page DeleteItem() removes the item from the ListBox (lets say
i dont call the second message to simplify, this would be the end of
the second postback, and the update panel hasnt refreshed :S)
I think i have isolated the problem, moved all the controls and functions from the usercontrol to the page, the problem persisted, but if i called the DeleteItem() function directly instead of his delegate it worked (keep in mind that in both cases the breakpoint at DeleteItem() triggered so the function code was executing correctly):
protected void btnOk_Click(object sender, EventArgs e)
{
ModalPopupMenssage.Hide();
/*if (FunctionButtonPressedOk!= null)
{
FunctionButtonPressedOk();
}*/
DeleteItem(); //page updates correctly! why?
}
Is there some incompatibility with delegates?
In the end i solved it changing the following lines:
if (FunctionButtonPressedOk!= null)
{
//FunctionButtonPressedOk();
Page.GetType().InvokeMember(FunctionButtonPressedOk.Method.Name, BindingFlags.InvokeMethod, null, Page, new []{sender, e});
}
Why it works this way?Whats the difference internally?

Repeater in ASP.net

I used repeater in asp.net. My problem is don't know how to hide a fields in repeater. There is a regular price and now price if regular price is equal to zero it will hide the fields and if not it will show the value of the regular price. i hope you can help on this.
here my code in asp:
<a href="<%=Utility.GetSiteRoot() %>/BookInfo.aspx?SKU=<%# Utility.SKUMask(Eval("lb_sku").ToString()) %>">
<img width="150px" src='<%# Eval("lb_picturepath")%>'>
</td>
<td valign="top">
<asp:Label ID="lb_titleLabel" runat="server" CssClass="center-head" Text='<%# Eval("lb_title") %>' />
<p><asp:Label ID="lb_descriptionLabel" runat="server" Text='<%# Eval("lb_description") %>' /></p>
<div class="price"><%# "Price: " + decimal.Round((decimal)Eval("lb_sellingprice"),2)%></div>
</td>
</tr>
<tr>
<td></td>
<td>
<a class="addtocart" href="<%=Utility.GetSiteRoot() %>/AddToCart.aspx?SKU=<%# Utility.SKUMask(Eval("lb_sku").ToString()) %>" >Add To Cart</a>
<a href="<%=Utility.GetSiteRoot() %>/BookInfo.aspx?SKU=<%# Utility.SKUMask(Eval("lb_sku").ToString()) %>" class="readmore">
View Details
</a></td>
thanks!
You would need to handle the OnItemDataBound event, and then change the visibility of the control. An example of this is shown below:
ASPX Page
<asp:Repeater ID="MyRepeater" OnItemDataBound="MyRepeater_OnItemDataBound" runat="server">
<ItemTemplate>
<asp:Label ID="RegularPriceLabel" runat="server" />
<br/>
<asp:Label ID="BuyNowPriceLabel" runat="server" />
</ItemTemplate>
</asp:Repeater>
Code Behind
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
MyRepeater.DataSource = GetDataSource();
MyRepeater.DataBind();
}
}
protected void MyRepeater_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// This will be your data object
MyEntity o = (MyEntity) e.Item.DataItem;
// Get the labels
Label RegularPriceLabel = (Label) e.Item.FindControl("RegularPriceLabel");
Label BuyNowPriceLabel = (Label) e.Item.FindControl("BuyNowPriceLabel");
// Only show regular price if it is set
RegularPriceLabel.Visible = (o.RegularPrice > 0);
// Populate labels
RegularPriceLabel.Text = o.RegularPrice.ToString();
BuyNowPriceLabel.Text = o.BuyNowPrice.ToString();
}
}
I would take a look at the ItemDataBound event of the Repeater. It will fire for every item in the repeater and allow you to do any code-behind (like hiding labels) more easily.
Edit: For your specific example, since you are formatting the price as well, it may be easier to just call a custom method to to render the price, like so:
ASPX:
<%#RenderPrice((decimal)Eval("lb_sellingprice"))%>
Method:
protected string RenderPrice(decimal price) {
if (price > 0) {
return "Price: $" + decimal.Round(price);
} else {
return string.Empty;
}
}
It's quick-and-dirty but it works.

Categories

Resources