2010-08-31 109 views
1

我正在擴展asp:Repeater以使用DataPager,現在我的代碼可以與SqlDataSource一起使用。爲了獲得更好的性能,我想使用ObjectDataSource,但是我必須使用DataPager的QueryStringField,否則我必須兩次單擊頁碼以使其工作。任何人都可以幫忙嗎?這是我的代碼:擴展asp問題:Repeater with DataPager

namespace WebTest.UserControl 
{ 
    public class PageableRepeater : Repeater, IPageableItemContainer 
    { 
     private static readonly object EventTotalRowCountAvailable = new object(); 

     private int _startRowIndex = 0; 
     private int _maximumRows = -1; 
     private int _totalRowCount = -1; 

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

     protected override void LoadControlState(object savedState) 
     { 
      _startRowIndex = 0; 
      _maximumRows = -1; 
      _totalRowCount = -1; 
      object[] state = savedState as object[]; 

      if (state != null) 
      { 
       base.LoadControlState(state[0]); 

       if (state[1] != null) 
       { 
        _totalRowCount = (int)state[1]; 
       } 

      } 
      else 
      { 
       base.LoadControlState(null); 
      } 
      if (!IsViewStateEnabled) 
      { 
       OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount)); 
      } 
     } 

     protected override object SaveControlState() 
     { 
      object baseState = base.SaveControlState(); 
      if (baseState != null || _totalRowCount != -1) 
      { 
       object[] state = new object[2]; 
       state[0] = baseState; 
       state[1] = _totalRowCount; 
       return state; 
      } 
      return true; 
     } 

     protected override System.Collections.IEnumerable GetData() 
     { 
      ListViewPagedDataSource pagedDataSource = new ListViewPagedDataSource(); 
      pagedDataSource.StartRowIndex = _startRowIndex; 
      pagedDataSource.MaximumRows = _maximumRows; 
      if (DataSource is ObjectDataSource) 
      { 
       SelectArguments.StartRowIndex = _startRowIndex; 
       SelectArguments.MaximumRows = _maximumRows; 
       SelectArguments.RetrieveTotalRowCount = true; 

       pagedDataSource.DataSource = base.GetData(); 
       _totalRowCount = SelectArguments.TotalRowCount; 
       pagedDataSource.AllowServerPaging = true; 
       pagedDataSource.TotalRowCount = _totalRowCount; 
      } 
      else 
      { 
       pagedDataSource.DataSource = base.GetData(); 
       pagedDataSource.AllowServerPaging = false; 
       pagedDataSource.TotalRowCount = 0; 
       _totalRowCount = pagedDataSource.DataSourceCount; 
      } 
      return pagedDataSource; 
     } 

     protected override void CreateControlHierarchy(bool useDataSource) 
     { 
      base.CreateControlHierarchy(useDataSource); 
      OnTotalRowCountAvailable(new PageEventArgs(_startRowIndex, _maximumRows, _totalRowCount)); 
     } 

     private void OnTotalRowCountAvailable(PageEventArgs pageEventArgs) 
     { 
      EventHandler<PageEventArgs> handler = (EventHandler<PageEventArgs>)Events[EventTotalRowCountAvailable]; 
      if (handler != null) 
      { 
       handler(this, pageEventArgs); 
      } 
     } 

     public int MaximumRows 
     { 
      get { return _maximumRows; } 
     } 

     public int StartRowIndex 
     { 
      get { return _startRowIndex; } 
     } 

     public void SetPageProperties(int startRowIndex, int maximumRows, bool databind) 
     { 
      if (maximumRows < 1) 
      { 
       throw new ArgumentOutOfRangeException("maximumRows"); 
      } 
      if (startRowIndex < 0) 
      { 
       throw new ArgumentOutOfRangeException("startRowIndex"); 
      } 

      _startRowIndex = startRowIndex; 
      _maximumRows = maximumRows; 

      if (databind) 
      { 
       RequiresDataBinding = true; 
      } 
     } 

     public event EventHandler<PageEventArgs> TotalRowCountAvailable 
     { 
      add 
      { 
       Events.AddHandler(EventTotalRowCountAvailable, value); 
      } 
      remove 
      { 
       Events.RemoveHandler(EventTotalRowCountAvailable, value); 
      } 
     } 
    } 
} 

