Итак ... У меня была эта умная идея, что я создаю свой собственный элемент управления ретранслятора, который реализует пейджинг и сортировку, наследуя от Repeater и расширяя его возможности. Я нашел некоторую информацию и кусочки о том, как это сделать, и все казалось нормально ...Создание богатого репитера, DataBind, удаляющего настраиваемые добавленные элементы управления
Я создал WebControlLibrary для размещения своих пользовательских элементов управления. Наряду с обогащенным ретранслятором я создал составной элемент управления, который будет действовать как «панель пейджера», имея выбор вперед, назад и страницы. Моя панель пейджера работает на 100% самостоятельно, правильно запуская измененное событие, когда пользователь взаимодействует с ним. Богатые файлы репитера без проблем, но когда загорается databind (когда я вызываю 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();
}
}
}
Я бы сменил ваш метод поискового вызова, чтобы использовать querystrings, а не postbacks. Это лучше для usablity и SEO, как я описываю в этом ответе ... http://stackoverflow.com/questions/1228083/if-i-need-pagination-support-should-i-use-a-listview-or -a-repeatater/1228198 # 1228198 – 2011-12-05 21:06:47