创建 Rich Repeater,DataBind 清除自定义添加的控件

发布于 2024-07-09 20:15:10 字数 7683 浏览 11 评论 0原文

所以...我有一个聪明的想法,我创建自己的 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();
        }
    }
}

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. 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. 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. 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. 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. I start to get very strange results including problems with altering the hierarchy of the control tree (resolved by adding [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();
        }
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

楠木可依 2024-07-16 20:15:10

您还可以使用新的 ASP.NET ListView 控件(自 .净3.5)
它具有分页/排序数据绑定和模板,这意味着您可以将其用作中继器
或者很容易地做复杂的事情,比如通过内联编辑显示网格。

You could also use the new ASP.NET ListView control (since .Net 3.5)
It has paging/sorting databinding and templating, which means you can use it as a repeater
or very easily do complex stuff like grid like displays with inline editing.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文