Updating on-screen element several times in one function - c#

This has got to be easy, but has got me stumped.
How do I change an element on screen several times in one function?
I want to change a label to read something like "starting..." at the beginning of my function, then go away and do some stuff and then change the label to "finished" at the end.
As an illustration why does the following code:
errorMessage.Text = "Three...";
System.Threading.Thread.Sleep(1000);
errorMessage.Text = "Two...";
System.Threading.Thread.Sleep(1000);
errorMessage.Text = "One...";
System.Threading.Thread.Sleep(1000);
errorMessage.Text = "Go!";
System.Threading.Thread.Sleep(1000);
Just pause for 4 seconds and then change the label text to "Go!" rather than counting down?
TIA
Ben

If you want to time a process and put your results out to a label you should use a string in your function instead. Try something like this:
string countDownTimes = "";
countDownTimes += String.Format("One at: {0}, ",DateTime.Now.ToString());
System.Threading.Thread.Sleep(1000);
countDownTimes += String.Format("Two at: {0}, ",DateTime.Now.ToString());
//etc..
errorMessage.Text = countDownTimes;
If your looking to update the UI button in increments then you should look at a javascript solution or async updates.

The reason that your code only updates the screen once is that it is running inside of a single postback. At the end of the postback, HTML is rendered in returned to the browser for display.
Updating the page multiple times during a postback actually isn't easy. But for what you're doing, there is an easier solution. Use JavaScript to change the caption to "Starting..." at the beginning of the request, and then have the method return "Finished."

Because it is a web page, and the final value is what is sent to the browser. All server side code executes and then sends the final values to browser.
Your code is updating the control with the new value on the server, but it won't be seen by the client. To do what you want, you either have to update the control through client side script (javascript), or you have to refresh the page and display the updated value.
Here is a link to the asp.net pages life cycle which is kinda what you are asking about.
http://msdn.microsoft.com/en-us/library/ms178472.aspx
If you notice nothing is sent to the browser until the Render method.

You need to learn about how the web works;
A browser requests a page from the server
The server sends the page (and might do some server-side processing such as ASP.net)
The client shows the page and runs javascripts on the page
Then these javascripts might change the page after it has loaded, but step 2 can't go and change something that's already been sent to the client.

If it's ASP.NET all the code will be executed prior to send the html to the browser so only the last value will be shown. If you want to do that at client side you will have to do some javascript.

Related

PuppeteerSharp - Access a background page, that opens in a new tab, as a regular page

I'm having issues with a program that generates reddit apps with refresh tokens from a discord command.
I've managed to get to a point, where I can generate the application, get all the relevant information, head over to https://not-an-aardvark.github.io/reddit-oauth-helper/ and from there generate the token, which opens a reddit confirmation page in a new window.
I've tried accessing it in various ways and have gone through multiple different methods, until I landed on using Target.PageAsync() to get the page.
For some reason, Puppeteer only sees the page as an iFrame and only gives this link when getting the Url property - https://www.redditmedia.com/gtm/jail?cb=8CqR7FcToPI - which doesn't lead to anywhere but seems to be related to the very first iFrame from what I've gathered in the HTML.
I've ran out of ideas on how to access the page to press quite literally one button and would appreciate any ideas or solutions on how to solve this or how to generate the refresh token without the use of an external website.
Another two hours later and I managed to figure out a solution.
Since PuppeteerSharp was unwilling to recognize the page, I just subscribed to Browser.TargetCreated at the correct moment with a handler that, after immediately unsubscribing, will log the most recent target (in this case, a javascript calling window.open()) and take the sender as the Browser, will then try to get the pages into an array and with a bit of code to ensure that it doesn't break itself, I finally managed a solution, I feel kinda dumb after three days and 12+ hours of work.
For anyone who might run into a similar situation, here's the snippet of code that made it finally work:
// Bla bla bla code to crawl or do whatever on the main page.
// Immediately subscribe to the target created event with the event handler
// that will handle the background page once it has
// been triggered by a button, link, etc.
browser.TargetCreated += TargetCreatedEventHandler;
}
static async void TargetCreatedEventHandler(object sender, TargetChangedArgs e)
{
// Unsubscribe from the event to
// make sure there are no duplicate unnecessary calls that might break the code.
browser.TargetCreated -= TargetCreatedEventHandler;
// Since I know the sender is the Browser object,
// I cast it it to another Browser used inside the event handler.
Browser eventBrowser = (Browser) sender;
// Get all the pages from the event browser
// and assume the first page is background one (for now)
Page[] pages = await eventBrowser.PagesAsync();
Page page = pages[0];
int counter = 0;
// Iterate through the pages, check if they're the page you were just on,
// use an int to help you keep track of of indexes.
// If it isn't the page you were on, assign the Page object the page
// with the current counter index from pages.
// (basically make sure it doesn't break itself with the wrong order).
foreach (var item in pages)
{
if (item.Url != "Main Page URL HERE")
{
page = pages[counter];
break;
}
counter++;
}
// Do whatever you need to do on your background page here
}

Response.Write not working in ASP.NET

I have a calendar named poDateCalendar, I wanted to make it so whenever the user selects the calendar to be any earlier than today's date, there will be a response as follows:
protected void poDateCalendar_SelectionChanged(object sender, EventArgs e)
{
if (poDateCalendar.SelectedDate < System.DateTime.Today)
{
Response.Write("<script>alert('Warning: you are selecting a PO date earlier than today's date')</script>");
}
poDateCalendar.Visible = false;
poDateBtn.Text = poDateCalendar.SelectedDate.ToShortDateString();
}
It worked the first time I tried it, but somehow now it doesn't work anymore, is there anything I did wrong?
I also tried doing breakpoints, it passed through the if statement and did run the response.write. However, there's just nothing that is displayed after.
Just replace your code with the following line
Response.Write("<script> alert(\"Warning: you are selecting a PO date earlier than today's date\");</script>");
In your case your code is failing because you have a single quote at "today's" which is making your code to fail. So I am using escape sequence at start and end of alert message.
Check the raw HTML sent to the browser. Likely that script was rendered before the opening html tag. There is no page or DOM yet, and so even if the browser ran the javascript at all it wouldn't know what to do with it.
This happens because of where you are in the ASP.Net Page Life Cycle at the time that code runs. A page class in ASP.Net works by first building up all of the controls and properties to have the correct data. Then, once that is all finished, there is a rendering phase where those controls are transformed into HTML for your browser. Before this rendering phase, anything you send to Response.Write() is going to a response stream that hasn't even sent headers to the browser yet.
To get around this, instead of writing to the Response stream direclty, use the Page.RegisterStartupScript() method.
I don't quite get the point - Allow users to do what they're not supposed to do, and then shout when they do so. + Message box / alerts are the old school ways of doing things. That's a bad user experience, IMHO.
I have a better suggestion here for you. You could instead disable to previous dates so that they can't select in first place. You can use DayRender event for that.
<asp:Calendar ID="poDateCalendar" runat="server" OnDayRender="poDateCalendar_DayRender" />
In code-behind:
protected void poDateCalendar_DayRender(object sender, DayRenderEventArgs e)
{
if (e.Day.Date < DateTime.Today)
{
e.Day.IsSelectable = false;
// Additionally grey out dates if you want
}
}

ASP.NET, ScriptManager, History Points and Dynamic Javascript

I have an ASP.NET user control that I want to write some dynamic Javascript to (basically a JQuery call to open an accordion node).
To complicate matters, I'm using history points. In a nutshell, I need to open a JQueryUI accordion based on a value in the history point data stored in the URL.
I've got the part that sets the history points working, and I can step through my code (below) as I navigate the history. The problem is, in this example, my script never renders on the page.
protected void uxScriptManager_OnNavigate(Object sender, HistoryEventArgs e)
{
if(!String.IsNullOrEmpty(e.State["activeTab"]))
{
ScriptManager.RegisterClientScriptBlock(this, this.GetType(), "xScript", "alert('Hello,world!');", true);
}
}
Am I doing something wrong?
Addendum
I've been tinkering, and it seems like my call to register the clientscriptblock works fine in other events...but in the Navigate event for the scriptmanager, I can't write new script out to the page. I'm thinking what I'm trying to do isn't possible...
From what I've found, it doesn't look like it's possible to write new client script out to a page - or change values in an existing script block - on the Navigate event. I'm noting this in case anyone else tries to do the same thing.
CORRECTION
I found out it is possible to do what I want!
I need to set the history point in an early part of the page lifecycle
I need to set the dynamic script in the RegisterStartupScript method for the page
(Ivan's post pointed me in the right direction, so I've flagged his post as the answer)
It looks like you need to add script by calling ScriptManager.RegisterStartupScript method to show elements on page:
ScriptManager.RegisterStartupScript(this, this.GetType(), this.ID,
""alert('Hello,world!');", true);

ClientScript.RegisterClientScriptBlock?

In my web application when i upload a video and click the save button, if the video is uploaded i write the code to display the message video is uploaded. My code is as follows:
ClientScript.RegisterClientScriptBlock(GetType(), "sas", "<script> alert('Inserted successfully');</script>", false);
When the alert box appears is comes with a white background. I clicked on ok button in that alert box but the page is not going back to the previous page it is showing the same white space.
Can you solve the problem.? If you not understand i will explain clearly.
In local it is working fine but when i update in online it is not working.
Hai sridhar,
I found an answer for your prob
ClientScript.RegisterClientScriptBlock(GetType(), "sas", "<script> alert('Inserted successfully');</script>", true);
change false to true
or try this
ScriptManager.RegisterClientScriptBlock(ursavebuttonID, typeof(LinkButton or button), "sas", "<script> alert('Inserted successfully');</script>", true);
The method System.Web.UI.Page.RegisterClientScriptBlock has been deprecated for some time (along with the other Page.Register* methods), ever since .NET 2.0 as shown by MSDN.
Instead use the .NET 2.0 Page.ClientScript.Register* methods.
- (The ClientScript property expresses an instance of the ClientScriptManager class )
Guessing the problem
If you are saying your JavaScript alert box occurs before the page's content is visibly rendered, and therefore the page remains white (or still unrendered) when the alert box is dismissed by the user, then try using the Page.ClientScript.RegisterStartupScript(..) method instead because it runs the given client-side code when the page finishes loading - and its arguments are similar to what you're using already.
Also check for general JavaScript errors in the page - this is often seen by an error icon in the browser's status bar. Sometimes a JavaScript error will hold up or disturb unrelated elements on the page.
See if the below helps you:
I was using the following earlier:
ClientScript.RegisterClientScriptBlock(Page.GetType(), "AlertMsg", "<script language='javascript'>alert('The Web Policy need to be accepted to submit the new assessor information.');</script>");
After implementing AJAX in this page, it stopped working. After reading your blog, I changed the above to:
ScriptManager.RegisterClientScriptBlock(imgBtnSubmit, this.GetType(), "AlertMsg", "<script language='javascript'>alert('The Web Policy need to be accepted to submit the new assessor information.');</script>", false);
This is working perfectly fine.
(It’s .NET 2.0 Framework, I am using)

Updating ASP.NET label while processing

I have a method thats run on a button click, with 4 labels. What I need to do is update a label after each block of code executes. I've tried threading, updatepanels, etc and can't seem to get anything to work. I thought the timer would work, but it only ticks when you're not inside a method. The code looks something like this:
private void SomeMethod()
{
label1.text = "Processing...";
AnotherMethod();
label1.text = "Done.";
label2.text = "Processing...";
AnotherAnotherMethod();
label2.text = "Done.";
//etc...
}
You have a misunderstanding of how asp.net works. Your server code runs in response to a request from a browser for a complete html page. This is true even when all you really want to do is run some button click code. The entire page must be rebuilt from scratch anyway, even on postbacks. It's just the way web forms are designed.
As soon as the page is rendered to the browser, that instance of your page class is destroyed. On the next postback you'll start from scratch again, with the notable exceptions of the session, viewstate, and the application cache. Even the page's previous DOM instance in the browser is replaced.
So when you set the text property of the label you aren't directly updating anything visually in the browser. All you are doing is updating some temporary storage in your page class. As the last stage of executing your server code, all those temporary variables are used to render the completed html and the response is finally sent to the browser and shown to the user.
That should be enough information to give you an understanding of why your code doesn't behave as expected. It's running all of the code in the method before any of your property changes make their way to the browser. Therefore, the only thing the user sees is the final state of the operation.
Now ajax can complicate things a bit. When using an ajax control you might not be updating the entire page anymore, but the concept still applies: one request is made, and one response is received and used to update the entire context of the request. You can further muddle things if you have a lot of javascript in place to handle the result of the ajax request.
Unfortunately, there's no quick fix for the code you posted. You'll need to think about how this really works and decide how you want your page to flow.
Can you expose the 3 methods to client script and then call them sequentially from your client side code, when method1 finishes the client script would update the ui then call method2, and so on...

Categories

Resources