change text on button and enabled status after click button(asp.net) - asp.net

I use ASP.NET to develop.
Here, I want the thing is that once I click button A (the text on the button A is "Start"), then the text on the button A will change to "processing...please wait" and button A will become not clickable. Then execute the stored procedure(the duration of stored procedure is 1 minute). After the stored procedure finishes, the text on the button A will change to "Start" and button A will become clickable.
I tried that before stored procedure, I added these codes:
ButtonA.Text = "processing...please wait";
ButtonA.Enabled = false;
And after stored procedure, I added these codes:
ButtonA.Text = "Start";
ButtonA.Enabled = true;
But the outcome is the text on the button A is not changed and button A is still clickable during the stored procedure is executing.
Can anyone tell me how to achieve what I want? Thanks.
Then I edit my aspx file to be below:
<asp:ScriptManager ID="MainScriptManager" runat="server"/>
<asp:UpdatePanel ID="pnlHelloWorld" runat="server" UpdateMode="Conditional" ChildrenAsTriggers="true">
<ContentTemplate>
<asp:Button ID="ButtonA" runat="server" OnClick="ButtonA_Click" Text="Start" />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="ButtonA" EventName="Click"/>
</Triggers>
</asp:UpdatePanel>
But the text of button still remains the same and the button is still clickable.

You can achieve your requirement by using Ajax. Using Ajax you can do partial page refresh.
Put ButtonA inside the UpdatePanel, and it should work as expected.
You can refer below sample code for reference.
webpage.aspx code
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Hello, world!</title>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="MainScriptManager" runat="server" />
<asp:UpdatePanel ID="pnlHelloWorld" runat="server">
<ContentTemplate>
<asp:Button runat="server" ID="ButtonA" OnClick="btnHelloWorld_Click" Text="Update label!" />
</ContentTemplate>
</asp:UpdatePanel>
</form>
</body>
</html>
c# code
protected void btnHelloWorld_Click(object sender, EventArgs e)
{
//Before Procedure call
ButtonA.Text = "processing...please wait";
ButtonA.Enabled = false;
//Call Procedure
procedure ....
//After Prodedure call
ButtonA.Text = "Start";
ButtonA.Enabled = true;
}
Hope that helps, thanks.

Related

ASP.NET WebForms: Asynchronous UpdatePanel?

