ASP.NET中使用ListView多層綁定的分頁問題始末

來源:互聯網
上載者:User

  前段時間著手做一個網站,在使用ListView和DataPager時遇到了一個新問題。先描述一下頁面的要求吧:有兩級類別,一個大類,下面有子類,子類下才對應了產品,然後在一個頁面中把大類(指定了哪些)、子類、產品按結構顯示出來,其中產品要有分頁。好了,目前來說,整個頁面互動性只在於產品的分頁上,大類、子類在伺服器端只是顯示的作用,故我理所當然地想到了使用ListView來層層綁定,並在產品層添加DataPager控制項來分頁。

  背景資料DTO也已經定義好,分別有大類、小類、產品:

 1     // 產品大類DTO 2     public class ProductTypeDTO 3     { 4         public int ID { get; set; } 5         // ... 6         public IEnumerable<CategoryDTO> Categorys { get; set; } 7     } 8  9     // 產品小類DTO10     public class CategoryDTO11     {12         // ...13         public IEnumerable<ProductDTO> Products { get; set; }14     }15 16     // 產品DTO17     public class ProductDTO18     {19         public int ID { get; set; }20         // ...21     }

  以慣性思維,先把大類資料來源傳給第一層ListView,再在一層內寫小類ListView,最後再在小類ListView中寫產品與DataPager。目前假設已經處理完成的資料來源為IList<ProductTypeDTO> ProductTypeList,它就是我們要顯示的東西了。

  最初設計的前台代碼為:

 1              <!-- Begin Types --> 2              <asp:ListView ID="LV_Products" runat="server"> 3                  <ItemTemplate> 4                      // 這裡是大類需要解析的HTML控制項            5                      <!-- Begin Categorys--> 6                      <asp:ListView DataSource='<%# DataBinder.Eval(Container.DataItem,"Categorys") %>' runat="server"> 7                          <ItemTemplate> 8                                      // 這裡是小類需要解析的HTML控制項                                               9                                      <!-- Begin Products -->10                                      <asp:ListView ID="LV_Item" DataSource='<%# DataBinder.Eval(Container.DataItem,"Products") %>' runat="server">11                                          <ItemTemplate>12                                              // 這是具體產品需要解析的HTML控制項                                            13                                          </ItemTemplate>14                                      </asp:ListView>15                                      <!-- End Products-->16                                      <div class="cleardiv"></div>17                                      <!-- Begin DataPager-->18                                      <div class="product_dp">19                                          <asp:DataPager ID="DP_Item" PageSize="10" PagedControlID="LV_Item" runat="server">20                                              <Fields>21                                                  // 這是分頁按鈕22                                              </Fields>23                                          </asp:DataPager>24                                      </div>25                                      <!-- End DataPager-->                                26                              <div class="cleardiv"></div>27                              <br />28                          </ItemTemplate>29                      </asp:ListView>30                      <!-- End Categorys-->31                      <div class="cleardiv"></div>32                      <br />33                  </ItemTemplate>34              </asp:ListView>35              <!-- End Types -->

  以上省略了與問題無關的一些繫結項目代碼,根據以往的經驗,要想不出現點擊兩次才翻頁的情況,可以把資料繫結語句:

  LV_Products.DataSource = ProductTypeList;
  LV_Products.DataBind();

  寫在Page_PreRender中,在IIS中調試一看,唔,資料正常顯示,分頁已經分好,但是我一點其它頁的,完全沒作用,頁面閃了一下,頁面的元素還是第一頁那些。經過排查,我覺得是資料繫結的問題(在PreRender中進行綁定,會導致每次都進行了一次資料更新,而我的LV_Item是動態產生的,DataPager也是動態,這會導致產生一個全新的頁面,而不會根據以前的PageIndex產生翻頁),於是把後台綁定的代碼改成寫在!IsPost中,看了下,能分頁、能顯示,點擊分頁,好像是發生了跳轉,可惜那些資料不能正常地綁定進來,而且需要點擊2次才能正常跳轉。

  思來想去,還是對ASP.NET的頁面載入不瞭解,於是仔細看了它的初始化流程,覺得與Page_PreRender相似的,我使用ListView.PreRender事件應該也可以達到相同效果,那麼需要取消LV_Item的綁定,而在後台手動來綁定其資料來源(LV_Products的綁定放在!IsPostBack內)。當頁面第一次載入時就綁定所有LV_Item的資料,當分頁回傳時,只重新綁定對應的LV_Item的資料來源。LV_Item的前台代碼改為:

<asp:ListView ID="LV_Item" OnPagePropertiesChanged="LV_PageChanged" runat="server">    // ...</asp:ListView>

  看到了沒,就是通過ListView的分頁改變事件來觸發資料來源綁定的,綁定需要發生在它的PreRender事件中:

protected void LV_PageChanged(object sender, EventArgs e){    (sender as ListView).PreRender += LV_OnPreRender;}

  這下明白了吧,第一次載入頁面,所有的ListView都會自動觸發OnPagePropertiesChanged事件,於是所有的ListView都會載入PreRender事件處理函數進行資料繫結,而當點擊分頁回傳裡,只有一個ListView會觸發OnPagePropertiesChanged事件,也就只有一個ListView會載入PreRender事件處理函數,所以繫結來源的重新綁定將只發生一個LV_Item身上。

  好了,LV_OnPreRender作為LV_Item的重新綁定函數,需要有具體的大類、小類的資訊才能把產品列表綁定給ListView,目前我只有一個ProductTypeList把大類、小類、產品的關係給封裝好了,而LV_OnPreRender、LV_PageChanged都不能得到目前這個ListView是哪個大類下的哪個小類的列表資訊,怎麼辦?

  只好另闢蹊徑了,來看個LV_Item產生的用戶端代碼:

  發現了什麼,這個是有命名規則的!CPH_main是我用的母片名,LV_Products是我的大類ListView,然後ctl100,它是我的小類ListView(沒給它命名,自動產生的),然後後面的0,就是第0個大類!再又接了個ctl100是我用的ajax UpdataPanel(本文中沒有,這是實際項目中用的),後面的0、1、2、3...就是實際的小類了!唔,經過測試,這是完全沒有問題的,只要你沒有改ClientIDMode。在後台代碼中,我們可以通過ListView.UniqueID來擷取與這類似的值,只是有一點區別。於是我們最後一個要點LV_OnPreRender的函數為:

 1     private static Regex _productRegex = new Regex(@"(?<=ctrl)\d+", RegexOptions.Singleline); 2     // 綁定資料來源 3     protected void LV_OnPreRender(object sender, EventArgs e) 4     {         5         var lv = sender as ListView; 6         // 確認資料來源 7         /* 根據具體情況來,我的UnitqueID是這樣的: 8          * 全域標識 ctl00$CPH_main$LV_Products$ctrl0$ctl00$ctrl0$LV_Item 9          *                                     大類        小類                       10         */11         var matche = _productRegex.Match(lv.UniqueID, 25);12         // 重新綁定資料13         try14         {15             int categoryID = Int32.Parse(matche.NextMatch().Value);16             int typeID = Int32.Parse(matche.Value);17             lv.DataSource = BaseConfig.ProductTypeList[typeID].Categorys.ElementAt(categoryID).Products;18             lv.DataBind();19         }20         catch21         {22             // 錯誤處理23         }24     }

  至此,分頁完成,效率不錯,在IIS上測試起來非常快,百來條一下的事。想看最終的,可以點我開啟圖片連結。

 

  轉載請註明原址:http://www.cnblogs.com/lekko/archive/2013/04/27/3046481.html

 

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.