65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 AJAX.NET Timer 和 UpdatePanel 实现延迟内容加载

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.48/5 (18投票s)

2007 年 6 月 5 日

4分钟阅读

viewsIcon

147071

downloadIcon

2009

本教程介绍如何在页面加载完成后再加载页面的某些部分。此示例使用 AJAX.NET Framework 中的 Timer 和 UpdatePanel 控件来加载内容。

Screenshot - DelayedContentLoading1.jpg

引言

当使用像长时间运行的 Web 服务或来自外部 Web 源的 RSS Feed 等内容时,最好先加载页面的重要部分,然后再加载加载速度较慢的部分。此示例将演示如何在页面主体有机会加载后加载多个 RSS 标题块。在页面加载期间,会显示占位符以指示将要加载其他内容。页面加载完成后,将异步检索并显示占位符的内容。

通常,页面上会出现需要比页面其余部分加载更长时间的内容。在某些情况下,您可以使用缓存来帮助解决此问题,但这并不总是可行或唯一的选择。如果某些内容加载时间比正常情况长,则显示某种视觉反馈给用户非常重要,以便他们知道需要等待。从远程服务器检索信息、显示大量数据以及照片库是一些可以推迟加载特定内容区域的示例。

必备组件

此示例使用

创建用户控件

您可以在 ASPX 页面上完成所有这些工作,但在此示例中,我们将使用一个UserControl。我选择创建一个消耗 RSS Feed 的UserControl,这个控件的名称正如其名,叫做RSSFeed.ascx。该控件使用ASP:TimerASP:UpdatePanelASP:MultiView控件来创建一个在页面加载后 1 毫秒加载的内容块。

用户控件源代码 (RSSFeed.ascx)

UserControl的源代码中,需要关注的关键区域是

  • ASP:TimerOnTick事件 - 在页面加载后 1 毫秒触发 - 触发从 RSS Feed 加载 RSS 标题的例程
  • ASP:UpdatePanel使用 AJAX 将标题加载到内容块中,并在不刷新页面的情况下更改ASP:MultiView
  • ASP:MultiView支持多种显示选项,具体取决于内容块所处的阶段,例如:默认、内容已加载、内容加载失败
<%@ Control Language="VB" AutoEventWireup="false"
  CodeFile="RSSFeed.ascx.vb" Inherits="RSSFeed" %>
<%@ Register Assembly="RssToolkit" Namespace="RssToolkit" TagPrefix="cc1" %>

<%--
  Create a datasource for the RSS feed.  For this example, I have used the
  RSS Toolkit to consume a RSS feed.
--%>
<cc1:RssDataSource ID="rssData"  runat="server"
  Url="http://tempuri.com"
  MaxItems="5" />

<asp:Panel runat="server" ID="pnlRSS" CssClass="RSSBlock" Width="275">
  <asp:Label runat="Server" ID="lblHeader" Text="Headlines" Visible="False" />
  <asp:UpdatePanel runat="Server" ID="updateRSS" UpdateMode="Conditional">
    <ContentTemplate>
      <asp:MultiView runat="server" ID="mvRSS" ActiveViewIndex="0" >

        <%-- This is the default view that will load with the page --%>
        <asp:View runat="Server" ID="view1">
          <asp:image runat="server" ID="image1"
            ImageAlign="middle" ImageUrl="spinner.gif" />
          <asp:Label runat="Server" ID="label1"
            Text="Loading..." Font-Size="smaller" ForeColor="orange" />
        </asp:View>

        <%--
          This is the where you will display the content that you want to
          load AFTER the page loads.  In this example, the RSS headlines
          will be ret rived and displayed here.
        --%>
        <asp:View runat="server" ID="view2">
          <asp:Repeater runat="Server" ID="rptRSS">
            <HeaderTemplate>
               <asp:Label runat="Server" id="lblRSSHeader"
                    Text='<%# lblHeader.Text %>'
                    Class="RSSHeader" />
                <ul>
            </HeaderTemplate>
            <ItemTemplate>
              <li>
                <asp:hyperlink runat="server" ID="linkRSS"
                  Text='<%# Eval("Title") %>'
                  NavigateUrl='<%# Eval("Link") %>' />
              </li>
            </ItemTemplate>
            <FooterTemplate></ul></FooterTemplate>
          </asp:Repeater>
        </asp:View>

        <%-- This is displayed if the content fails to load --%>
        <asp:View runat="Server" ID="view3">
          <asp:Label runat="Server" ID="lblNoData"
            Text="Unable to load headlines at this time."
            Font-Size="smaller" ForeColor="orange" />
        </asp:View>
      </asp:MultiView>


      <%--
        The timer works in millisecond intervals.  A setting of "1"
        will begin loading the block almost instantly after the page loads.
      --%>
      <asp:Timer ID="timerRSS" Interval="1"
        OnTick="DisplayRSS" runat="server" />

    </ContentTemplate>
  </asp:UpdatePanel>
