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.
Related
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..
}
}
}
.aspx
<asp:ListView ID="ListViewUsers" ItemType="User" runat="server" OnItemCommand="ListViewUsers_ItemCommand">
<ItemTemplate>
<div class="center">
<table id="tableUsers">
<tr>
<td><%#Item.UserName%></td>
<td><asp:Button ID="Btn_addFriend"
runat="server" Text="Add friend" /></td>
</tr>
</table>
</div>
</ItemTemplate>
...
.aspx.cs
protected void ListViewUsers_ItemCommand(object sender, ListViewCommandEventArgs e)
{
// How to access the button, and do some work when it is clicked.
}
The correct way of doing this is to add CommandName argument to Your button and later catch this inside Your EventHandler. Example below:
<asp:Button ID="Btn_addFriend" runat="server" Text="Add friend" CommandName="Add friend" />
Now You can catch this command in Your event handler like this:
protected void ListViewUsers_ItemCommand(object sender,ListViewCommandEventArgs e)
{
if(String.Equals(e.CommandName, "Add friend"))
{
// ... DO SOME WORK HERE
}
}
Referring to MSDN article https://msdn.microsoft.com/pl-pl/library/system.web.ui.webcontrols.listview.itemcommand%28v=vs.110%29.aspx
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
I have a tabcontainer with two tabs. The first tab contains a textbox, while the second tab contains a panel.
I want the second tab to be disabled at first page load, and I want it to become enabled as soon as the user enters an input in the textbox in tab1. When textbox in tab1 is emptied again, the second tab should again be disabled.
I tried the following code, but the second tab remains disabled no matter what.
Any help would be appreciated. Thank you!
aspx
<asp:TabContainer ID="TabContainer1" runat="server" ActiveTabIndex="4" HeaderText=""
Height="578px" Width="900px" TabStripPlacement="Top" ScrollBars="None" UseVerticalStripPlacement="false"
VerticalStripWidth="120px" BackColor="White" BorderColor="White" Style="margin-right: 84px">
<asp:TabPanel ID="TabPanel1" runat="server">
<HeaderTemplate>
General
</HeaderTemplate>
<ContentTemplate>
<asp:UpdatePanel ID="TestUpdatePanel" runat="server">
<ContentTemplate>
<table style="height: 247px; width: 100%;">
<tr>
<td>
<asp:TextBox ID="HorizonTextBox" runat="server" OnTextChanged="HorizonTextBox_TextChanged"
AutoPostBack="True"></asp:TextBox>
</td>
</tr>
</table>
</ContentTemplate>
</asp:UpdatePanel>
<ContentTemplate>
</asp:TabPanel>
<asp:TabPanel ID="TabPanel2" runat="server">
<HeaderTemplate>
Dashboard
</HeaderTemplate>
<ContentTemplate>
<asp:Button ID="RunSimulationButton" runat="server" Text="Run Simulation" OnClick="RunSimulationButton_OnClick" />
<br />
<br />
<asp:Panel ID="PlotPanel" runat="server">
</asp:Panel>
</ContentTemplate>
</asp:TabPanel>
aspx.cs
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
TabContainer1.ActiveTabIndex = 0;
TabPanel2.Enabled = false;
}
}
protected void HorizonTextBox_TextChanged(object sender, EventArgs e)
{
if(HorizonTextBox.Text != "")
{
TabPanel2.Enabled = true;
}
}
you may need to enclose whole tab container into updatepanel to allow update panel enable/disable child controls
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">