官术网_书友最值得收藏!

  • 決戰.NET
  • 黃忠成
  • 1666字
  • 2018-12-27 16:56:04

5.2 當UpdatePanel遇上MasterPage

MasterPage技術的出現,讓設計師可以輕松地設計網頁樣板,ASP.NET AJAX自然也支持這種架構,設計師只需在MasterPage中放置一個ScriptManager控件,之后套用此MasterPage的頁面便可直接放入UpdatePanel等ASP.NET AJAX的控件,無需再放入ScriptManager控件。這樣的應用相當常見,并無任何可議之處,唯一可能會引發問題的情況是套用MasterPage之頁面內的UpdatePanel控件需要依賴MasterPage中的控件來刷新時,此時并無法依賴Triggers來實現,因為你無法在Triggers編輯窗中選取位于MasterPage中的控件,這有兩種解法,一是將MasterPage中欲觸發UpdatePanel刷新的控件,通過ScriptManager的RegisterAsyncPostback函數注冊成Async-Postback的控件,一旦完成此動作后,該控件的任何Postback動作將轉變成Async-Postback,再對應于事件中,以Update函數來更新UpdatePanel即可。請照著下列步驟做。

1. 于AdvAjaxDemo的Web Site項目中新增一個MasterPage,命名為Default.master。

2. 在其內鍵入程序5-3的程序代碼。

3. 在Default.master.cs中鍵入程序5-4的代碼。

程序5-3

    Samples\5\AdvAjaxDemo\Default.master
    <%@ Master Language="C#" AutoEventWireup="true" CodeFile="Default.master.cs"
      Inherits="_Default" %>
    <!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>
            <table>
            <tr>
            <td valign=top>
                  <asp:TreeView ID="TreeView1" runat="server" ImageSet="Msdn"
                      NodeIndent="10"
                      OnSelectedNodeChanged="TreeView1_SelectedNodeChanged">
                  <ParentNodeStyle Font-Bold="False" />
                  <HoverNodeStyle BackColor="#CCCCCC" BorderColor="#888888"
                      BorderStyle="Solid"
                      Font-Underline="True" />
                  <SelectedNodeStyle BackColor="White" BorderColor="#888888"
                      BorderStyle="Solid"
                      BorderWidth="1px"
                      Font-Underline="False" HorizontalPadding="3px"
                      VerticalPadding="1px" />
                  <NodeStyle Font-Names="Verdana" Font-Size="8pt"
                      ForeColor="Black"
                      HorizontalPadding="5px"
                      NodeSpacing="1px" VerticalPadding="2px" />
                </asp:TreeView>
            </td>
            <td valign=top>
            <asp:contentplaceholder id="ContentPlaceHolder1" runat="server">
            </asp:contentplaceholder>
            </td>
            </tr>
            </table>
        </div>
        </form>
    </body>
    </html>

程序5-4

    Samples\5\AdvAjaxDemo\Default.master.cs
    using System;
    using System.Data;
    using System.Data.SqlClient;
    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 _Default : System.Web.UI.MasterPage
    {
        private void BindTreeView()
        {
            TreeView1.Nodes.Clear();
            TreeNode currentMasterNode = null;
            using (SqlConnection conn =
              new SqlConnection(
                  ConfigurationManager.ConnectionStrings[
                  "NorthwindConnectionString"].ConnectionString))
            {
                using(SqlCommand cmd =
                  new SqlCommand(
                    "SELECT City FROM Customers GROUP BY City ORDER BY City",conn))
                {
                    conn.Open();
                    using(SqlDataReader reader =
                    cmd.ExecuteReader(CommandBehavior.CloseConnection))
                    {
                      while(reader.Read())
                      {
                        if (!reader.IsDBNull(0))
                        {
                      string city = reader.GetString(0);
                      if (currentMasterNode == null)
                      {
                                  currentMasterNode = new TreeNode(
                                    city.Substring(0, 1), "NonSelect");
                                  TreeView1.Nodes.Add(currentMasterNode);
                      }
                      else
                      {
                                  if (currentMasterNode.Text != city.Substring(0, 1))
                                  {
                                      currentMasterNode =
                                        new TreeNode(city.
                                        Substring(0, 1), "NonSelect");
                                      TreeView1.Nodes.Add(currentMasterNode);
                                  }
                      }
                      currentMasterNode.ChildNodes.Add(new TreeNode(city));
                        }
                      }
                    }
                }
            }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostback && !ScriptManager1.IsInAsyncPostback)
                BindTreeView();
            ScriptManager1.RegisterAsyncPostbackControl(TreeView1);
        }
        protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
        {
            UpdatePanel up = ContentPlaceHolder1.FindControl("UpdatePanel1")
              as UpdatePanel;
            up.Update();
        }
    }

