决战.NET
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

第4章ASP.NET AJAX提高篇

4.1 动态加载的课题

前一章中,已经展示了如何动态加载UserControl至UpdatePanel控件中,但这只是一段旅程的序曲,动态加载的复杂性远超过你的想象,一般来说,动态加载控件至UpdatePanel控件中并不是最大的问题,如何维持载入的控件能正常运作才是最大的课题,就如同动态加载控件至PlaceHolder或Panel控件中一样,在下次Postback发生前,我们必须负责重载已加载的控件,否则该控件的事件将无法正常递送。请照以下的步骤来建立一个Web Site。

1. 建立一个AJAX-Enabled的Web Site,命名为AjaxDemo2。

2. 建立一个UserControl,命名为WebUserControl2.ascx。

3. 在UserControl中放入一个Calender控件。

4. 建立一个新网页,命名为DynamicLoadUserControl.aspx。

5. 在页面中放入一个ScriptManager控件。

6. 在页面中放入一个UpdatePanel控件。

7. 将UpdatePanel1控件的UpdateMode设为Conditional。

8. 放一个Button控件至UpdatePanel控件中。

9. 在Button的Click事件中,键入程序4-1的代码。

程序4-1

    Samples\4\AjaxDemo2\DynamicLoadUserControl.aspx.cs
    protected void Button1_Click(object sender, EventArgs e)
    {
                if (UpdatePanel1.ContentTemplateContainer.FindControl(
                    "Dynamic_UserControl1") == null)
                {
                      Control c = LoadControl("WebUserControl2.ascx");
                      c.ID = "Dynamic_UserControl_Hidden1";
                      UpdatePanel1.ContentTemplateContainer.Controls.Add(c);
                }
    }

执行程序并点击Button后,Calender如预期般显示,但若再点击某个日期后,Calender便立刻消失,这与动态加载控件至PlaceHolder及Panel控件的情况一样,因为点击日期后并未触发Button的Click事件,所以也就没有加载UserControl的动作发生,自然UserControl也不可能显示在网页上。那么该如何做才能正常呢?与使用PlaceHolder及Panel动态加载控件的解法相同,我们必须建立一个标记,当Button被点击时设定这个标记,这样在下次Postback发生时,即可用此标记来判定是否要加载UserControl,担任此标记最好的演员便是Hidden Field。请照以下的步骤来修改此例。

1. 删除Button的Click事件中的程序代码。

2. 在网页源码中放入Hidden Field,如程序4-2之粗体字所示。

3. 在此网页的.cs中加入程序4-3的代码。

程序4-2

    Samples\4\AjaxDemo2\DynamicLoadUserControl.aspx
    <%@ Page Language="C#" AutoEventWireup="true" CodeFile=
      "DynamicLoadUserControl.aspx.cs" Inherits="DynamicLoadUserControl" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
      "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" >
    <head runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
        </div>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server">
                <ContentTemplate>
                  <input type=hidden ID="Dynamic_UserControl_Hidden1" runat=server/>
                  <asp:Button ID="Button1" runat="server" Text="Button"
                          OnClientClick="ShowControl();" OnClick="Button1_Click" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </form>
    </body>
    </html>

程序4-3

    Samples\4\AjaxDemo2\DynamicLoadUserControl.aspx.cs
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    public partial class DynamicLoadUserControl : System.Web.UI.Page
    {
        protected void Page_Init(object sender, EventArgs e)
        {
            //从送来的参数中,判断UserControl是否已经加载
            if (Request.Params["Dynamic_UserControl_Hidden1"] == "true")
                LoadDynamicUserControl();
        }
        //动态加载UserControl
        private void LoadDynamicUserControl()
        {
            if (UpdatePanel1.ContentTemplateContainer.FindControl(
                                      "Dynamic_UserControl1") == null)
            {
                Control c = LoadControl("WebUserControl2.ascx");
                c.ID = "Dynamic_UserControl1";
                //取得位于UserControl中的Hidden Field,并将其值设为True,
                //代表UserControl已经加载
                HtmlInputHidden hidden = (HtmlInputHidden)
                  UpdatePanel1.ContentTemplateContainer.FindControl(
                                      "Dynamic_UserControl_Hidden1");
                hidden.Value = "true";
                UpdatePanel1.ContentTemplateContainer.Controls.Add(c);
            }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            //送上来的参数中的Hidden Field表示UserControl已载入,
            //将载入的UserControl删除
            if (Request.Params["Dynamic_UserControl_Hidden1"] == "true")
            {
                UpdatePanel1.ContentTemplateContainer.Controls.Remove(
                          UpdatePanel1.ContentTemplateContainer.FindControl(
                          "Dynamic_UserControl1"));
                HtmlInputHidden hidden = (HtmlInputHidden)
                          UpdatePanel1.ContentTemplateContainer.FindControl(
                          "Dynamic_UserControl_Hidden1");
                hidden.Value = "false";
            }
            else
                LoadDynamicUserControl();
        }
    }

