Asp.Net Button click Event inside Repeater inside UpdatePanel - c#

I am trying to use a Repeater inside a Updatepanel and have Buttons that delete one entery in the Database and get the new Data for the Repeater and Update the Panel. I have tried a LinkButton, but it does always postback and the page relodes. Then i tried a regular Button and create a Event for that Button on DataBound Event. But it doesnt work. Here is the code:
aspx file:
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel runat="server" id="Panel">
<ContentTemplate>
<table cellpadding="0" cellspacing="0" id="saveTable">
<tr style="font-weight: bold;">
<td>Erstellt am</td>
<td>Anforderer</td>
<td>Werk</td>
<td>Gebäude</td>
<td>Start Datum</td>
<td>Löschen</td>
<td>Benutzen</td>
</tr>
<asp:Repeater ID="Repeater1" runat="server" onitemdatabound="Repeater1_ItemDataBound">
<ItemTemplate>
<tr id="Meldung<%# DataBinder.Eval(Container.DataItem,"meldungId")%>">
<td><%# DataBinder.Eval(Container.DataItem, "timestamp").ToString().Substring(0, 10)%></td>
<td><%# DataBinder.Eval(Container.DataItem,"nameAnforderer") %></td>
<td><%# DataBinder.Eval(Container.DataItem,"Werk") %></td>
<td><%# DataBinder.Eval(Container.DataItem,"Building") %></td>
<td><%# DataBinder.Eval(Container.DataItem,"startDatum").ToString().Substring(0, 10) %></td>
<td>
<asp:Button runat="server" ID="test"/>
</td>
<td></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</ContentTemplate>
</asp:UpdatePanel>
and in the code behind i give the Button with id = test a event
protected void deleteMeldung(object sender, EventArgs e) {
System.Threading.Thread.Sleep(5000);
}
protected void Repeater1_ItemDataBound(object source, RepeaterItemEventArgs e) {
RepeaterItem repeaterSource = e.Item;
Button btn1 = repeaterSource.FindControl("test") as Button;
DataRowView drv = e.Item.DataItem as DataRowView;
string meldungId = drv.Row["meldungId"].ToString();
btn1.ID = "myNewButton"+meldungId;
btn1.Click += new EventHandler(deleteMeldung);
btn1.Text = "delete";
}
so whats working is passing the Text and the ID to each button like that. But the Buttons do not have the Click Event to call deleteMeldung()

What I tend to do is to have a separate delete button outside of the repeater (this is usually asp:Button with style set to 'display:none' along with a hidden field. Lets call these B_Delete and HF_DeleteId.
The buttons inside of the repeater do not cause postback themselves, but they only set the ID of the given row to the hidden field HF_DeleteId, and then call $('#B_Delete').click() (where the B_Delete should be replaced with current ClientID of the button). Then in the server method B_Delete_Click you can retrieve the ID of the row to be deleted from the hidden field. Works with update panels no problem. No need to mess with triggers and handling events from dynamically generated buttons.
It may look like this:
<asp:UpdatePanel runat="server" ID="UP_Rptr" UpdateMode="Conditional">
<ContentTemplate>
<asp:Repeater runat="server" ID="RPTR_DeleteTest" EnableViewState="False" OnItemDataBound="RPTR_DeleteTest_ItemDataBound">
<ItemTemplate>
<div>
<span><%# Eval("ID") %></span>
<span><%# Eval("Name") %></span>
<span><asp:LinkButton runat="server" ID="LB_Delete" Text="delete"></asp:LinkButton></span>
</div>
</ItemTemplate>
</asp:Repeater>
<asp:HiddenField runat="server" ID="HF_DeleteId" />
<asp:Button runat="server" ID="B_Delete" OnClick="B_Delete_Click" Style="display:none;" />
</ContentTemplate>
</asp:UpdatePanel>
And the server methods:
protected void RPTR_DeleteTest_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var lb = e.Item.Controls[1] as LinkButton; // for simplicity only - do not use code like this
lb.OnClientClick = String.Format("$('#{0}').val('{1}');$('#{2}').click();return false;",
HF_DeleteId.ClientID,
DataBinder.Eval(e.Item.DataItem, "ID"),
B_Delete.ClientID);
}
protected void B_Delete_Click(object sender, EventArgs e)
{
int id = Int32.Parse(HF_DeleteId.Value);
// do your sanity checks and deletion logic here
}

