• <samp id="frm2q"><ins id="frm2q"></ins></samp>
      1. <samp id="frm2q"></samp>
        <progress id="frm2q"><bdo id="frm2q"><strong id="frm2q"></strong></bdo></progress>
        <menuitem id="frm2q"><ins id="frm2q"><u id="frm2q"></u></ins></menuitem>

        <progress id="frm2q"></progress>
      2. XTemplate + WCF 打造無刷新數據分頁

        小編:管理員 91閱讀 2022.09.07

        ExtJs的Grid組件雖然不管從哪一方面來講,都稱得上是很好很強大,但是總會有一些應用場景并不需要這么多功能,比如網站的留言列表,開發者只想要一個簡單的<li>或<table>列表而已,這時候XTemplate就顯得很有用了。 本文將講解如何用XTemplate結合WCF與服務端交互,生成數據列表,同時加上無刷新分頁功能(默認情況下ExtJs并沒有為XTemplate并沒有提供分頁功能) 1.先做一些準備工作,寫一個通用的類,用于WCF向ExtJs返回分頁數據

        Code
        using System;
        using System.Collections.Generic;
        using System.Runtime.Serialization;
        
        /// <summary>
        ///PageData 的摘要說明
        /// </summary>
        /// 
        [DataContract]
        public class PageData<T>
        {
            [DataMember]
            public int RecordCount { set; get; }
        
            [DataMember]
            public int PageSize { set; get; }
        
            [DataMember]
            public int PageCount { set; get; }
        
            [DataMember]
            public int CurrentPageIndex { set; get; }
        
            [DataMember]
            public T Data { set; get; }
        }
        復制

        2.DateTime序列化問題,因為.net序列化DateTime時,不管你怎么努力,只要是DateTime類型,最終只能生成類似 "F_Date":"\/Date(1221023588109+0800)\/"這樣的字符串,ExtJs并不能正確識別!為此我們需要一個第三方的用于序列化DateTime的小工具Newtonsoft.Json.dll,它是專門用于將對象序列化成Json字符串。重要的是,用這個序列化后的DateTime字符串,ExtJs能夠識別(注:百度搜索一下"Newtonsoft.Json"很容易就能找到N多下載的,下載后直接添加到項目引用里即可) 3.編寫具體的實體類T_GuestBook,直接在數據庫里建好,拖到dbml里就可以了,主要代碼如下(注意要設置dbml的序列化屬性為"單向",否則vs不會自動為class以及成員加上序列化標簽):

        Code
        [Table(Name="dbo.T_GuestBook")]
        [DataContract()]
        public partial class T_GuestBook : INotifyPropertyChanging, INotifyPropertyChanged
        {
            
            
            
            [Column(Storage="_F_ID", AutoSync=AutoSync.OnInsert, DbType="Int NOT NULL IDENTITY", IsPrimaryKey=true, IsDbGenerated=true)]
            [DataMember(Order=1)]
            public int F_ID
            {
                
            }
            
            [Column(Storage="_F_IP", DbType="NVarChar(15) NOT NULL", CanBeNull=false)]
            [DataMember(Order=2)]
            public string F_IP
            {
                
            }
            
            [Column(Storage="_F_Date", DbType="DateTime NOT NULL")]
            [DataMember(Order=3)]
            public System.DateTime F_Date
            {
                
            }
            
            [Column(Storage="_F_Content", DbType="NVarChar(1000) NOT NULL", CanBeNull=false)]
            [DataMember(Order=4)]
            public string F_Content
            {
                
            }
            
            [Column(Storage="_F_Reply", DbType="NVarChar(1000) NOT NULL", CanBeNull=false)]
            [DataMember(Order=5)]
            public string F_Reply
            {
                
            }
            
            
        }
        復制

        為閱讀方便,去掉了一些自動生成的代碼

        4.建一個WCF服務,并添加一個方法:

        Code
        [OperationContract]
            [WebInvoke(ResponseFormat = WebMessageFormat.Json,UriTemplate = "GetData2?PageSize={PageSize}&PageIndex={PageIndex}", Method = "*")]
            public string GetData2(int PageSize, int PageIndex)
            {
                System.Threading.Thread.Sleep(1000);//為演示Ajax加載效果,停1秒
        
                List<T_GuestBook> _List = new List<T_GuestBook>();
                _List.Add(new T_GuestBook() { F_ID = 1, F_IP = "192.23.37.41", F_Date = DateTime.Now, F_Content = "這是第一條留言", F_Reply = "" });
                _List.Add(new T_GuestBook() { F_ID = 2, F_IP = "192.168.0.1", F_Date = DateTime.Now, F_Content = "這是第二條留言", F_Reply = "" });
                _List.Add(new T_GuestBook() { F_ID = 3, F_IP = "192.168.0.2", F_Date = DateTime.Now, F_Content = "這是第三條留言", F_Reply = "" });
                _List.Add(new T_GuestBook() { F_ID = 4, F_IP = "172.168.235.1", F_Date = DateTime.Now, F_Content = "這是第四條留言", F_Reply = "" });
                _List.Add(new T_GuestBook() { F_ID = 5, F_IP = "10.200.30.4", F_Date = DateTime.Now, F_Content = "這是第五條留言", F_Reply = "" });
                _List.Add(new T_GuestBook() { F_ID = 6, F_IP = "10.200.30.5", F_Date = DateTime.Now, F_Content = "這是第六條留言", F_Reply = "" });
                //以上操作也可以改為利用Linq直接從數據庫讀取
        
        
        
                PageData<List<T_GuestBook>> _PageData = new PageData<List<T_GuestBook>>();
        
                _PageData.RecordCount = _List.Count;
        
                if (PageSize <= 0) { PageSize = 1; }
                if (PageSize > _PageData.RecordCount) { PageSize = _PageData.RecordCount; }
                _PageData.PageSize = PageSize;
        
                //計算總頁數
                if (_PageData.RecordCount % _PageData.PageSize == 0)
                {
                    _PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize);
                }
                else
                {
                    _PageData.PageCount = (_PageData.RecordCount / _PageData.PageSize) + 1;
                }
        
        
                if (PageIndex <= 0) { PageIndex = 1; }
                if (PageIndex > _PageData.PageCount) { PageIndex = _PageData.PageCount; }
        
                _PageData.CurrentPageIndex = PageIndex;
        
                List<T_GuestBook> _List2 = _List.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();//取得當前頁數據
        
                _PageData.Data = _List2;
        
                return JavaScriptConvert.SerializeObject(_PageData);
        
            }
        復制

        注意,這里我們返回的是string類型,并且是用JavaScriptConvert.SerializeObject處理后的JSON字符串,至于WebInvoke(ResponseFormat = WebMessageFormat.Json這里為什么要加Json返回格式,原因很簡單,不指定Json格式,默認就是以xml返回的,會無端在前后加上更多無用字符 5.ExtJs前端完整代碼:

        Code
         <html>
        <head>
            <title>ExtJs.XTemplate + WCF 打造無刷新數據分頁</title>   
            <script type="text/javascript" src="../adapter/ext/ext-base.js"></script>
            <script type="text/javascript" src="../ext-all-debug.js"></script>
            <style type="text/css">
                *{font-size: 9pt;line-height: 120%;}
                .red{color: Red;}
                h1{font-size:16px;}
            </style>
        </head>
        <body>
        
            <script type="text/javascript">
                Ext.onReady(function() {           
        
                    //定義XTemplate模板組件
                    var tpl = new Ext.XTemplate(
        '<table width="100%">',
        '<tpl for="Data">', //表明這里開始循環
        '<tr><td style="font-weight:bold;color:#666">網友[{F_IP}] {F_Date:date("Y-m-d H:i:s")} 說:</td></tr>',
        '<tr><td>  {F_Content}</td></tr>',
        '<tr><td><hr style="height:1px"/></td></tr>',
        '</tpl>', //循環結束
        '</table>',
        '<div id="Page">', //這里開始是分頁部分
        '<span style="float:left">當前:第<span class="red">{CurrentPageIndex}</span>頁/共<span class="red">{PageCount}</span>頁,<span class="red">{PageSize}</span>條/每頁,共<span>{RecordCount}</span>條</span>',
        '<span style="float:right"><a href="javascript:;" id="btnFirst">首頁</a>|<a href="javascript:;" id="btnPre">上頁</a>|<a href="javascript:;" id="btnNext">下頁</a>|<a href="javascript:;" id="btnLast">尾頁</a>',
        ' <input type="text" id="GoPage" style="width:20px" value="{CurrentPageIndex}"/><button id="btnGo">Go</button></span>',
        '</div>'
        );
        
        
        
                    //初始化分頁變量 
                    var iPageSize = 4;
                    var iCurrentPageIndex = 1;
                    var iRecordCount = 0;
                    var iPageCount = 0;
        
                    //加載數據函數
                    function loadData(pageSize, currentPageIndex) {
                        //alert("pageSize:" + pageSize + " , currentPageIndex:" + currentPageIndex);
                        var BBS = Ext.get("BBS");
                        BBS.dom.innerHTML = "數據加載中,請稍候";
                        BBS.dom.className = "red";
                        Ext.Ajax.request({
                            url: "../WCF/MyService.svc/GetData2",
                            params: { PageSize: pageSize, PageIndex: currentPageIndex },
                            method: "GET",
                            success: function(request) {
                                BBS.dom.className = "";
                                
                                //轉換服務器端返回字符串的格式
                                var data = request.responseText;
                                data = data.substr(1);
                                data = data.substr(0, data.length - 1);
                                data = data.replace(/\\\"/g, '"');                        
                                data = Ext.util.JSON.decode(data)
        
                                tpl.overwrite("BBS", data);
        
        
                                //其實下面這四句在本例中沒什么大的作用,不過可能以后改進時會用到,暫時先保留吧
                                iPageSize = data.PageSize;
                                iCurrentPageIndex = data.CurrentPageIndex;
                                iRecordCount = data.RecordCount;
                                iPageCount = data.PageCount;
        
                                //alert("pageSize:" + iPageSize + " , currentPageIndex:" + iCurrentPageIndex);
        
                                //開始處理分頁按鈕/鏈接事件
                                var oBtnGo = Ext.get("btnGo");
                                var oGoPage = Ext.get("GoPage");
                                oBtnGo.on("click", function() {
                                    loadData(iPageSize, oGoPage.dom.value);
                                });
        
                                var oBtnFirst = Ext.get("btnFirst"); //第一頁
                                oBtnFirst.on("click", function() { loadData(iPageSize, 1); })
        
        
                                var oBtnPre = Ext.get("btnPre"); //上一頁
                                oBtnPre.on("click", function() { loadData(iPageSize, iCurrentPageIndex - 1); })
        
                                var oBtnNext = Ext.get("btnNext"); //下一頁
                                oBtnNext.on("click", function() { loadData(iPageSize, iCurrentPageIndex + 1); })
        
                                var oBtnLast = Ext.get("btnLast"); //最后一頁
                                oBtnLast.on("click", function() { loadData(iPageSize, iPageCount); })
        
                            },
        
                            failure: function() {
                                BBS.dom.innerHTML = "數據加載失敗,請嘗試刷新!";
                            }
                        });
                    }
        
                    //載入數據
                    loadData(iPageSize, iCurrentPageIndex);
        
                });
            </script>
            <h1>ExtJs.XTemplate + WCF 打造無刷新數據分頁</h1>
            <div id="BBS">
                <!-- 模板參考部分
                <table>
                    <tr>
                        <td style="font-weight: bold; color: #666">
                            網友[127.0.0.1] 2007-9-1:00 說:
                        </td>
                    </tr>
                    <tr>
                        <td>
                            這是第一條留言
                        </td>
                    </tr>
                    <tr>
                        <td>
                            <hr style="height: 1px" />
                        </td>
                    </tr>
                </table>
                -->
            </div>    
            
        </body>
        </html>
        復制

        這里有幾個要點: (1).datetime在xtemplate中的格式化寫法:{F_Date:date("Y-m-d H:i:s")} (2).服務端返回字符格式的處理: 因為JavaScriptConvert.SerializeObject(_PageData)這里已經成功序列化了,但是wcf的服務在返回時,必須要有一種格式,要么xml,要么json,所以我們指定了wcf以json格式返回后,會對正常的結果再做一次序列化,最后的結果是使字符串前后都加上了雙引號,同時把原來正常的雙引號做了轉義處理,參考下面的:

        正常的Json字符串: {"RecordCount":6,"PageSize":3,"PageCount":2,"CurrentPageIndex":1,"Data":[{"F_ID":1,"F_IP":"192.23.37.41","F_Date":new Date(1221052494578),"F_Content":"這是第一條留言","F_Reply":""},{"F_ID":2,"F_IP":"192.168.0.1","F_Date":new Date(1221052494578),"F_Content":"這是第二條留言","F_Reply":""},{"F_ID":3,"F_IP":"192.168.0.2","F_Date":new Date(1221052494578),"F_Content":"這是第三條留言","F_Reply":""}]}

        服務器返回的Json字符串: "{\"RecordCount\":6,\"PageSize\":3,\"PageCount\":2,\"CurrentPageIndex\":1,\"Data\":[{\"F_ID\":1,\"F_IP\":\"192.23.37.41\",\"F_Date\":new Date(1221052494578),\"F_Content\":\"這是第一條留言\",\"F_Reply\":\"\"},{\"F_ID\":2,\"F_IP\":\"192.168.0.1\",\"F_Date\":new Date(1221052494578),\"F_Content\":\"這是第二條留言\",\"F_Reply\":\"\"},{\"F_ID\":3,\"F_IP\":\"192.168.0.2\",\"F_Date\":new Date(1221052494578),\"F_Content\":\"這是第三條留言\",\"F_Reply\":\"\"}]}"

        所以我們要處理一下,關鍵代碼: //轉換服務器端返回字符串的格式                         var data = request.responseText;                         data = data.substr(1);                         data = data.substr(0, data.length - 1);                         data = data.replace(/\\\"/g, '"');                                                data = Ext.util.JSON.decode(data)

        (3).為使分頁按鈕有效,我們需要在成功返回服務端數據后,為每個分頁鏈接以及按鈕加上onClick事件,即這一部分 //開始處理分頁按鈕/鏈接事件                         var oBtnGo = Ext.get("btnGo");                         var oGoPage = Ext.get("GoPage");                         oBtnGo.on("click", function() {                             loadData(iPageSize, oGoPage.dom.value);                         });

        var oBtnFirst = Ext.get("btnFirst"); //第一頁                         oBtnFirst.on("click", function() { loadData(iPageSize, 1); })

        var oBtnPre = Ext.get("btnPre"); //上一頁                         oBtnPre.on("click", function() { loadData(iPageSize, iCurrentPageIndex - 1); })

        var oBtnNext = Ext.get("btnNext"); //下一頁                         oBtnNext.on("click", function() { loadData(iPageSize, iCurrentPageIndex + 1); })

        var oBtnLast = Ext.get("btnLast"); //最后一頁                         oBtnLast.on("click", function() { loadData(iPageSize, iPageCount); })

        另外這一段代碼的位置,也要留意一下,不能寫在其它地方:比如Ajax請求之后,因為當Ajax還未成功返回數據/XTemplate未成功更新時,分頁按鈕以及鏈接還沒有加載到頁面中,這時如果用Ext.get()取對象,Js會報錯

        完成了,我們來看下一效果:

        最后講一點題外話:    做完這個后,我在想:單就這個示例而言,這跟直接用asp.net ajax的updatePannel有什么區別,有什么優勢呢?相信也有不少人跟我有一樣的疑問,后來我想了想,至少有二個好處:    a.updatepannel默認會引起大量的數據回發,雖然頁面沒刷新,但是客戶端跟服務端之間的傳輸數據量很大,而用ExtJs+Wcf,除了wcf返回的字符串,就沒其它東西了,性能上會提高    b.相對而言,ExtJs的Ajax請求方式,我覺得比aspx.net ajax的更容易操作.

        關聯標簽:
        日本漂亮人妻被强制

      3. <samp id="frm2q"><ins id="frm2q"></ins></samp>
          1. <samp id="frm2q"></samp>
            <progress id="frm2q"><bdo id="frm2q"><strong id="frm2q"></strong></bdo></progress>
            <menuitem id="frm2q"><ins id="frm2q"><u id="frm2q"></u></ins></menuitem>

            <progress id="frm2q"></progress>