Создавая Rich Repeater, DataBind уничтожает добавленные пользователем элементы управления - PullRequest
2 голосов
/ 02 декабря 2008

Итак ... У меня была эта умная идея, что я бы создал свой собственный элемент управления Repeater, который реализует разбиение на страницы и сортировку путем наследования от Repeater и расширения его возможностей. Я нашел некоторую информацию и кусочки о том, как это сделать, и все казалось нормальным ...

Я создал библиотеку 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();
        }
    }
}

1 Ответ

1 голос
/ 14 июля 2009

Вы также можете использовать новый элемент управления ASP.NET ListView (начиная с .Net 3.5) Он имеет подкачку / сортировку данных и шаблонов, что означает, что вы можете использовать его как ретранслятор или очень легко делать сложные вещи, такие как сетка, как дисплеи с встроенным редактированием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...