i tried Pafkas solution and it worked, thank you for that. However, i was intressted if there is any other way to solve this problem and i found another solution, i registred every LinkButton with the ScriptManager like that:
btn1.Click += new EventHandler((sender1, e1) => deleteMeldung(sender1, e1, meldungId));
ScriptManager scriptManager = ScriptManager.GetCurrent(Page);
if (scriptManager != null) {
scriptManager.RegisterAsyncPostBackControl(btn1);
}
and with this link button :
<asp:LinkButton runat="server" ID="test"/>
it worked, it fired the deleteMeldung method without reloding und passed the parameter meldungId to delete the enterie and updates the new Data to the UpdatePanel

Related

How to access Listview items to codebehind using asp.net

Iam using a listview to display table contents,How can i access a values form listview to code behind in button click
aspx
<LayoutTemplate>
<table runat="server" id="table1">
<tr id="Tr1" runat="server">
<th class="tablehead"id="mname">Movie Name</th>
<th class="tablehead">Movie Genre</th>
<th class="tablehead">Runtime</th>
</tr>
<tr runat="server" id="itemPlaceholder"></tr>
<ItemTemplate>
<tr id="Tr2" runat="server" class="tablerw">
<td style="background-color:#EEEEEE;width:100px;" class="tablerw"><asp:Label ID="Label5" runat="server" Text='<%#Eval("MovieName") %>' /></td>
<td style="background-color:#EEEEEE;width:100px;"><asp:Label ID="NameLabel" runat="server" Text='<%#Eval("movieGenre") %>' /></td>
<td style="background-color:#EEEEEE;width:100px;"><asp:Label ID="Label1" runat="server" Text='<%#Eval("Runtime") %>' /></td>
<td>
<asp:Button ID="Button1" runat="server" Text="Approve" OnClick="Button1_Click"></asp:Button>//Here is my button
</ItemTemplate>
aspx.cs
protected void Button1_Click(Object sender,
System.EventArgs e)
{
//I want to access value here
}
I want to get Movie Name,Movie Genre,Runtime to code behind.. Any help is appreciated..
Proper way to deal with button control click event in data bound controls is by setting a CommandArgument & CommandName properties. Instead of registering a click handler of button you can register a ItemCommand event of ListView. This way whenever a button is clicked then this event is raised and you can find the data correctly like this:-
Add CommandName & CommandArgument properties to your button and remove the click handler:-
<asp:Button ID="Button1" runat="server" Text="Approve" CommandName="GetData"
CommandArgument='<%# Eval("MovieId") %>' ></asp:Button>
Next, register the ItemCommand event with your listview:-
<asp:ListView ID="lstMovies" runat="server" OnItemCommand="ListView1_ItemCommand">
Finally in the code behind, in ListView1_ItemCommand method check if event is raised by your button and find all the respective controls:-
protected void ListView1_ItemCommand(object sender, ListViewCommandEventArgs e)
{
if (e.CommandName == "GetData")
{
if (e.CommandSource is Button)
{
ListViewDataItem item = (e.CommandSource as Button).NamingContainer
as ListViewDataItem;
Label NameLabel = item.FindControl("NameLabel") as Label;
Label Label5 = item.FindControl("Label5") as Label;
//and so on..
}
}
}

How to get items row id of repeater when user clicks rows linkbutton control

