2008-12-02 25 views
2

所以...我有一個聰明的想法,我會創建自己的Repeater控件,通過繼承Repeater並擴展它的功能來實現分頁和排序。我發現一些信息和關於如何去做這件事的一些東西,一切似乎都沒問題......創建一個豐富的轉發器,DataBind擦除自定義添加的控件

我創建了一個WebControlLibrary來容納我的自定義控件。隨着豐富的中繼器,我創建了一個複合控件,作爲「傳呼機欄」,有前進,後退和頁面選擇。我的分頁欄自己可以100%工作,在用戶與它交互時正確觸發分頁的已更改事件。豐富的中繼器數據綁定沒有問題,但是當數據綁定觸發時(當我調用base.databind())時,控件集合被清除,我的傳呼條被刪除。這使得瀏覽器欄的視圖狀態變得不可用,從而無法正確激活它們的事件或保持它們的狀態。

我試過在base.databind()觸發後將控件添加回集合,但這並不能解決問題。我開始得到非常奇怪的結果,包括改變控制樹層次結構的問題(通過添加[ViewStateModeById]解決)。

在我回到繪圖板並創建第二個包含中繼器和分頁欄的複合控件(以便中繼器不負責分頁欄視圖狀態)之前,有沒有關於如何解析問題?

爲了共享和共享的利益,中繼器本身的代碼在下面,頁面滾動並不像問題實際上是維護任何其他子控件的狀態一樣重要。 (原諒的一些代碼的粗糙度......它仍然在進展中的工作)

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Text; 
using System.Data; 
using System.Web; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

[ViewStateModeById] 
public class SortablePagedRepeater : Repeater, INamingContainer { 

    private SuperRepeaterPagerBar topBar = new SuperRepeaterPagerBar(); 
    private SuperRepeaterPagerBar btmBar = new SuperRepeaterPagerBar(); 

    protected override void OnInit(EventArgs e) { 
     Page.RegisterRequiresControlState(this); 

     InitializeControls(); 
     base.OnInit(e); 
     EnsureChildControls(); 
    } 

    protected void InitializeControls() { 
     topBar.ID = this.ID + "__topPagerBar"; 
     topBar.NumberOfPages = this._currentProperties.numOfPages; 
     topBar.CurrentPage = this.CurrentPageNumber; 
     topBar.PageChanged += 
      new SuperRepeaterPagerBar.PageChangedEventHandler(PageChanged); 

     btmBar.ID = this.ID + "__btmPagerBar"; 
     btmBar.NumberOfPages = this._currentProperties.numOfPages; 
     btmBar.CurrentPage = this.CurrentPageNumber; 
     btmBar.PageChanged += 
      new SuperRepeaterPagerBar.PageChangedEventHandler(PageChanged); 
    } 

    protected override void CreateChildControls() { 
     EnsureDataBound(); 

     this.Controls.Add(topBar); 
     this.Controls.Add(btmBar); 
     //base.CreateChildControls(); 
    } 

    private void PageChanged(object sender, int newPage) { 
     this.CurrentPageNumber = newPage; 
    } 

    public override void DataBind() { 
     //pageDataSource(); 

     //DataBind removes all controls from control collection... 
     base.DataBind(); 
     Controls.Add(topBar); 
     Controls.Add(btmBar); 
    } 