First off, I know that what I am doing here seems entirely impractical and not good design, but I am trying to increase performance in this ASPX that contains 8,000+ lines of markup. Because of the complexity of this page (not to mention messiness) and short deadline, rewriting it to use clientside binding with AJAX/JSON is just not an option, so I have to continue to use serverside binding.
The page I am working on contains around 13 individual sections, each one loading its own entity from the database. Right now, the page initially loads ALL entities synchronously, so you can imagine that this page can sometimes take 5 seconds or longer to load. My goal here is to employ a quick fix that will load these sections only when the section is expanded so that we load only the sections that are requested by the user, thus increasing performance and conserving database resources.
The sample code below should be easy to paste right into a VB.NET WebForm if you're interested in trying this out for yourself. Just name the page asyncupdatepanels.aspx.
The problem:
Overall, my solution is working fairly well. In cmUpdate_Click, I use Threading.Thread.Sleep(2000) to simulate a call to the database to retrieve data. When you click one of the buttons, it pauses for 2 seconds and then sets the appropriate Panel's .Visible property to True.
The issue occurs when you click one button and then click the the other before the first one is finished updating. For example, if you click Show Panel 1 then quickly click Show Panel 2, only Panel 2 shows even though both button clicks are triggered in the codebehind.
Maybe asynchronous UpdatePanel is the wrong term to use here. Regardless, I need to find a way to show the panels as if they were executed in separate asyncronous threads. I want to be able to click these buttons pretty much near the same time and have both panels show.
If anyone has any other solutions to my problem that will not require major changes to the way I bind controls in each section, I'd love to hear it. The method I am using now is pretty much a hack, but it will work for now until we eventually rewrite this whole thing in MVC/c#.
Edit: The production code doesn't actually call a Javascript function by use of a button's OnClientClick. Instead, it uses a jQuery accordion. I just wanted to keep the sample code simple. For now, focus on __doPostBack("<%=cmUpdate.ClientID %>", ButtonId); regardless of how it's ultimately called.
ASPX
<%# Page Language="vb" AutoEventWireup="false" EnableEventValidation="false" CodeBehind="asyncupdatepanels.aspx.vb" Inherits="JsonJqueryDevex.asyncupdatepanels" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<script language="javascript" type="text/javascript">
function UpdateIt(ButtonId) {
__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);
return false;
}
</script>
</head>
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
<asp:Button ID="cmShow1" Text="Show Panel 1" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl1" Visible="false" runat="server">
Panel 1 content
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="cmShow2" Text="Show Panel 2" ClientIDMode="Static" OnClientClick="javascript:return UpdateIt(this.id);" runat="server" />
<asp:UpdatePanel ID="UpdatePanel2" UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Panel ID="pnl2" Visible="false" runat="server">
Panel 2 content
</asp:Panel>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="cmUpdate" EventName="Click" />
</Triggers>
</asp:UpdatePanel>
<div style="display: none">
<asp:UpdatePanel UpdateMode="Conditional" runat="server">
<ContentTemplate>
<asp:Button ID="cmUpdate" runat="server" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
</div>
</form>
</body>
</html>
Codebehind:
Public Class asyncupdatepanels
Inherits System.Web.UI.Page
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
End Sub
Private Sub cmUpdate_Click(sender As Object, e As System.EventArgs) Handles cmUpdate.Click
Dim Param As String = Request("__EVENTARGUMENT")
Threading.Thread.Sleep(2000)
Select Case Param
Case "cmShow1"
pnl1.Visible = True
Case "cmShow2"
pnl2.Visible = True
End Select
End Sub
End Class
How about disabling the appropriate buttons on click?
Say,
function UpdateIt(ButtonId) {
$('#<%=cmShow1.ClientID %>').attr('disabled', true);
$('#<%=cmShow2.ClientID %>').attr('disabled', true);
__doPostBack("<%=cmUpdate.ClientID %>", ButtonId);
return false;
}
Then, in your code behind, after the sleep, enable them again (cmShow1.Enabled = true / cmShow2.Enabled = true) - the UpdatePanel call will handle the rest.
I would do an AJAX call to your server-side in the page_load event of the page where your updated panel is. You would then call the Update method of your update panel when your processing is done.
You won't have to wait for the processing to be done to do whatever you want to do meanwhile.
Javascript(with jQuery):
function ajaxCall() {
$.ajax({
url: "YourPage.aspx"
});
}
You can process your AJAX call in the Page_Load in your .NET.
I know that you said using AJAX wouldn't be a good option, but this is fairly short and simple.

Updating ASP.NET label after button click, using UpdatePanel