順便說一句,我發現CodeProject另一個實現這一點,但我不認爲它使用IPageableItemContainer非常好。

+0

哇你是對的..那真的是錯的。我正在尋找同樣的東西 - 你找到了解決方案嗎? – 2011-05-24 12:40:00

回答

0

我知道這是一箇舊的,但我最近一直在尋找解決方案來使用Repeater與DataPager控件。

大部分的研究都把我帶到這個CodeProject article,但它對我來說似乎有些破綻。我已經解決了這個問題,並且把它放在了一邊,因爲我正在旋轉車輪,直到看到你的問題和示例代碼。我能夠把你的代碼應用到我的工作解決方案(至少它適用於我)。通過下面的DataPagerRepeater控件,我可以在頁面上刪除DataPagerRepeater,DataPager和一個DataSource(ObjectDataSource等)。將DataPagerRepeaters DataSource或DataSourceID設置爲指向數據源,然後將DataPagers PagedControlID設置爲DataPagerRepeater。似乎很好。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Web.UI; 
using System.Web.UI.WebControls; 

namespace My.Web.UI.WebControls 
{ 
    /// <summary> 
    /// Extends the Repeater to be compatable with a DataPager 
    /// </summary> 
    /// <remarks> 
    /// To page through data in a control that implements the IPageableItemContainer interface, DataPager control can be used. 
    /// Repeater does not support paging and does not implement IPageableItemContainer interface. ListView is the only control that works with DataPager. 
    /// 
    /// The DataPager control supports built-in paging user interface (UI). NumericPagerField object enables users to select a page of data by page number. 
    /// NextPreviousPagerField object enables users to move through pages of data one page at a time, or to jump to the first or last page of data. 
    /// The size of the pages of data is set by using the PageSize property of the DataPager control. One or more pager field objects can be used in 
    /// a single DataPager control. Custom paging UI can be created by using the TemplatePagerField object. In the TemplatePagerField template, 
    /// the DataPager control is referenced by using the Container property which provides access to the properties of the DataPager control. 
    /// These properties include the starting row index, the page size, and the total number of rows currently bound to the control. 
    /// </remarks> 
    [ToolboxData("<my:DataPagerRepeater runat=server></my:DataPagerRepeater>")] 
    [Themeable(true)] 
    public class DataPagerRepeater : Repeater, IPageableItemContainer 
    { 
     /// <summary>Gets the maximum number of items to display on a single page of the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control. 
     /// </summary> 
     /// <returns>The maximum number of items to display on a single page of the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control. 
     /// </returns> 
     public int MaximumRows 
     { 
      get; 
      //{ 
      // return ViewState["maxrows"] != null ? (int)ViewState["maxrows"] : -1; 
      //} 
      private set; 
      //{ 
      // ViewState["maxrows"] = value; 
      //} 
     } 

     /// <summary>Gets the index of the first record that is displayed on a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control. 
     /// </summary> 
     /// <returns>The index of the first record that is displayed on a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control. 
     /// </returns> 
     public int StartRowIndex 
     { 
      get; 
      //{ 
      // return ViewState["startrowindex"] != null ? (int)ViewState["startrowindex"] : -1; 
      //} 
      private set; 
      //{ 
      // ViewState["startrowindex"] = value; 
      //} 
     } 

     /// <summary> 
     /// Total number of rows that are avialable, regardless of what is currently being displayed 
     /// </summary> 
     private int TotalRowsAvailable 
     { 
      get; 
      //{ 
      // return ViewState["totalrows"] != null ? (int)ViewState["totalrows"] : -1; 
      //} 
      set; 
      //{ 
      // ViewState["totalrows"] = value; 
      //} 
     } 

