ASP.NET 文件处理页面,无法在程序开始之前获取正在加载的 GIF 以呈现

ASP.NET page for file processing, Unable to get a Loading GIF to render before procedures begin

我有一个 webforms 应用程序,它使用一个典型的文件下载器页面,可以从我的应用程序中的许多地方访问。在正常情况下,页面提供文件,关闭,用户甚至不知道它的存在。但是,我添加了一个 PDF 转换工具,可以将某些文档转换为 PDF,这个过程需要几秒钟,所以最终用户会看到该页面,我同意。

我正在尝试向页面添加一些简单的文本和“正在加载”GIF,但我无法在页面加载事件开始并阻止页面呈现之前呈现它。

我有一个简单的页面加载事件来决定 运行。

Protected Sub Page_Load(sender As Object, e As EventArgs) Handles Me.Load
    If Not Me.IsPostBack Then
        Dim Type As String = Request.QueryString("Type")
        If Type = "File" Then
            'TODO
        ElseIf Type = "DB" Then
            OpenDBFile()
        ElseIf Type = "QCBDBYMCSID" Then
            OpenQCBD("BYMCSID")
        ElseIf Type = "QCBDBYNAME" Then
            OpenQCBD("BYNAME")
        Else
            'TODO
        End If
    End If
End Sub

我试图通过在页面生命周期后期用一个事件替换 Me.Load 来延迟它,例如 Me.SaveStateComplete 但没有任何变化。

在客户端,我尝试了几个不同的选项,使用和更新面板,一个 UpdateProgress 和一个普通的 DIV 使用 CSS 来设置背景图像而不是图像标签,但没有显示。

这里有 2 个我尝试过的例子。

    <asp:UpdatePanel ID="UpdatePanel1" runat="server" >
        <ContentTemplate>
            <div style="text-align: center">
                <h1 style="text-align: center;">MCS File Downloader</h1>
                <asp:Image ID="Image2" ImageAlign="Middle" ImageUrl="~/MyPictures/colorchangearrowdown.gif" runat="server" />
                <h3 runat="server" id="h3Text" style="text-align: center">Processing File...</h3>
            </div>
        </ContentTemplate>
    </asp:UpdatePanel>


<asp:UpdateProgress ID="prgLoadingStatus" runat="server" DynamicLayout="true">
            <ProgressTemplate>
                <div id="overlay">
                    <div id="modalprogress">
                        <div id="theprogress">
                            <h1 style="text-align: center;">MCS File Downloader</h1>
                            <asp:Image ID="imgWaitIcon" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/MyPictures/colorchangearrowdown.gif" />
                            <h3 runat="server" id="h3Text" style="text-align: center">Processing File...</h3>
                        </div>
                    </div>
                </div>
            </ProgressTemplate>
        </asp:UpdateProgress>

如有任何帮助,我们将不胜感激!

好吧,您无法关闭或隐藏隐藏代码等等任何东西。你点击一个按钮,页面就会被发送到服务器。然后在运行s后面编码,然后将页面发送回去。

隐藏代码从不直接与用户交互。页面 post 返回将整个页面发送到服务器。当代码在 运行s 时,它可以修改控件、文本框等。但是,用户看到的是零,直到后面的所有代码都完成,然后整个页面让它回到客户端,是re-loaded,JavaScrip re-runs,然后显示页面。因此,处理各种服务器端代码是 100% 的时间浪费,是徒劳的追逐。

然而,通过简单地掌握页面 life-cycle 和 post 返回(所谓的往返),然后一些解决方案变得容易 - 实际上在这里非常简单。

所以,无论你想做什么?比如说点击一个按钮?然后添加客户端事件和服务器端事件。

客户端现在可以显示微调器(动画 gif)或其他内容。事实上,在 99% 的情况下,您不需要任何代码来隐藏微调器或其他任何东西,因为所有服务器端代码何时完成?好吧,一个全新的网页副本从服务器上快速下来,因此您可以免费获得整个页面的 re-plot 和 re-load - 包括您隐藏的 spinner/gif现在又被隐藏了。

因此,在最简单的层面上,在空白的新测试页上尝试此代码:

你不需要花哨的代码,你不需要线程,你不需要太多的东西。 (但您确实需要简单了解页面 post-backs 的工作原理)。

所以,我们要在网页上放置一个按钮。我们将单击该按钮,后面有一段很长的 运行ning 服务器端按钮代码(比如 5 秒)。后面的代码完成后,微调器将消失。