</asp:Panel>

用户控件代码隐藏 (RSSFeed.ascx.vb)

请注意以下关键区域

  • 两个公共属性 URL 和 RSSTitle 将允许您将 RSS Feed 的 URL 和内容块的标题传递给UserControl。您将在后面的文章中看到如何实现这一点。
  • DisplayRSS子程序通过ASP:Timer的 OnTick 事件在达到其 Interval 时被触发。当然,您也可以轻松地做其他事情,例如显示长时间运行的 Web 服务的结果、大型数据表、大型图像、视频等。
Option Strict On
Option Explicit On

Imports System.Data
Imports System.Xml
Imports System.Net
Imports System.IO

Partial Class RSSFeed
  Inherits System.Web.UI.UserControl

  Public WriteOnly Property URL() As String
    Set(ByVal value As String)
    'Link to the RSS XML page

      rssData.Url = value
    End Set
  End Property

  Public WriteOnly Property RSSTitle() As String
    Set(ByVal value As String)
    'Create a header for the RSS block

      lblHeader.Text = value
    End Set
  End Property

  Protected Sub DisplayRSS(ByVal s As Object, ByVal e As EventArgs)
    Try

      'Download the RSS feed

      Dim wc As WebClient
      wc = New WebClient()
      wc.Proxy.Credentials = 
        System.Net.CredentialCache.DefaultNetworkCredentials
      Dim feed As Byte()
      feed = wc.DownloadData(rssData.Url)


      'Populate the RSS content block

      rptRSS.DataSource = rssData
      rptRSS.DataBind()

     'Display the loaded content block

      mvRSS.ActiveViewIndex = 1
    Catch ex As Exception
      'Display the "unable to load" content block

      mvRSS.ActiveViewIndex = 2
    End Try

    'Important! Turn the timer off or it will continuously run

    'this routine.  You could add an increased value to the

    'Interval setting if you want it to try again but, at some

    'point you need to tell it to stop--unless you are purposefully

    'cycling through content.

    timerRSS.Enabled = False
  End Sub
End Class

将用户控件添加到网页

在此示例中,多个 RSSFeedUserControl实例已添加到Default.aspx以演示效果。大多数UserControl都提供了有效的 RSS URL,但有些提供了无效或缺失的 URL,以展示内容无法正确加载时会发生的情况。RSS Feed 来自各种不同的 Web 源。以下是如何将UserControl添加到网页的方法

在页面顶部,<%@ Page %>指令之后

<%@ Register Src="RSSFeed.ascx" TagName="RSSFeed" TagPrefix="uc1" %> 

在页面正文中

请注意,该控件正在接收我们之前创建的 RSSTitle 和 URL 属性的值。

<uc1:RSSFeed id="RSSFeed1" runat="server"
   RSSTitle="MSDN: United States"
   URL="http://msdn.microsoft.com/globalrss/en-us/global-msdn-en-us.xml"  />

本地运行示例

  • 下载示例文件 (VB | C#)
  • 解压到本地文件夹
  • 在 Web Developer Express 或 Visual Studio 2005 中将DelayedContentLoading文件夹打开为网站
  • 生成并运行网站

关注点

  • 使用多个带有计时器的UserControl时,它们将按顺序一个接一个地加载。这意味着第二个UserControl将在第一个UserControl加载后开始其计时器,依此类推。
  • 块中的内容不是随页面一起加载的。因此,搜索引擎将不会索引页面加载后加载的内容块。查看在线示例的源代码以了解我的意思。
  • 这些内容块可能会造成可访问性问题。由于它们未添加到页面源代码中,我不确定屏幕阅读器和其他辅助技术 (AT) 会如何响应。也许有人可以在下面的评论区提供一些反馈。

高级选项

通过为延迟内容创建一个UserControl,我们现在拥有了一个可重用的控件,可以动态添加。因此,请考虑以下扩展此想法的选项

  • 将多个UserControl实例加载到ASP:PlaceHolder中,而不是在页面上手动逐个编写它们。
  • 如果在OnTick事件触发后不停止ASP:Timer,它会一直运行。如果您使用更长的间隔,例如 5000(5 秒),您可以让计时器运行并显示每 5 秒更改一次的内容块系列。

历史

  • 2007 年 6 月 5 日 - 发布原始版本
  • 2007 年 6 月 6 日 - 根据 nbr (Noel) 的建议更新,以支持代理。最初在DmitryR 的博客上提出
  • 2007 年 10 月 24 日 - 添加了演示项目的 C# 版本 (感谢 Shawn N.!)
© . All rights reserved.