2008-12-02 26 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