此MasterPage一開始時,會由Northwind數據庫中的Customers數據表以GROUP BY City的方式取出城市數據列表,然后一一指定給頁面上的TreeView1控件,接著在Page_Load函數中將TreeView1注冊為Async-Postback控件,這時TreeView1的任何Postback動作都會被轉換成Async-Postback,不會引發整個頁面的刷新,接著在TreeView1的SelectedNodeChanged事件中,通過ContentPlaceHolder1取得要刷新的UpdatePanel,調用Update函數要求刷新。完成后請再照著下列步驟建立套用此MasterPage的頁面。

1. 新增一個網頁,命名為TreeViewWithGridView.aspx,套用Default.master作為Master Page。

2. 在頁面中放入一個UpdatePanel控件,命名為UpdatePanel1。

3. 在UpdatePanel1控件中放入一個SqlDataSource控件,命名為SqlDataSource1,連結至Northwind數據庫的Customers數據表,選取CustomerID、CompanyName、ContactTitle、ContactName字段,指定一個WHERE參數,如圖5-5所示。

4. 在UpdatePanel1控件中放入一個GridView控件,命名為GridView1,DataSourceID設為SqlDataSource1,勾選Enable Paging。

5. 在Page_Load函數中鍵入程序5-5的代碼。

true

圖5-5

程序5-5

    Samples\5\AdvAjaxDemo\ TreeViewWithGridView.aspx.cs
    protected void Page_Load(object sender, EventArgs e)
    {
            if (ScriptManager.GetCurrent(this).IsInAsyncPostback &&
              ScriptManager.GetCurrent(this).AsyncPostbackSourceElementID.
              EndsWith("TreeView1"))
            {
                TreeView tv =
                  (TreeView)Master.FindControl(ScriptManager.GetCurrent(this).
                  AsyncPostbackSourceElementID);
                if (tv.SelectedValue != "NonSelect")
                {
                    SqlDataSource1.SelectParameters["City"].DefaultValue =
                      tv.SelectedValue;
                    GridView1.DataBind();
                }
            }
    }

完成后將此頁面設為默認并運行,便可看到如圖5-6所示的畫面。

true

圖5-6

眼尖的讀者應發現這個設計有些問題,MasterPage與套用MasterPage的頁面有著一小層鏈接,那就是套用MasterPage的頁面之UpdatePanel控件必須命名為UpdatePanel1,這在大量使用MasterPage技術的系統中,會顯得非常不恰當,若能將此鏈接切斷,改由套用MasterPage的頁面來決定哪些UpdatePanel控件要隨著MasterPage上的控件動作而更新,豈不更好?辦得到嗎?當然!只要將MasterPage中的TreeView1設為UpdatePanel的Trigger就可以了,見程序5-6。

程序5-6

    Samples\5\AdvAjaxDemo\ TreeViewWithGridView.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 TreeViewWithGridView : System.Web.UI.Page
    {
        private void AttachUpdateTrigger()
        {
            TreeView tv = (TreeView)Master.FindControl("TreeView1");
            AsyncPostbackTrigger trigger = new AsyncPostbackTrigger();
            trigger.ControlID = tv.ID;
            trigger.EventName = "SelectedNodeChanged";
            UpdatePanel1.Triggers.Add(trigger);
        }
        protected void Page_Init(object sender, EventArgs e)
        {
            AttachUpdateTrigger();
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (ScriptManager.GetCurrent(this).IsInAsyncPostback &&
              ScriptManager.GetCurrent(this).AsyncPostbackSourceElementID.
              EndsWith("TreeView1"))
            {
                TreeView tv = (TreeView)Master.FindControl(
                    ScriptManager.GetCurrent(this).AsyncPostbackSourceElementID);
                if (tv.SelectedValue != "NonSelect")
                {
                    SqlDataSource1.SelectParameters["City"].DefaultValue =
                    tv.SelectedValue;
                    GridView1.DataBind();
                }
            }
        }
    }