所以,我们有这个标记:一个按钮,然后是动画“gif”微调器:

       <div id="MySpinner" runat="server" style="display:none">
            <img src="Content/wait2.gif" />
        </div>


        <div id="MyGrid" runat="server" style="width:50%">
            <asp:GridView ID="GridView1" runat="server" CssClass="table"></asp:GridView>
        </div>

        <asp:Button ID="cmdLoadGrid" runat="server" Text="Load data" CssClass="btn"
            OnClientClick="ShowSpinner();return true;" />


    </div>

        <script>

            function ShowSpinner() {
                $("#MySpinner").show();

            }

        </script>

请注意我如何将微调器隐藏在 div(显示:none)中。

注意我们有一个平面简按钮,但它也有一个客户端点击事件。

后面的代码是这样的

Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) 句柄 Me.Load

End Sub

Protected Sub cmdLoadGrid_Click(sender As Object, e As EventArgs) Handles cmdLoadGrid.Click

    Thread.Sleep(4000)       ' fake a big delay

    Dim strSQL As String = "SELECT TOP 6 ID, FirstName, LastName, HotelName, City, Description from tblHotels
                            WHERE Description is not null"

    Using conn As New SqlConnection(My.Settings.TEST4)
        Using cmdSQL As New SqlCommand(strSQL, conn)

            conn.Open()
            GridView1.DataSource = cmdSQL.ExecuteReader
            GridView1.DataBind()

        End Using
    End Using

    '' hide the spinner
    'MySpinner.Style("Display") = "none"
    'MyGrid.Style("Display") = "normal"

End Sub

所以我加入了 4 秒的“假”延迟。

因此,页面如下所示:

如果我点击按钮,我们会看到:

然后当服务器代码完成后,它发回整个页面,我现在看到了这个:

请注意,我什至不必“隐藏”微调器 gif - 当后面的代码完成后,它会恢复到其原始设置,并且现在将整个新页面发送回客户端。

因此弹出您的 gif 或 toast 消息,甚至 jQuery 带有“请稍候”的对话框。当服务器端代码完成时,一切都会被吹走,新的新鲜网页返回到客户端。

编辑:好的,假设您掌握了页面生命周期?

因此,您可以 运行 页面加载所需的所有代码 - 直到马匹回家,但代码和页面仍在服务器上。所以你必须让页面向下移动到客户端。这意味着您后面的代码必须完成对网页的修改和更改。

THEN 并且仅然后页面向下移动到客户端并显示。因此,您可以在页面上的任何事件中更改内容,但只有在页面然后向下移动到客户端之后,最终用户才会看到您的代码背后的更改结果。

那么,简单解释一下这意味着什么?

您必须让页面向下传送到客户端。然后单击一个按钮以显示您的 message/gif,然后 运行 您的服务器端代码。

所以,你可以这样做:

首先炸毁并丢弃您的更新面板 - 您不需要它们。

因此,您像这样放入 div,连同一个隐藏字段,以及一个单击按钮,然后 运行 您的代码(但是,代替用户单击在按钮上,我们将获得客户端代码来为我们点击该按钮!!!)。

所以,你有这个:

        <div id="theprogress" runat="server">
            <h1 style="text-align: center;">MCS File Downloader</h1>
            <asp:Image ID="imgWaitIcon" runat="server" ImageAlign="AbsMiddle" ImageUrl="~/MyPictures/colorchangearrowdown.gif" />
            <h3 runat="server" id="h3Text" style="text-align: center">Processing File...</h3>
        </div>

        <asp:Button ID="cmdLoad" runat="server" Text="Button" ClientIDMode="Static" />

注意上面的按钮,所以,将您的代码放在该按钮中: 例如:

 Protected Sub cmdLoad_Click(sender As Object, e As EventArgs) Handles cmdLoad.Click


    Dim Type As String = Request.QueryString("Type")
    If Type = "File" Then
        'TODO
    ElseIf Type = "DB" Then
        OpenDBFile()
    ElseIf Type = "QCBDBYMCSID" Then
        OpenQCBD("BYMCSID")
    ElseIf Type = "QCBDBYNAME" Then
        OpenQCBD("BYNAME")
    Else
        'TODO
    End If

    theprogress.Style.Add("Display", "none") ' hide progress when we are done


End Sub

那么,现在会发生什么?

页面加载将注入一个按钮点击。代码已完成,现在页面向下传送到客户端 - div 将显示您的进度 +“动画”。您在页面加载中注入的 JavaScript 代码现在将单击该按钮,并且会出现 post 返回 - 但页面会显示,并且会一直显示直到您的代码完成,然后您的后面的代码隐藏了动画。由于这表明某种可能的文件下载,因此将隐藏进度 div 移动到按钮单击的第一行。

最后一个任务:一旦一切正常,然后隐藏bu吨在页面上:

<asp:Button ID="cmdLoad" runat="server" Text="Button"
    ClientIDMode="Static" style="display:none" />