    private void pageDataSource() { 
     //Create paged data source 
     PagedDataSource pds = new PagedDataSource(); 

     pds.PageSize = this.ItemsPerPage; 
     pds.AllowPaging = true; 

     // first get a PagedDataSource going and perform sort if possible... 
     if (base.DataSource is System.Collections.IEnumerable) { 
      pds.DataSource = (System.Collections.IEnumerable)base.DataSource; 
     } else if (base.DataSource is System.Data.DataView) { 
      DataView data = (DataView)DataSource; 
      if (this.SortBy != null && data.Table.Columns.Contains(this.SortBy)) { 
       data.Sort = this.SortBy; 
      } 
      pds.DataSource = data.Table.Rows; 
     } else if (base.DataSource is System.Data.DataTable) { 
      DataTable data = (DataTable)DataSource; 
      if (this.SortBy != null && data.Columns.Contains(this.SortBy)) { 
       data.DefaultView.Sort = this.SortBy; 
      } 
      pds.DataSource = data.DefaultView; 
     } else if (base.DataSource is System.Data.DataSet) { 
      DataSet data = (DataSet)DataSource; 
      if (base.DataMember != null && data.Tables.Contains(base.DataMember)) { 
       if (this.SortBy != null && data.Tables[base.DataMember].Columns.Contains(this.SortBy)) { 
        data.Tables[base.DataMember].DefaultView.Sort = this.SortBy; 
       } 
       pds.DataSource = data.Tables[base.DataMember].DefaultView; 
      } else if (data.Tables.Count > 0) { 
       if (this.SortBy != null && data.Tables[0].Columns.Contains(this.SortBy)) { 
        data.Tables[0].DefaultView.Sort = this.SortBy; 
       } 
       pds.DataSource = data.Tables[0].DefaultView; 
      } else { 
       throw new Exception("DataSet doesn't have any tables."); 
      } 
     } else if (base.DataSource == null) { 
      // don't do anything? 
     } else { 
      throw new Exception("DataSource must be of type System.Collections.IEnumerable. The DataSource you provided is of type " + base.DataSource.GetType().ToString()); 
     } 


     if (pds != null && base.DataSource != null) { 
      //Make sure that the page doesn't exceed the maximum number of pages 
      //available 
      if (this.CurrentPageNumber >= pds.PageCount) { 
       this.CurrentPageNumber = pds.PageCount - 1; 
      } 

      //Set up paging values... 
      btmBar.CurrentPage = topBar.CurrentPage = pds.CurrentPageIndex = this.CurrentPageNumber; 
      this._currentProperties.numOfPages = btmBar.NumberOfPages = topBar.NumberOfPages = pds.PageCount; 

      base.DataSource = pds; 
     } 
    } 

    public override object DataSource { 
     get { 
      return base.DataSource; 
     } 
     set { 
      //init(); //reset paging/sorting values since we've potentially changed data sources. 
      base.DataSource = value; 
      pageDataSource(); 
     } 
    } 

    protected override void Render(HtmlTextWriter writer) { 
     topBar.RenderControl(writer); 
     base.Render(writer); 
     btmBar.RenderControl(writer); 
    } 

    [Serializable] 
    protected struct CurrentProperties { 
     public int pageNum; 
     public int itemsPerPage; 
     public int numOfPages; 
     public string sortBy; 
     public bool sortDir; 
    } 

    protected CurrentProperties _currentProperties = new CurrentProperties(); 

    protected override object SaveControlState() { 
     return this._currentProperties; 
    } 

    protected override void LoadControlState(object savedState) { 
     this._currentProperties = (CurrentProperties)savedState; 
    } 

    [Category("Status")] 
    [Browsable(true)] 
    [NotifyParentProperty(true)] 
    [DefaultValue("")] 
    [Localizable(false)] 
    public string SortBy { 
     get { return this._currentProperties.sortBy; } 
     set { 
      //If sorting by the same column, swap the sort direction. 
      if (this._currentProperties.sortBy == value) { 
       this.SortAscending = !this.SortAscending; 
      } else { 
       this.SortAscending = true; 
      } 
      this._currentProperties.sortBy = value; 
     } 
    } 

    [Category("Status")] 
    [Browsable(true)] 
    [NotifyParentProperty(true)] 
    [DefaultValue(true)] 
    [Localizable(false)] 
    public bool SortAscending { 
     get { return this._currentProperties.sortDir; } 
     set { this._currentProperties.sortDir = value; } 
    } 

    [Category("Status")] 
    [Browsable(true)] 
    [NotifyParentProperty(true)] 
    [DefaultValue(25)] 
    [Localizable(false)] 
    public int ItemsPerPage { 
     get { return this._currentProperties.itemsPerPage; } 
     set { this._currentProperties.itemsPerPage = value; } 
    } 

    [Category("Status")] 
    [Browsable(true)] 
    [NotifyParentProperty(true)] 
    [DefaultValue(1)] 
    [Localizable(false)] 
    public int CurrentPageNumber { 
     get { return this._currentProperties.pageNum; } 
     set { 
      this._currentProperties.pageNum = value; 
      pageDataSource(); 
     } 
    } 
} 
+0

我會改變你的分頁方法來利用querystrings而不是回發。這對於用例和搜索引擎優化來說都更好,正如我在這個答案中所描述的那樣... http://stackoverflow.com/questions/1228083/if-i-need-pagination-support-should-i-use-a-listview-or -a-repeater/1228198#1228198 – 2011-12-05 21:06:47

回答

1

你也可以使用新的ASP.NET ListView control(因爲NET 3.5的) 它具有分頁/整理數據綁定和模板,這意味着您可以將其用作中繼器 或者非常容易地執行復雜的內容,如帶內聯編輯的網格狀顯示。

+0

通過DataPager可以輕鬆地將分頁添加到ListView控件。但是,DataPager利用回傳是一種醜陋的方式來處理分頁。 – 2011-12-05 20:33:45