I have a repeater, nested with Html table rows:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<HeaderTemplate>
<table id="grid">
<thead>
<tr>
<th>SID</th>
<th>Start Date</th>
<th>End Date</th>..
<th>PDF Text</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#DataBinder.Eval(Container.DataItem,"ID") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"startDate") %></td>
<td><%#DataBinder.Eval(Container.DataItem,"endDate") %></td
<td>
<asp:LinkButton runat="server" ID="lbtnPDF" Text="PDF Full Text" OnClick="lbtnPDF_Click" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</asp:Repeater>
When the user clicks on linkbutton, I want to get the ID of that row of repeater item and will display the PDF file which is related to that ID, in another aspx page.
I wrote on itemdatabound event :
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
LinkButton lnkBtn = (LinkButton)e.Item.FindControl("lbtnPDF");
}
How can I get column Id of repeater nested with an html table?
I don't think you are following the right approach to do it. I would choose the benefits of Repeater's ItemCommand Event to do it.
The following code might be helpful to you:
HTML/ASP.net
<asp:Repeater ID="Repeater1" DataSourceID="SqlDataSource1" runat="server" OnItemCommand="Repeater1_ItemCommand">
<ItemTemplate>
<asp:Button ID="Button1" runat="server" Text='<%#DataBinder.Eval(Container.DataItem,"Username") %>' CommandName="ViewPDF" CommandArgument='<%#DataBinder.Eval(Container.DataItem,"ID") %>' />
</ItemTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString='<%$ ConnectionStrings:myConnString %>' SelectCommand="SELECT * FROM [tblUserAccounts]"></asp:SqlDataSource>
As you have noticed, I have used CommandName and CommandArgument attributes in the label. I have used CommandName attribute to identify which action the user is expecting. Also the CommandArgument to pass the required data object to server.
Go to Repeater's OnItemCommand instead of ItemDataBound event. And write the code as below;
protected void Repeater1_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ViewPDF")
{
Response.Redirect("~/MyPDFFiles/" + (string)e.CommandArgument);
}
}
Now run and test your Application!
Hope this helps!

Repeater in UpdatePanel Only Updates After Button Is Submitted A Second Time

I have a repeater in an UpdatePanel and when I add some text and submit a button, the update does not appear immediately, but only after I submit the button a second time.
Any thoughts as to why this is happening?
Thanks.
<asp:UpdatePanel ID="updateStatus" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<table border="">
<tbody>
<asp:TextBox Width="520" Height="35" style="font-size:13px;padding-left:0px;padding-right:0px;" id="txtStatusUpdate" runat="server"></asp:TextBox>
<asp:UpdatePanel ID="updButton" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:Button style="font-size:25px;padding-left:0px;padding-right:0px;" ID="btnAddStatus" runat="server" Text="Add" OnClick="btnAddStatus_Click" />
</ContentTemplate>
</asp:UpdatePanel>
<asp:Repeater ID="repFilter" runat="server">
<ItemTemplate>
<tr>
<td class="date"><%# String.Format("{0:MM/dd/yyy}", ((Alert)Container.DataItem).CreateDate) %></td>
<td><%# ((Alert)Container.DataItem).Message %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
</table>
</ContentTemplate>
</asp:UpdatePanel>
protected void Page_Load(object sender, EventArgs e)
{
_presenter = new RespondentProfilePresenter();
_presenter.Init(this);
}
protected void btnAddStatus_Click(object sender, EventArgs e)
{
StatusUpdate su = new StatusUpdate();
su.CreateDate = DateTime.Now;
su.AccountID = _userSession.CurrentUser.AccountID;
su.Status = txtStatusUpdate.Text;
_statusRepository.SaveStatusUpdate(su);
_alertService.AddStatusUpdateAlert(su);
updateStatus.Update();
//_redirector.GoToHomePage();
}
public void ShowAlerts(List<Alert> alerts)
{
repFilter.DataSource = alerts;
repFilter.DataBind();
if (repFilter.Items.Count == 0)
{
//lblMessage.Text = "You don't have any alerts yet!";
}
}
EDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDITEDIT EDIT
I have updated the HTML (I have taken out the second UpdatePanel) but am still getting the same results - the most recent update does not post until the second time the button submits.
<asp:UpdatePanel ID="updateStatus" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:TextBox Width="520" Height="35" style="font-size:13px;padding-left:0px;padding-right:0px;" id="txtStatusUpdate" runat="server"></asp:TextBox>
<asp:Button style="font-size:25px;padding-left:0px;padding-right:0px;" ID="btnAddStatus" runat="server" Text="Add" OnClick="btnAddStatus_Click" />
<table border="">
<tbody>
<asp:Repeater ID="repFilter" runat="server">
<ItemTemplate>
<tr>
<td class="date"><%# String.Format("{0:MM/dd/yyy}", ((Alert)Container.DataItem).CreateDate) %></td>
<td><%# ((Alert)Container.DataItem).Message %></td>
</tr>
</ItemTemplate>
</asp:Repeater>
</tbody>
</table>
</ContentTemplate>
</asp:UpdatePanel>
public class RespondentProfilePresenter
{
//CODE HERE....
public void Init(IRespondentProfile View)
{
_view = View;
_view.SetAvatar(_accountBeingViewed.AccountID);
_view.DisplayInfo(_accountBeingViewed);
if (_userSession.CurrentUser != null)
ShowDisplay();
TogglePrivacy();
}
private void ShowDisplay()
{
List<Alert> _objAlerts = _alertService.GetAlertsByAccountID(_userSession.CurrentUser.AccountID);
_view.ShowAlerts(_objAlerts);
}
}
Its a bit hard for me to follow your code, as I dont have your BL classes (Alert, IREspondedProfile etc), so Im going to half guess:
Within your page load, you call the Init method of the RespondentProfilePresenter class.
This method calls ShowDisplay, which eventually binds the repeater.
Notice that this happens BEFORE the event handler of the pressed button is fired, which is the place in code where You update your alerts list.
Your new alert is added AFTER the data source for the repeater is set, and therefor You only see the update on every other button click. You need to reorder Your code in such way that the DataBind will occur only AFTER the addition of the new alert.

