我正在扩展asp:Repeater以使用DataPager,现在我的代码可以使用SqlDataSource。为了获得更好的性能,我想使用ObjectDataSource,但是我必须使用DataPager的QueryStringField,否则我必须单击两次页码才能使它工作。任何人都可以帮忙吗?这是我的代码:
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 :(得分:0)
我知道这是一个旧的,但我最近一直在寻找使用带有DataPager控件的Repeater的解决方案。
大多数研究都把我带到了这个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;
}
}
}