完成后执行程序,点击Button后Calendar显示,此次你能正常地点击任何日期,而不会使Calendar消失,如图4-1所示。

true

图4-1

同时再次点击Button后,Calendar也会消失,这是借助Hidden Field的帮助。除了使用Hidden Field之外,我们也可以利用VIEWSTATE来达到同样的效果,这个方法的好处是不需要另一个Hidden Field的帮助,程序代码会显得较简洁、直观,如程序4-4所示。

程序4-4

    Samples\4\AjaxDemo2\DynamicLoadUserControlWithViewState.aspx
    <%@ Page Language="C#" AutoEventWireup="true"
      CodeFile="DynamicLoadUserControlWithViewState.aspx.cs"
      Inherits="DynamicLoadUserControlWithViewState" %>
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head id="Head1" runat="server">
        <title>Untitled Page</title>
    </head>
    <body>
        <form id="form1" runat="server">
        <div>
            <asp:ScriptManager ID="ScriptManager1" runat="server">
            </asp:ScriptManager>
        </div>
            <asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode=
              "Conditional">
                <ContentTemplate>
                    <asp:Button ID="Button1" runat="server" Text="Button"
                          OnClick="Button1_Click" />
                </ContentTemplate>
            </asp:UpdatePanel>
        </form>
    </body>
    </html>
    Samples\4\AjaxDemo2\DynamicLoadUserControlWithViewState.aspx.cs
    using System;
    using System.Data;
    using System.Configuration;
    using System.Collections;
    using System.Web;
    using System.Web.Security;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Web.UI.WebControls.WebParts;
    using System.Web.UI.HtmlControls;
    public partial class DynamicLoadUserControlWithViewState : System.Web.UI.Page
    {
        private bool ControlIsLoaded
        {
            get
            {
                object o = ViewState["ControlIsLoaded"];
                return (o == null ? false : (bool)o);
            }
            set
            {
                ViewState["ControlIsLoaded"] = value;
            }
        }
        private void LoadDynamicUserControl()
        {
            if (UpdatePanel1.ContentTemplateContainer.FindControl(
                "Dynamic_UserControl1") == null)
            {
                Control c = LoadControl("WebUserControl2.ascx");
                c.ID = "Dynamic_UserControl1";
                ControlIsLoaded = true;
                UpdatePanel1.ContentTemplateContainer.Controls.Add(c);
            }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (ControlIsLoaded)
                LoadDynamicUserControl();
        }
        protected void Button1_Click(object sender, EventArgs e)
        {
            if (ControlIsLoaded)
            {
                UpdatePanel1.ContentTemplateContainer.Controls.Remove(
                  UpdatePanel1.ContentTemplateContainer.FindControl(
                  "Dynamic_UserControl1"));
                ControlIsLoaded = false;
            }
            else
                LoadDynamicUserControl();
        }
    }

截至目前,我们已经看过两种动态显示控件的方式,第一种较为简单、不需要设计师写太多的程序代码,第二种较为复杂,需要设计师写较多的的程序代码,两者间性能的差距在于初次加载网页时,第一种不管如何都会建立欲动态显示的控件,虽然将其Visible设为False能减轻初次载入网页的负担,但毕竟控件还是加载了,对性能多少都有一些影响;第二种则是完全动态式的加载,初期并未建立该控件,而是需要时才建立,当网页上有多种这类控件时,这种做法特别有效率。