Use repeater to display all the threads in same topic question

I want to use asp.net repeater control to display all threads that under same topic. Each thread has three buttons--reply,edit and delete. Besides buttons, I also want to display author, subject, post time and content. I have two questions here regarding to how to write button click event and binding data to a div in backend. My front end code is as following:(I use c#)
<asp:Repeater ID="Repeater1" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td colspan="2">
<asp:Button ID="btn_Reply" runat="server" Text="Rreply" OnClick="btn_Reply_Click" />
<asp:Button ID="btn_Edit" runat="server" Text="Edit" OnClick="btn_Edit_Click" CommandArgument='<%Eval("id").ToString() %>' />
<asp:Button ID="btn_Delete" runat="server" Text="Delete" OnClick="btn_Delete_Click" CommandArgument='<%Eval("id").ToString() %>' />
</td>
</tr>
<tr>
<td align="right" width="100px">Author:</td>
<td><%#Eval("owner") %></td>
</tr>
<tr>
<td align="right" width="100px">Subject:</td>
<td><%#Eval("title") %></td>
</tr>
<tr>
<td align="right" width="100px">Post Time:</td>
<td><%#Eval("timePosted") %></td>
</tr>
<tr>
<td colspan="2">
<div id="contentDiv" runat="server" ondatabinding="contentDiv_DataBinding"></div>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Question 1: how to write button click event in backend, for example I want to use CommandArgument of edit button, what's the click event should be?
protected void btn_Edit_Click(object sender,??//I don't know how to write the second)
Question 2: the content stored in database is in html format, What to write in contentDiv_DataBinding event?
protected void contentDiv_DataBinding(object sender, System.EventArgs e)
{
//seems it can not find contentDiv, otherwise, I'll just use contentDiv.html=<%#Eval("content") %>
}
Thank you in advance!
As the control is nested inside the Repeater, you must refer to it by finding it inside the item being data bound:
protected void Repeater_DataBinding(object sender, System.EventArgs e)
{
HtmlControl contentDiv = e.item.FindControl("contentDiv");
}
However, I think it would be better to put a Literal control inside the Div and refer to that instead:
<div id="contentDiv" runat="server">
<asp:literal id="ltlContent" runat="server" />
</div>
protected void Repeater_DataBinding(object sender, System.EventArgs e)
{
Literal ltlContent = e.item.FindControl("ltlContent");
ltlContent = e.Item.DataItem("content");
}
Regarding controlling the buttons inside the Repeater, you can add a CommandName to the button and call this in the ItemCommand event:
<asp:Button ID="btn_Reply" runat="server" Text="Rreply" CommandName="Reply" CommandArgument='<%Eval("id")%>' />
<asp:Button ID="btn_Edit" runat="server" Text="Edit" CommandName="Edit" CommandArgument='<%Eval("id").ToString() %>' />
<asp:Button ID="btn_Delete" runat="server" Text="Delete" CommandName="Delete" CommandArgument='<%Eval("id").ToString() %>' />
protected void contentDiv_ItemCommand(object sender, System.EventArgs e)
{
if (e.CommandName == "Reply"){
}
if (e.CommandName == "Edit"){
}
if (e.CommandName == "Delete"){
}
}
Finally, change your Repeater tag to:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater_DataBinding" OnItemCommand="contentDiv_ItemCommand">

Adding javascript to a link's OnClientClick property while binding a repeater

I'm trying to get this working but no success:
<asp:Repeater ID="Repeater1" runat="server" OnItemCommand="btnDeleteFamily_Click">
<HeaderTemplate>
<table>
<tr>
<th width="90" valign="top"><%=getTag("name")%></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#Eval("chrname")%></td>
<asp:LinkButton ID="btnDeleteFamily" CssClass="fRight ui-icon ui-icon-trash" runat="server" CommandName="delete" CommandArgument='<%#Eval("idmember")%>' OnClientClick='return confirm("<%= getTag("deletefamilymemberdialog") %>")' Text="" ValidationGroup="delete_family" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
When clicking on the btnDeleteFamily OnClientClick the confirm dialog is not shown.
getTag (method in the code behind) is used for localization to get the text depending on the language. My intention is to show that message in the JavaScript dialog, but I'm getting:
<a href="javascript:__doPostBack('ctl00$ContentPlaceHolder1$rptFamily$ctl01$btnDeleteFamily','')" class="fRight ui-icon ui-icon-trash" id="ctl00_ContentPlaceHolder1_rptFamily_ctl01_btnDeleteFamily" onclick='return confirm("<%= getTag("deletefamilymemberdialog") %>");'/>
So it's not processing getTag in the server side otherwise I would be getting
onclick='return confirm("Are you sure that you want to delete this entry?");'
Thanks
I think writing the message to page as a javascript variable is a better solution :
<script>
var deleteMemberDialogMessage = '<%= getTag("deletefamilymemberdialog") %>';
</script>
And your repeater :
<asp:LinkButton ID="btnDeleteFamily" CssClass="fRight ui-icon ui-icon-trash"
runat="server" CommandName="delete" CommandArgument='<%#Eval("idmember")%>'
OnClientClick='return confirm(deleteMemberDialogMessage)' Text=""
ValidationGroup="delete_family" />
By the way be sure that your deletefamilymemberdialog message doesn't have single quote.
EDIT : If you want to bind a value from your datasource to your repeater, you should bind your column to control instead of Response.Write (<%=) like that :
<asp:LinkButton ID="btnDeleteFamily" CssClass="fRight ui-icon ui-icon-trash"
runat="server" CommandName="delete" CommandArgument='<%#Eval("idmember")%>'
OnClientClick='<%# Bind("return confirm('{0}');'", "YourColumnName") %> Text=""
ValidationGroup="delete_family" />
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
LinkButton lb = e.Item.FindControl("btnDelete") as LinkButton;
if (lb != mull) {
lb.OnClientClick = "whatever";
}
}
It seems to be ok, for me at least.
You could try it in firefox, and using the WebDeveloper toolbar or Firebug extensions you will be able to get more information about what is happening behind scene.
Maybe there are others errors on the page that doesn't allow this code to work.
If you want to use the jQuery dialog in confirmation mode to bind to link buttons on a repeater inside an update panel, AND the code you want to execute after confirmation is different for each row, you can set it up this way:
Add a javascript function to your page/control like this:
function confirm(buttonFunctionForPostBack)
{
$("#dialog").dialog('option', 'buttons', {
"Cancel": function() {
$(this).dialog("close");
},
"Delete Payment": function () {
eval(buttonFunctionForPostBack);
$(this).dialog("close");
}
}
).dialog('open');
}
And in your code behind:
public void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
LinkButton lb = e.Item.FindControl("deleteButton") as LinkButton;
if (lb != null)
{
lb.OnClientClick = "confirm(\"" + this.Page.ClientScript.GetPostBackEventReference(lb, string.Empty) + "\");return false;";
}
}
And in your aspx page:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
<HeaderTemplate>
<table>
<tr>
<th width="90" valign="top"></th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><%#Eval("name")%></td>
<td><asp:LinkButton ID="deleteButton" runat="server" CommandName="delete" CommandArgument='<%#Eval("id")%>' Text="Delete" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
This lets you take advantage of the fact that you can set the dialog's 'buttons' option after the dialog was created. Also, it doesn't require any extra script variables.

Categories

Resources