     private static readonly object EventPagePropertiesChanged = new object(); 
     /// <summary>Occurs when the page properties change, after the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control sets the new values. 
     /// </summary> 
     public event EventHandler PagePropertiesChanged 
     { 
      add 
      { 
       base.Events.AddHandler(DataPagerRepeater.EventPagePropertiesChanged, value); 
      } 
      remove 
      { 
       base.Events.RemoveHandler(DataPagerRepeater.EventPagePropertiesChanged, value); 
      } 
     } 

     private static readonly object EventPagePropertiesChanging = new object(); 
     /// <summary>Occurs when the page properties change, but before the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control sets the new values. 
     /// </summary> 
     public event EventHandler<PagePropertiesChangingEventArgs> PagePropertiesChanging 
     { 
      add 
      { 
       base.Events.AddHandler(DataPagerRepeater.EventPagePropertiesChanging, value); 
      } 
      remove 
      { 
       base.Events.RemoveHandler(DataPagerRepeater.EventPagePropertiesChanging, value); 
      } 
     } 

     private static readonly object EventTotalRowCountAvailable = new object(); 
     /// <summary>For a description of this member, see <see cref="E:System.Web.UI.WebControls.IPageableItemContainer.TotalRowCountAvailable" />. 
     /// </summary> 
     public event EventHandler<PageEventArgs> TotalRowCountAvailable 
     { 
      add 
      { 
       base.Events.AddHandler(DataPagerRepeater.EventTotalRowCountAvailable, value); 
      } 
      remove 
      { 
       base.Events.RemoveHandler(DataPagerRepeater.EventTotalRowCountAvailable, value); 
      } 
     } 

     /// <summary> 
     /// Register the control as one who's control state needs to be persisted 
     /// </summary> 
     /// <param name="e"></param> 
     protected override void OnInit(EventArgs e) 
     { 
      base.OnInit(e); 
      Page.RegisterRequiresControlState(this); 
     } 