程序5-6在Page_Init時調用了AttachUpdateTrigger函數,此函數會利用Master屬性來找到位于MasterPage中的TreeView1控件,并將其添加成UpdatePanel1的Trigger,此舉意味著當TreeView1發生Postback時,將會被轉變為Async-Postback,并引發UpdatePanel1的刷新動作。一旦此頁面添加Triggers后,MasterPage頁面就不需要再使用RegisterAsyncPostback來將TreeView1注冊為Async-Postback控件,也不需于TreeView1的SelectedNodeChanged事件中以Update函數來刷新UpdatePanel了,一切都移往套用MasterPage技術的頁面,這不是更符合群體開發時的情況嗎?程序5-7是修改后的Default.master.cs。

程序5-7

    Samples\5\AdvAjaxDemo\Default.master.cs
    using System;
    using System.Data;
    using System.Data.SqlClient;
    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 _Default : System.Web.UI.MasterPage
    {
        private void BindTreeView()
        {
            TreeView1.Nodes.Clear();
            TreeNode currentMasterNode = null;
            using (SqlConnection conn = new SqlConnection(
              ConfigurationManager.ConnectionStrings[
              "NorthwindConnectionString"].ConnectionString))
            {
                using(SqlCommand cmd = new SqlCommand(
                    "SELECT City FROM Customers GROUP BY City ORDER BY City",conn))
                {
                    conn.Open();
                    using(SqlDataReader reader =
                    cmd.ExecuteReader(CommandBehavior.CloseConnection))
                    {
                      while(reader.Read())
                      {
                        if (!reader.IsDBNull(0))
                        {
                      string city = reader.GetString(0);
                      if (currentMasterNode == null)
                      {
                                  currentMasterNode = new TreeNode(
                                    city.Substring(0, 1), "NonSelect");
                                  TreeView1.Nodes.Add(currentMasterNode);
                      }
                      else
                      {
                                  if (currentMasterNode.Text != city.Substring(0, 1))
                                  {
                                      currentMasterNode =
                                        new TreeNode(city.Substring(0,1),"NonSelect");
                                      TreeView1.Nodes.Add(currentMasterNode);
                                  }
                      }
                      currentMasterNode.ChildNodes.Add(new TreeNode(city));
                        }
                      }
                    }
                }
            }
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostback && !ScriptManager1.IsInAsyncPostback)
                BindTreeView();
          //  ScriptManager1.RegisterAsyncPostbackControl(TreeView1);
        }
        protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
        {
            //UpdatePanel up = ContentPlaceHolder1.FindControl("UpdatePanel1")
              as UpdatePanel;
            //up.Update();
        }
    }

ScriptManagerProxy與MasterPage

將ScriptManager控件放在MasterPage上的缺點是,套用此MasterPage的網頁由于沒有ScriptManager控件,所以無法通過ScriptManager控件的Scripts、Services來引入外部的JavaScript程序文件及Web Services,這時另一個ScriptManagerProxy控件便派上用場了,只要將ScriptManagerProxy控件放在套用MasterPage的頁面內的ContentPlaceHolder中,設計師便能通過它所提供的Scripts、Services來設定要引入的JavaScript程序文件及Web Services,這些設定會于此頁面被瀏覽時迭加到MasterPage中的ScriptManager控件內。舉個例子來說,Default2.master中的ScriptManager之Scripts引用了JScript1.js,Default2.aspx是套用了Default2.master作為MasterPage的頁面,只要在Default2.aspx的ContentPlaceHolder中放入一個ScriptManagerProxy控件,于其Scripts中添加引用JScript2.js,那么當用戶瀏覽Default2.aspx時,該頁面就會引用JScript1.js、JScript2.js兩個JavaScript程序文件。那如果MasterPage頁面中沒有ScriptManager控件,而套用MasterPage的頁面有呢?結果并不意外,ScriptManagerProxy控件會丟出需要ScriptManager控件的出錯信息。

主站蜘蛛池模板: 辽宁省| 邹平县| 余江县| 财经| 襄城县| 固始县| 新河县| 永平县| 建宁县| 清镇市| 许昌县| 朔州市| 龙门县| 丰台区| 博白县| 宣化县| 普格县| 定襄县| 云梦县| 堆龙德庆县| 密云县| 泰和县| 邵武市| 梓潼县| 阜阳市| 佛山市| 岑巩县| 府谷县| 澳门| 广安市| 准格尔旗| 恩平市| 双峰县| 浠水县| 芦溪县| 高密市| 桂平市| 卢氏县| 和林格尔县| 兰溪市| 商都县|