I'm trying to have two things happen when I click on a button in an ASP.NET page:
Change the text in an ASP:Label.
Disable the button.
I've done a lot of research on this, but I've had difficulties doing either.
For #1, I thought that this should work, but it doesn't:
<%# Page Language="VB" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
Protected Sub BtnSubmit_Click(sender As Object, e As System.EventArgs)
Label1.Text = "Working..."
System.Threading.Thread.Sleep(5000)
Label1.Text = "Done."
End Sub
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Test Page</title>
</head>
<body>
<form id="form1" runat="server">
<ajaxToolkit:ToolkitScriptManager runat="server" />
<div>
<asp:ListBox runat="server" Height="100px" />
<br />
<asp:UpdatePanel runat="server">
<Triggers>
<asp:AsyncPostBackTrigger ControlID="BtnSubmit" EventName="Click" />
</Triggers>
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Press the button" />
</ContentTemplate>
</asp:UpdatePanel>
<br />
<asp:Button runat="server" ID="BtnSubmit" OnClick="BtnSubmit_Click" Text="Submit Me!" />
</div>
</form>
</body>
</html>
The "Working..." message is never displayed.
As for #2, I added this to the button (I forget where I found it):
OnClientClick="this.disabled = true; this.value = 'Working...';"
UseSubmitBehavior="false"
That had the desired effect of disabling the button and changing its text (value), but it wasn't possible to change it back using Text and Enabled properties.
I just found a solution on msdn (http://msdn.microsoft.com/en-us/library/bb386518.aspx). Added some code and remove some unnecessary parts.
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void btnDoWork_Click(object sender, EventArgs e)
{
/// do something long lasting
System.Threading.Thread.Sleep(3000);
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="Head1" runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<script language="javascript" type="text/javascript">
<!--
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_initializeRequest(InitializeRequest);
prm.add_endRequest(EndRequest);
var postBackElement;
function InitializeRequest(sender, args) {
if (prm.get_isInAsyncPostBack()) {
args.set_cancel(true);
}
postBackElement = args.get_postBackElement();
if (postBackElement.id == 'btnDoWork') {
$get('btnDoWork').value = 'Working ...';
$get('btnDoWork').disabled = true;
}
}
function EndRequest(sender, args) {
if (postBackElement.id == 'btnDoWork') {
$get('btnDoWork').value = 'Done!';
$get('btnDoWork').disabled = false;
}
}
// -->
</script>
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:Label ID="Label1" runat="server" Text="Hello World!"></asp:Label><br />
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnDoWork" />
</Triggers>
</asp:UpdatePanel>
<asp:Button ID="btnDoWork" runat="server" Text="Start!" OnClick="btnDoWork_Click" />
</div>
</form>
</body>
</html>
What you basically do, is you register some eventHandler for Initialize_ and End_Request - in those you disable and enable your button!
HTH
ASP will not flush the result to the browser while working even if you use an UpdatePanel. It will finish the jobb (including the sleep) before flushing.
You can use a UpdateProgress to show the "Working.." text.
<asp:UpdateProgress>
This will show its content while the UpdatePanel is working. Once the UpdatePanel is finished, the content will disappear.
What you need in you ClickEvent is:
Label1.Text = "Done."
btnSubmit.Enabled = false
This will show the Done text and disable the button. And tell the UpdateProgress to disappear.
The Working message is never displayed because you are executing the script on the server, which doesn't respond to the client until the method exits.
ASP.NET AJAX has a built in control for displaying messages like this while the UpdatePanel is waiting on the server.
Check out the UpdateProgress Control:
<asp:UpdateProgress runat="server" id="progress" ><ProgressTemplate>Working...</ProgressTemplate></asp:UpdateProgress>
You can disable the button by setting the Enabled property to false in your server-side method.
BtnSubmit.Enabled = false
#1: You will never see the message "Working" as you stopped the thread .... Every Message will be shown when your process has "ended".
#2: you coded clientSide to disable the button, there is no code to re-enable your button
hth
First off, "working" never appears because the final value of the label at the time of post-back is "Done." Think about what is happening here - you click the button which causes a post-back to the server. It processes the post-back which includes running the button click code, the result of which is then sent back to the browser. Your 'working' text never makes it back over the wire.
I am not clear on what you're trying to accomplish with the client-side code, but to do what you describe you're almsot there server-side:
Protected Sub BtnSubmit_Click(sender As Object, e As System.EventArgs)
Label1.Text = "Done."
btnSubmit.Enabled = false
End Sub
Also, but your button inside your update panel template tags so it participates in the ajax-postback.

Refresh content-page asynchronously?

I have a master page "PartialUpdate.Master" and 2 simple content pages "WebForm1.aspx" and "WebForm2.aspx"
WebForm1.aspx/WebForm2.aspx: the content-pages just display their filename
The master page "PartialUpdate.Master" has 2 buttons and a ContentPlaceHolder
in an UpdatePanel. When clicking on a button I want to see the corresponding content-page
Here's what it looks like...
PartialUpdate.Master :
<body>
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<div>
Master Page
<asp:UpdatePanel ID="UpdatePanel1" UpdateMode="Conditional"
runat="server">
<ContentTemplate>
<asp:Button ID="btnForm1" CommandArgument="WebForm1.aspx"
runat="server" Text="Form1" OnClick="ChangeForm_Click" />
<asp:Button ID="btnForm2" CommandArgument="WebForm2.aspx"
runat="server" Text="Form2"
OnClick="ChangeForm_Click" />
<hr />
<asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</ContentTemplate>
<Triggers>
<asp:AsyncPostBackTrigger ControlID="btnForm1"
EventName="Click" />
<asp:AsyncPostBackTrigger ControlID="btnForm2"
EventName="Click" />
</Triggers>
</asp:UpdatePanel>
</div>
</form>
</body>
The code behind of PartialUpdate.Master.cs
protected void ChangeForm_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
Response.Redirect(btn.CommandArgument);
}
Problem here is that Response.Redirect() triggers a full-page postback.
I just want the Master to refresh the content located in the 'ContentPlaceHolder' asynchronously (that's why I added the AJAX UpdatePanel)
In other words, I'd like to dynamically change the content-page that the Master is displaying whitout causing a full-page postback.
Is this possible? If so how?
thank you
Chris
You can call with WebRequest in ajax call and write the content you recieve to the page...
But you can`t "knowing" the browser that you want to redirect to another page without post back.

Timer issue on Asp.Net

I have encountered a serious issue in asp.net which is stopping me going further.
The issue is due to server side timer control. The following is the scenario,
When main page loads , timer will start automatically and it should keep run throughout the application. My page contains Infragistics controls.
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server">
</asp:ScriptManager>
<asp:UpdatePanel ID="UpdatePanel1" runat="server" onload="UpdatePanel1_Load">
<ContentTemplate>
<asp:Timer ID="Timer1" runat="server" Enabled="true" Interval="10000" />
</ContentTemplate>
</asp:UpdatePanel>
<ig:WebDataMenu ID="WebDataMenu1" runat="server" OnItemClick="wdmenu_Context_ItemClick">
<Items>
<ig:DataMenuItem Key="0" Text="Add" >
</ig:DataMenuItem>
<ig:DataMenuItem Key="1" Text="Edit">
</ig:DataMenuItem>
</Items>
<ClientEvents ItemClick="wdmenu_Context_ItemClick" />
</ig:WebDataMenu>
</div>
</form>
</body>
If i open model dialog and after 2 to 3 sec , i am closing the model dialog... the wdmenu_Context_ItemClick server side event (which is for opening model dialog ) is firing two times...
Also on click of that button , i am opening model dialog using java script which is shown below
<head runat="server">
<title>Untitled Page</title>
<script language="javascript" type="text/javascript">
function wdmenu_Context_ItemClick(sender, eventArgs)
{
var win = window.showModalDialog("Default2.aspx", "Dialog", 'center:yes;resizable:no;dialogHeight:500px;dialogwidth:660px');
}
</script>
</head>
Please help me regarding this....

asp.net dropdownlist - C#.NET and javascript

I have a drop down and a div right next to it. The text contained inside the div should be updated based on value selected in the dropdown.
I do NOT want to use AutoPostBack feature.
Use OnChange client side event of the dropdownlist control. Here is a sample that updates a div's inner text with the selected value of the dropdown list :
<asp:DropDownList runat="server" ID="myDDL"
OnChange="document.getElementById('myDiv').innerText=this.value;">
</asp:DropDownList>
<div id="myDiv"></div>
As people have said, you cannot access the C# codebehind code without performing a postback.
One way of accomplishing what you want is to use PageMethods. This is the Microsoft idiom for accomplishing this but there are lots of other Ajax libraries that will do it.
Provide a static method in your codebehind which will get called form your dropdownlist OnChange event.
[WebMethod]
public static string MyMethod()
{
// Your code goes here
return "The text for the div"
}
You then call this PageMethod from your .aspx page:
You need to add a scriptmanager (after the form tag)
<asp:ScriptManager ID="scriptmanager1" EnablePageMethods="true" EnablePartialRendering="true" runat="server" ></asp:ScriptManager>
Then in the OnChange event (or a function called from it) you have:
<asp:DropDownList id="ddl" runat="server" OnChange="PageMethods.MyMethod(OnComplete);" />
Where OnComplete is a javascript function that handlers the PageMethod response:
<script language="javascript">
function OnComplete(result, userContext, methodName) {
document.getElementById(yourDivId').innerText=result;
}
</script>
You can also have a paramaterised webmethod if needed:
[WebMethod]
public static string MyMethod(string myNeatParam)
{
// Your code goes here
return "The text for the div"
}
And call it with:
PageMethods.MyMethod('SomeValue', OnComplete)
Updated based on comments:
Here's a sample page on using an UpdatePanel to do what you need to do. Please keep in mind though that there is a full postback happening, even though it is transparent to the user.
<%# Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="UpdatePanelMadness._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server">
<ContentTemplate>
<asp:DropDownList ID="ColorsDropDownList" runat="server" AutoPostBack="true"
onselectedindexchanged="ColorsDropDownList_SelectedIndexChanged">
<asp:ListItem Text="Red" Value="Red" />
<asp:ListItem Text="Green" Value="Green" />
<asp:ListItem Text="Blue" Value="Blue" />
</asp:DropDownList>
<div id="ColorDiv" runat="server">
<p>
Hello World!
</p>
</div>
</ContentTemplate>
</asp:UpdatePanel>
</div>
</form>
</body>
</html>
code behind:
namespace UpdatePanelMadness
{
using System;
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
protected void ColorsDropDownList_SelectedIndexChanged(object sender, EventArgs e)
{
ColorDiv.InnerText = this.ColorsDropDownList.SelectedValue;
}
}
}

Resources