我有这段代码:
<div style="padding: 0px 12px 12px 12px;">
<asp:UpdatePanel runat="server" ID="Panel">
<ContentTemplate>
<asp:Button ID="btnGenerate" CssClass="button" Style="float: right" runat="server"
Text="Go" OnClick="btnGenerate_Click" />
</ContentTemplate>
</asp:UpdatePanel>
</div>
<div>
<asp:UpdateProgress runat="server" ID="PageUpdateProgress">
<ProgressTemplate>
<img src="ajax-loader.gif" />
<asp:Label ID="lblStatus" runat="server" Text="Working..." CssClass="label" />
</ProgressTemplate>
</asp:UpdateProgress>
</div>
当我点击按钮时,动画gif显示...这很棒,但是这个过程需要一分钟,我想向用户展示(只要代码不复杂)发生了什么。< / p>
所以我在图像旁边放了一个标签,在我尝试做的时候在代码后面:
lblStatus.Text = "Doing xyz";
它提供了某种命名空间问题。我有什么想法可以实现这个目标吗?
更新: 错误是“无法找到类型或名称空间'lblStatus'。”
答案 0 :(得分:5)
你无法使用.net更新面板执行此操作,至少我不认为这很容易。虽然你可以通过2个独立的AJAX调用来实现它。
此示例使用JQuery作为AJAX,代码隐藏在vb.net中。
基本上你需要做的就是让你的第一次调用开始漫长的过程,然后重复进行第二次调用,使用第二种方法来获得长的过程的状态。
AJAX
这是您对漫长过程的主要要求。如果需要,您需要将数据传递给方法。请注意,有一个processName。这应该是一个随机的字符串,以确保您只获得此进程的状态。其他用户将拥有不同的随机进程名称,因此您不会感到困惑。
var processName = function GenerateProcessName() {
var str = "";
var alhpabet = "abcdefghijklmnopqrstuvwxyz";
for (i = 1; i < 20; i++) {
str += alhpabet.charAt(Math.floor(Math.random() * alhpabet.length + 1));
}
return str;
}
function StartMainProcess(){
$j.ajax({
type: "POST",
url: "/MyWebservice.asmx/MyMainWorker",
data: "{'processName' : '" + processName + "','someOtherData':'fooBar'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
if (msg.d) {
// do a final timerPoll - process checker will clear everything else
TimerPoll();
}
}
});
TimerPoll();
}
您的第二个AJAX调用将是另一种获取进度的方法。这将通过计时器方法每隔XXX次调用一次。
这是TimerPoll功能;在这种情况下将每3秒触发一次
function TimerPoll() {
timer = setTimeout("GetProgress()", 3000)
}
最后,GetProgress()函数可以获得进度。我们必须传入上面使用的相同processName,才能获得此用户调用的过程
function GetProgress() {
// make the ajax call
$j.ajax({
type: "POST",
url: "/MyWebService.asmx/MyMainWorkerProgress",
data: "{'processName' : '" + processName + "'}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
// Evaulate result..
var process = msg.d
if (process.processComplete) {
// destroy the timer to stop polling for progress
clearTimeout(timer);
// Do your final message to the user here.
} else {
// show the messages you have to the user.
// these will be in msg.d.messages
// poll timer for another trip
TimerPoll();
}
});
}
现在,在后端,您将有几个与AJAX通信的Web方法。您还需要一个共享/静态对象来保存所有进度信息,以及您想要传递给用户的任何内容。
在我的例子中,我创建了一个类,它的属性已经填充,并在每次调用MyMainWorkerProcess时传回。这看起来有点像这样。
Public Class ProcessData
Public Property processComplete As Boolean
Public Property messages As List(Of String) = New List(Of String)
End Class
我还有一个使用此类的共享属性,它看起来像......(这个共享属性能够由多个用户保存多个进程 - 因此是字典。字典的键将是进程名称。所有进度数据将在ProcessData类中
Private Shared processProgress As Dictionary(Of String, ProcessData) = New Dictionary(Of String, ProcessData)
我的主要工作人员功能看起来有点像这样。请注意,我们首先确保没有其他具有相同
的processProgress<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function MyMainWorker(ByVal processName as string, ByVal SomeOtherData as string) as Boolean
'' Create progress object - GUI outputs process to user
'' If the same process name already exists - destroy it
If (FileMaker.processProgress.ContainsKey(processName)) Then
FileMaker.processProgress.Remove(processName)
End If
'' now create a new process
dim processD as ProcessData = new ProcessData() with {.processComplete = false}
'' Start doing your long process.
'' While it's running and after whatever steps you choose you can add messages into the processData which will be output to the user when they call for the updates
processD.messages.Add("I just started the process")
processD.messages.Add("I just did step 1 of 20")
processD.messages.Add("I just did step 2 of 20 etc etc")
'' Once done, return true so that the AJAX call to this method knows we're done..
return true
End Function
现在剩下的就是调用progress方法了。所有这一切都是返回字典processData,它具有我们之前设置的相同processName ..
<WebMethod()> _
<ScriptMethod(ResponseFormat:=ResponseFormat.Json)> _
Public Function MyMainWorkerProgress(ByVal processName As String) As ProcessData
Dim serializer As New JavaScriptSerializer()
If (FileMaker.processProgress.ContainsKey(processName)) Then
Return processProgress.Item(processName)
Else
Return New ProcessData()
End If
End Function
瞧..
所以回顾一下..
...声明 我之前没有在这里提供过这么长的答案。它可能不符合人们习惯看到的格式。对不起,如果这一切看起来有点令人困惑:)我已经从正在运行的项目复制了大部分代码,所以它应该工作..但如果有一些错别字,请不要拍我:)
答案 1 :(得分:1)
如果您想要更改,请动态使用以下代码,
创建如下所示的功能
function ChangeUpdateProgress(message)
{
document.getElementById('lblStatus').innerText=message;
}
调用事件的OnClick
函数
<asp:LinkButton ID="btnUpdate" runat="server"Text="Update" OnClientClick="ChangeUpdateProgress('Please wait Updating....')" OnClick="btnUpdate_Click"></asp:LinkButton>
<asp:LinkButton ID="btnAdd" runat="server" OnClientClick="ChangeUpdateProgress('Please wait Adding....')" OnClick="btnAdd_Click"></asp:LinkButton>
希望这会有所帮助..
答案 2 :(得分:0)
代码将很复杂,因为你不能直接这样做。
ASP.NET AJAX请求的体系结构是在请求完成之前它不会返回任何内容。这为您提供了一些不同的选项,包括: -
1)将操作拆分为多个加载,自动重新部分过帐以执行下一个加载并更新标签
2)在服务上的单独进程中运行操作(例如,使用EXE)并在计时器上执行常规的部分回发,以与服务器上的EXE通信并获取当前状态并更新标签
3)在iframe的页面中运行任务并使用Response.Write更新iframe并关闭缓冲(或者每次状态更新后至少刷新一次)
答案 3 :(得分:0)
要显示状态,您需要2个不同的AJAX调用,一个是当前和主要实际完成工作,另一个是检查当前状态返回一个非常简单的消息。
//Changes the HTML like this
<asp:UpdateProgress runat="server" ID="PageUpdateProgress">
<ProgressTemplate>
<span id="currentStatu"></span> <img src="ajax-loader.gif" />
</ProgressTemplate>
</asp:UpdateProgress>
//Javascript
setInterval(jQuery.get(page.aspx?status=1, function () { $("#currentStatu").text(data); } ), 500); // every 0.5 second.
棘手的部分是如何从服务器端获取当前状态。如果您可以将它保留在Session中,那么当Request [“status”] ==“1”时,这将是最简单的方法,只需将此会话作为文本返回,并且全部完成。
另一方面,您也可以查询您的数据库以获取当前状态。
我希望它有所帮助。