简体   繁体   English

创建富中继器,DataBind清除自定义添加的控件

[英]Creating a Rich Repeater, DataBind wiping out custom added controls

So...I had this clever idea that I'd create my own Repeater control that implements paging and sorting by inheriting from Repeater and extending it's capabilities. 所以...我有一个聪明的主意,我将创建自己的Repeater控件,该控件通过继承Repeater并扩展其功能来实现分页和排序。 I found some information and bits and pieces on how to go about this and everything seemed ok... 我找到了一些有关如何进行此操作的信息和点点滴滴,一切似乎都很好。

I created a WebControlLibrary to house my custom controls. 我创建了一个WebControlLibrary来容纳我的自定义控件。 Along with the enriched repeater, I created a composite control that would act as the "pager bar", having forward, back and page selection. 与丰富的转发器一起,我创建了一个复合控件,该控件将充当“寻呼机栏”,具有前进,后退和页面选择功能。 My pager bar works 100% on it's own, properly firing a paged changed event when the user interacts with it. 我的传呼工具栏本身可以100%工作,当用户与其互动时,它会正确触发一个页面更改事件。 The rich repeater databinds without issue, but when the databind fires (when I call base.databind()), the control collection is cleared out and my pager bars are removed. 丰富的转发器数据绑定没有问题,但是当databind触发时(当我调用base.databind()时),控件集合被清除并且我的寻呼机栏被删除。 This screws up the viewstate for the pager bars making them unable to fire their events properly or maintain their state. 这会弄乱寻呼机栏的视图状态,使它们无法正确触发事件或保持其状态。

I've tried adding the controls back to the collection after base.databind() fires, but that doesn't solve the issue. 我尝试在base.databind()触发后将控件添加回集合中,但这不能解决问题。 I start to get very strange results including problems with altering the hierarchy of the control tree (resolved by adding [ViewStateModeById]). 我开始得到非常奇怪的结果,包括更改控制树的层次结构的问题(通过添加[ViewStateModeById]解决)。

Before I go back to the drawing board and create a second composite control which contains a repeater and the pager bars (so that the repeater isn't responsible for the pager bars viewstate) are there any thoughts about how to resolve the issue? 回到绘图板并创建第二个复合控件,其中包含转发器和寻呼机栏(以便转发器不负责寻呼机视图状态)之前,是否有关于如何解决此问题的想法?

In the interest of share and share alike, the code for the repeater itself is below, the pagerbars aren't as significant as the issue is really the maintaining of state for any additional child controls. 出于共享的目的,转发器本身的代码在下面,分页器并不重要,因为问题实际上是维护任何其他子控件的状态。 (forgive the roughness of some of the code...it's still a work in progress) (原谅某些代码的粗糙性,它仍在进行中)

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();
        }
    }
}

您还可以使用新的ASP.NET ListView控件 (自.Net 3.5起),它具有分页/排序数据绑定和模板,这意味着您可以将其用作转发器,也可以非常轻松地完成诸如网格之类的复杂工作,例如带有内联编辑的显示。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM