英文:
Is there an easy way to force VB.net to update the UI?
问题
I have been having a really difficult time with this, and it's almost unbelievable there is no way to force the UI to update. All I want is for the computer to actually show the LoadingImg before moving on the next calls. I've tried so many different things from threads, tasks, OnClientClick, Asyn/Await, etc. Most of the obvious methods like Refresh & Invoke are not methods for ASP.NET. Is there no easy way to call on the UI to update itself? What exactly should I be doing?
Protected Async Sub BtnModSave_Click(sender As Object, e As EventArgs)
LoadingImg.Visible = True
BtnDelete_Click()
BtnSaveSchedule_Click(sender, e, 1)
Call Response.Redirect("~/Schedule.aspx")
End Sub
I have also tried using Client Side with the code
<asp:Image runat="server" ID="LoadingImg" src="../Content/Images/wait2.gif" style="height: 75%; width: 75%" visible="false"/>
<asp:Button ID="BtnModSave" runat="server" Text="Update" CssClass="btn btn-success" OnClick="UUI" OnClientClick="validate()"/>
英文:
I have been having a really difficult time with this, and it's almost unbelievable there is no way to force the UI to update. All I want is for the computer to actually show the LoadingImg before moving on the the next calls. I've tried so many different things from threads,tasks,OnClientClick, Asyn/Await etc. Most of the obvious methods like Refresh & Invoke are not methods for aspx.net. Is there no easy way to call on the UI to update itself? What exactly should I be doing?
Protected Async Sub BtnModSave_Click(sender As Object, e As EventArgs)
LoadingImg.Visible = True
BtnDelete_Click()
BtnSaveSchedule_Click(sender, e, 1)
Call Response.Redirect("~/Schedule.aspx")
End Sub
I have also tried using Client Side with the code
<asp:Image runat="server" ID="LoadingImg" src="../Content/Images/wait2.gif" style="height: 75%; width: 75%" visible="false"/>
<script type="text/javascript">
function validate() {
document.getElementById('LoadingImg').style.visibility = 'true';
}
</script>
<asp:Button ID="BtnModSave" runat="server" Text="Update" CssClass="btn btn-success" OnClick="UUI" OnClientClick="validate()"/>
答案1
得分: 1
首先,在进行任何Web开发之前,您确实需要了解页面生命周期的工作原理。有了这个知识,一切都变得非常简单。包括当您点击常规的asp.net按钮来运行一些代码时,也可以显示某种“请稍候”的方法。
然而,如果没有掌握页面生命周期的基本原则,所有这些看起来都像巫术,您会尝试无数不起作用的方法。
所以,第一课,您必须掌握的第一个概念是回发的概念。
当您单击普通按钮以运行一些代码时,整个Web页面都会发送到服务器。
页面类被创建,加载,然后才运行您的代码。
所以,假设我们有这样的标记:
<asp:Button ID="cmdStart" runat="server" Text="启动进程" CssClass="btn" OnClick="cmdStart_Click" />
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
因此,我们将点击一个按钮,并在代码后台启动一个进程。
我们的代码后台可能是这样的:
Protected Sub cmdStart_Click(sender As Object, e As EventArgs)
TextBox1.Text = "working...."
'模拟一个长时间的过程
System.Threading.Thread.Sleep(4000) '5秒延迟
End Sub
那么,用户会看到文本框文本“变为”“工作...”然后延迟4秒吗?
不是!将发生的是页面中的文本框将被更改,然后我们等待4秒,然后整个页面回到浏览器,重新加载,然后我们看到更改。
所以,所谓的“往返”?
代码后台只能在页面上升到服务器时修改页面。然而,由服务器代码进行的更改不会在客户端显示。(整个网页仍然在服务器上。)
所以,你没有这个:
In other words, the web server can ONLY process a post-back page, but from ANY user - not just you!
服务器能够处理的仅仅是一个回发的页面,而不仅仅是您!
在您只是坐在浏览器前面的时候,服务器上根本没有您的页面的副本。
所以,好吧,我们点击按钮。
我们有这个:
So, we click on the button, and the post-back starts.
所以,我们点击按钮,回发开始。
网页现在被发布到服务器。
服务器接收该页面,加载页面类,创建页面类的实例(您的代码后面存在的地方),然后开始运行代码后面。
在您的代码运行时,您正在更改服务器上的浏览器的副本。您可以更改任何控件-甚至将计数器循环到控件。最终用户及其浏览器的副本仍然只是坐在他们的桌面上。
用户不能,也不会看到由代码后面进行的更改。
所以,我们有这个:
All the end user sees is the browser "spinner" or "wait".
所有终端用户看到的只是浏览器的“旋转器”或“等待”。
您可以加载图片,更改文本框等。但所有这些都发生在服务器上的网页的副本上。
在这一点上,用户不会看到任何更改!
仅在代码完全运行之后,只有当整个新鲜的浏览器页面回到客户端时,用户才会看到代码后面对服务器所做的所有更改。
请注意,现在服务器将“处理”并“销毁”代码后面和页面类。这就是为什么现在所有变量都超出范围的原因(有点像调用子程序,当您退出子程序时,该子程序中的所有值和代码现在都消失了,超出了内存)。Web服务器现在已准备好接受来自任何用户的任何页面回发-不仅仅是您!因此,服务器上不再存在代码或网页的副本!
因此,现在有了这个新知识?
英文:
Well, first before doing any web development, you really need to grasp how the page life cycle works. With that knowledge, then everything becomes really simple. Including that of say you clicking a on a regular asp.net button to run some code behind, but also show some kind of "please wait" method.
However, without a grasp of the basic principal of the page life cycle, then all of this will seem like voodoo, and you try endless things that don't work.
So, the FIRST lesson, the FIRST concept you have to grasp is the concept of a post back.
When you click on plain button to run some code behind, then the WHOLE web page is sent up to the server.
The page class is created, loaded, and THEN your code behind runs.
So, say we have this markup:
<asp:Button ID="cmdStart" runat="server"
Text="Start the process" CssClass="btn"
OnClick="cmdStart_Click"
/>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
So, we will click a button, and start a process with our code behind.
Our code behind is say this:
Protected Sub cmdStart_Click(sender As Object, e As EventArgs)
TextBox1.Text = "working...."
' fake a long process
System.Threading.Thread.Sleep(4000) ' 5 second delay
End Sub
So, will the user see the text box text "become" working... and then a 4 second delay?
Nope! What will occur is the text box in the "DOM" of the page will be changed, then we wait 4 seconds, AND THEN THE WHOLE page makes the trip back down to the browser, is re-loaded, and then we see the changes.
So, the so-called "round trip"?
Code behind can ONLY EVER modify the page WHILE it is up on the server. However, changes made by the server code don't appear client side. (the whole web page is STILL up on the server).
So, you do NOT have this:
In other words, the web server can ONLY process a post-back page, but from ANY user - not just you!
There is NOT a copy of your page on the server while you are just sitting there looking at the browser.
So, OK, so we click on the button.
We have this:
So, we click on the button, and the post-back starts.
The web page is now posted to the server.
The server receives that page, loads the page class, creates a instance of the page class (where you code behind exists), and THEN starts to run code behind.
WHILE your code runs, you are changing a copy of the browser on the server. You can change any control - even loop a counter to a control. The end user and their copy of the browser is STILL just sitting on their desktop.
The user can not, will not see changes being made by the code behind.
So, we have this:
All the end user sees is the browser "spinner" or "wait".
you can load pictures, change text boxes etc. But ALL of that is occurring on the copy of the web page on the server.
At this point, the USER DOES NOT SEE any changes!
Only AFTER 100% of your code is done running, then and ONLY then does a WHOLE NEW FRESH copy of the browser page now makes the trip back down to the client side.
so, now this part of the page "round trip starts".
The client side browser page THEN loads, renders, starts JavaScript, and THEN the user will now see all the changes your code behind on the server made.
Note that NOW the server will "dispose" and "dump" and "destroy" the code behind and page class. This is why all variables are now out of scope (kind of like calling a sub, when you exit the sub, all values and code in that sub are now gone, out of memory).
the web server is now ready to accept ANY page post back from ANY user - not just you! So NOT EVEN a copy of the code nor web page exists on the server any more!
So, NOW with this new knowledge in mind?
Well, we NOW realize that clicking a button to run some code (server side code behind) means that the end user will NOT see anything change!
So, what this means?
We need to run a bit of code client side FIRST before that post-back button runs!
it turns out that a regular button has provisions for this. So, a simple button click has TWO parts.
A client side event, and a server side event!
So, let's say we want a please wait .... (and say a animated GIF spinner) to display when we click the button.
Well, our button code will this look like this:
<asp:Button ID="cmdStart" runat="server"
Text="Start the process" CssClass="btn"
OnClick="cmdStart_Click"
OnClientClick="mywaitdialog()"
/>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<div id="mywaitmsg" style="display:none;width:300px" >
<h3>Updating data - please wait</h3>
<div style="text-align: center">
<img src="../Content/wait2.gif" style="height: 64px; width: 70px" />
</div>
</div>
<script>
function mywaitdialog() {
var mywait = document.getElementById("mywaitmsg")
mywait.style.display = 'block';
}
</script>
So, note how the button NOW has two events, and one is the client click.
So, when we click the button, then client side code runs, and SHOWS our hidden div.
Then the above page lifecycle starts.
Note VERY carefully how at the end of the process, we don't have to "hide" the spinner and div message area. (because that page from the server going to come barreling down, and re-load the WHOLE client side page - which of course then hides the div for us!
So, the effect is now this:
And note our server side button code can be this:
' fake a long process
System.Threading.Thread.Sleep(4000) ' 5 second delay
TextBox1.Text = "done"
or, it can be this:
TextBox1.Text = "done"
' fake a long process
System.Threading.Thread.Sleep(4000) ' 5 second delay
note the order of where we place the text = "done" does not matter!
(because the page is HELD UP and STAYS on the server until ALL of the code behind is done.
So, as you can see, it really only about 2-3 extra lines of code (client side JavaScript) to display that "wait message".
So, in effect we modify/change/show the wait message client side and THEN let the page life cycle start.
When all is done server side, then a WHOLE NEW copy of the page returns to the client side, and thus no need to even hide the message stuff, since it will revert back to what it was before the button click (the div was hidden with style).
So keep in mind that the code behind NEVER interacts with the user, but ONLY interacts with the copy of the web page that is NOW up on the server. Code behind does not interact with the user, it ONLY can change the page, and only change the page WHILE it is up on the server. So, your code behind in fact does not interact with the user EVER! It only can change the page and controls. the interact ONLY occurs when the WHOLE page makes the trip back down to the client side.
So, while the above to display that wait message was dead simple? It also demonstrates that code behind can't interact with the user. Only code on the page can!
So, a REALLY fantastic next question would be how could I have a progress bar, have 4 or say 8 steps server side, and how would one update the progress bar as we run those 8 steps!
but, for now, for a button to load a gridview, or do whatever that takes a bit of time?
you simple add a client side bit of code to display/show the wait message, and then the server side code can run and go to work. ONLY after all that server side code runs does then the web page up-date. And in our example, we use that fact (the fresh new page) to hide our displayed wait message.
So, with a grasp of the page life cycle, we can leverage the fact that whole new page will arrive sooner or later - and re-load, and re-display the browser.
So, now let's look at your code example:
LoadingImg.Visible = True
OK, so above changes the visibility of the image - but REMEMBER, this is occurring on the server. The user can't see that change and will ONLY see that change WHEN the whole page travels back to the client side!
Then we have this code:
BtnDelete_Click()
BtnSaveSchedule_Click(sender, e, 1)
OK, the page is still up on the server side, and you call 2 routines.
(user still has the original copy of their web page on their desktop - they still can't see anything or any changes).
Then this:
Call Response.Redirect("~/Schedule.aspx")
Hold on! We now are saying to the server do NOT send the current page back to the user, but now we asking the server to jump + load a 100% different page.
So, now the server will nuclear bomb out of existence the current page (that has NOT made the trip back to the end user - so they never see any changes in the browser). The page we were just making changes to now is tossed out into the garbage, and now the we are asking the server to load + start rendering a WHOLE new page. but, the current page NEVER makes the trip back to the client side.
So, we now loading a whole new page. That means ANY changes to the current page we were on can't been seen, and will NEVER be seen by the client side. Specific in this case is this line of code:
LoadingImg.Visible = True
the user not going to see the above UNLESS we let the whole page travel back to the client side, and finish the round trip!
So, as noted, let's take our example, and change it.
Our code behind is now this:
TextBox1.Text = "done" ' NEVER will be seen, since next line
Response.Redirect("MyTestPage2.aspx")
So, we change textbox1, but then next line says to jump and render a whole different page.
So, our current page will NEVER travel back to the client. The user NEVER gets to see the text box change to "done", since we NEVER let that page finish the round trip. Since the page NEVER travels back to the client, then they will never see the text box change to "done".
As noted, changes to the browser page by code behind does will NOT be seen when we change the text box, but only AFTER all code is done, and the WHOLE web page then travels back to the client browser. That is when they will see the text box change to "done". Since we then decide to do load a different web page (response redirect), then the user will never see any changes on that current web page - the web page has not traveled back to the client side to display our change to that text box.
So, let's assume that MyTestPage2.aspx has this markup:
<h2>Welcome to test page 2</h2>
And let's assume that the page load event of test page 2 is this:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
System.Threading.Thread.Sleep(3000)
End If
End Sub
So, what will happen now?
Our button code on the 1st page is still this:
<asp:Button ID="cmdStart" runat="server"
Text="Start the process" CssClass="btn"
OnClick="cmdStart_Click"
OnClientClick="mywaitdialog()"
/>
<asp:TextBox ID="TextBox1" runat="server"></asp:TextBox>
<div id="mywaitmsg" style="display:none;width:300px" >
<h3>Updating data - please wait</h3>
<div style="text-align: center">
<img src="../Content/wait2.gif" style="height: 64px; width: 70px" />
</div>
</div>
<script>
function mywaitdialog() {
var mywait = document.getElementById("mywaitmsg")
mywait.style.display = 'block';
}
</script>
so, what will occur is we click on the button.
Our spinner shows, and WHOLE page now is posted to the server.
We do this:
Protected Sub cmdStart_Click(sender As Object, e As EventArgs)
TextBox1.Text = "done"
Response.Redirect("MyTestPage2.aspx")
End Sub
We modify text box, but THEN say please load a different page - that is the page that will be sent to the client for our life cycle. We NEVER let the current page go back to the client, did we?
So, our page load event as noted is this in page 2
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
If Not IsPostBack Then
System.Threading.Thread.Sleep(3000)
End If
End Sub
But, the effect again is this:
So, once again, this all makes sense WHEN you grasp the page lifecycle.
The tell-tale sign that you don't grasp the page life cycle is your line of code behind that tries to set the image visible = true, but THEN you say load (send to client) a 100% different page. So, your visible image setting will never be seen by the client, since we NEVER let the whole page life cycle complete for the first page, but code behind decides to jump to a 100% different page - that is the page the client side browser will receive.
Note that we can put the test sleep delay in the new page load event, or we can put it in the button click code behind. The effect is the same. The client side is STILL waiting for a whole page to return to the client. it don't matter if that is the same current page, or a redirect to a whole new page. The client side will wait and wait until that new page comes down the pipe from the server.
So, if you need a simple "wait", then you simple have to have client side code that runs on that button click. Then the display of that "animated" GIF, or even a simple please wait text will remain in view until such time a whole page is returned from the server. The page returned can be the current page, but with a response redirect, then a different page is returned. but, it still in a sense a page life cycle (in which the client side is waiting for a page to be returned from the server).
So, just keep in mind that code behind "as" it makes changes to the web page are NEVER seen by the user. Any and all changes to that web page are ONLY seen when the WHOLE PAGE on the server makes it's trip back to the client side browser. Then and only then does the browser update. In fact, you can update 1 control, or 20, or set visible of some element. None of these changes will be seen UNTIL THE WHOLE page travels back to the client side.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论