     /// <summary> 
     /// Initialize the start row index, maximum rows, and total rows available values. Load the total rows available from viewstate. 
     /// </summary> 
     /// <param name="savedState"></param> 
     protected override void LoadControlState(object savedState) 
     { 
      this.StartRowIndex = 0; 
      this.MaximumRows = -1; 
      this.TotalRowsAvailable = -1; 
      object[] state = savedState as object[]; 

      if (state != null) 
      { 
       base.LoadControlState(state[0]); 

       if (state[1] != null) 
       { 
        this.TotalRowsAvailable = (int)state[1]; 
       } 

      } 
      else 
      { 
       base.LoadControlState(null); 
      } 

      if (!IsViewStateEnabled) 
      { 
       OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable)); 
      } 
     } 

     /// <summary> 
     /// Save the total rows available value to viewstate 
     /// </summary> 
     /// <returns></returns> 
     protected override object SaveControlState() 
     { 
      object baseState = base.SaveControlState(); 
      if (baseState != null || this.TotalRowsAvailable != -1) 
      { 
       object[] state = new object[2]; 
       state[0] = baseState; 
       state[1] = this.TotalRowsAvailable; 
       return state; 
      } 
      return true; 
     } 


     /// <summary>Sets the properties of a page of data in the <see cref="T:InteriorHealth.Web.UI.WebControls.DataPagerRepeater" /> control. 
     /// </summary> 
     /// <param name="startRowIndex">The index of the first record on the page.</param> 
     /// <param name="maximumRows">The maximum number of items on a single page.</param> 
     /// <param name="databind">true to rebind the control after the properties are set; otherwise, false.</param> 
     /// <exception cref="T:System.ArgumentOutOfRangeException"> 
     /// <paramref name="maximumRows" /> is less than 1.-or-<paramref name="startRowIndex" /> is less than 0. 
     /// </exception> 
     public void SetPageProperties(int startRowIndex, int maximumRows, bool databind) 
     { 
      if (maximumRows < 1) 
      { 
       throw new ArgumentOutOfRangeException("maximumRows"); 
      } 
      if (startRowIndex < 0) 
      { 
       throw new ArgumentOutOfRangeException("startRowIndex"); 
      } 
      if (this.StartRowIndex != startRowIndex || this.StartRowIndex != maximumRows) 
      { 
       PagePropertiesChangingEventArgs pagePropertiesChangingEventArgs = new PagePropertiesChangingEventArgs(startRowIndex, maximumRows); 
       if (databind) 
       { 
        this.OnPagePropertiesChanging(pagePropertiesChangingEventArgs); 
       } 

       this.StartRowIndex = pagePropertiesChangingEventArgs.StartRowIndex; 
       this.MaximumRows = pagePropertiesChangingEventArgs.MaximumRows; 

       if (databind) 
       { 
        this.OnPagePropertiesChanged(EventArgs.Empty); 
       } 
      } 
      if (databind) 
      { 
       this.RequiresDataBinding = true; 
      } 

      //this.OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable)); 
     } 


     /// <summary> 
     /// Creates a control hierarchy, with or without the specified data source. 
     /// </summary> 
     /// <param name="useDataSource"> 
     /// Indicates whether to use the specified data source. 
     /// </param> 
     protected override void CreateControlHierarchy(bool useDataSource) 
     { 
      base.CreateControlHierarchy(useDataSource); 
      OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable)); 
     } 

     /// <summary>Returns an <see cref="T:System.Collections.IEnumerable" /> interface from the data source.</summary> 
     /// <returns>An object implementing <see cref="T:System.Collections.IEnumerable" /> that represents the data from the data source.</returns> 
     protected override System.Collections.IEnumerable GetData() 
     { 
      System.Collections.IEnumerable data = base.GetData(); 
      this.TotalRowsAvailable = this.SelectArguments.TotalRowCount; 

      this.OnTotalRowCountAvailable(new PageEventArgs(this.StartRowIndex, this.MaximumRows, this.TotalRowsAvailable)); 
      return data; 
     } 

     /// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.PagePropertiesChanging" /> event. 
     /// </summary> 
     /// <param name="e">The event data.</param> 
     protected virtual void OnPagePropertiesChanging(PagePropertiesChangingEventArgs e) 
     { 
      EventHandler<PagePropertiesChangingEventArgs> eventHandler = (EventHandler<PagePropertiesChangingEventArgs>)base.Events[DataPagerRepeater.EventPagePropertiesChanging]; 
      if (eventHandler != null) 
      { 
       eventHandler(this, e); 
      } 
     } 

     /// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.SelectedIndexChanged" /> event.</summary> 
     /// <param name="e">The event data.</param> 
     protected virtual void OnPagePropertiesChanged(EventArgs e) 
     { 
      EventHandler eventHandler = (EventHandler)base.Events[DataPagerRepeater.EventPagePropertiesChanged]; 
      if (eventHandler != null) 
      { 
       eventHandler(this, e); 
      } 
     } 

     /// <summary>Raises the <see cref="E:InteriorHealth.Web.UI.WebControls.DataPagerRepeater.PagePropertiesChanging" /> event.</summary> 
     /// <param name="e">The event data.</param> 
     protected virtual void OnTotalRowCountAvailable(PageEventArgs e) 
     { 
      EventHandler<PageEventArgs> eventHandler = (EventHandler<PageEventArgs>)base.Events[DataPagerRepeater.EventTotalRowCountAvailable]; 
      if (eventHandler != null) 
      { 
       eventHandler(this, e); 
      } 
     } 


     /// <summary> 
     /// Override the selection of rows that we need 
     /// </summary> 
     /// <returns></returns> 
     protected override DataSourceSelectArguments CreateDataSourceSelectArguments() 
     { 
      DataSourceSelectArguments arg = base.CreateDataSourceSelectArguments(); 
      arg.StartRowIndex = this.StartRowIndex; 
      arg.MaximumRows = this.MaximumRows; 

      return arg; 
     } 
    } 
}