自定义GridView Server Control DataBind导致重复的控件ID错误

时间:2013-03-19 18:30:33

标签: asp.net c#-4.0 custom-server-controls

行。我早就用这个网站作为参考,但我现在已经碰到了自己的墙。

我正在创建一个继承自System.Web.UI.WebControls.GridView类的自定义服务器控件。它的目的只是显示具有非常定义格式的网格。它绑定并加载数据很好,但是尝试激活任何分页会抛出一个异常,说“找到了具有相同ID的多个控件'lblHdrText_2'。FindControl要求控件具有唯一的ID。”。

我可以将事件抛给用户并让他们进行分页,但其中一个目标是让这个控件能够处理自己的分页,就像GridView控件已经做的那样。

我在排序和更改页面大小方面遇到了同样的问题。基本上任何时候我都可以在控件中调用“DataBind”后再调用它。

以下是处理这些事件的代码:

    protected void OnFirstPageClicked(EventArgs e)
    {
        if (this.FirstPageClicked != null)
            this.FirstPageClicked.Invoke(this, e);

        GridViewPageEventArgs pgea = new GridViewPageEventArgs(0);
        this.OnPageIndexChanging(pgea);
        if (pgea.Cancel)
            return;

        this.PageIndex = 0;
        this.RefreshData();

        this.OnPageIndexChanged(e);
    }
    protected void OnLastPageClicked(EventArgs e)
    {
        if (this.LastPageClicked != null)
            this.LastPageClicked.Invoke(this, e);

        GridViewPageEventArgs pgea = new GridViewPageEventArgs(this.PageCount - 1);
        this.OnPageIndexChanging(pgea);
        if (pgea.Cancel)
            return;

        this.PageIndex = this.PageCount - 1;
        this.RefreshData();

        this.OnPageIndexChanged(e);
    }
    protected void OnPreviousPageClicked(EventArgs e)
    {
        if (this.PageIndex > 0)
        {
            if (this.PreviousPageClicked != null)
                this.PreviousPageClicked.Invoke(this, e);

            GridViewPageEventArgs pgea = new GridViewPageEventArgs(this.PageIndex++);
            this.OnPageIndexChanging(pgea);
            if (pgea.Cancel)
                return;

            this.PageIndex--;
            this.RefreshData();

            this.OnPageIndexChanged(e);
        }
    }
    protected void OnNextPageClicked(EventArgs e)
    {
        if (this.PageIndex < this.PageCount - 1)
        {

            if (this.NextPageClicked != null)
                this.NextPageClicked.Invoke(this, e);

            GridViewPageEventArgs pgea = new GridViewPageEventArgs(this.PageIndex++);
            this.OnPageIndexChanging(pgea);
            if (pgea.Cancel)
                return;

            this.PageIndex++;
            this.RefreshData();

            this.OnPageIndexChanged(e);
        }
    }
    protected void OnPageSizeChanged(EventArgs e)
    {
        this.RefreshData();
        if (this.PageSizeChanged != null)
            this.PageSizeChanged.Invoke(this, e);
    }
    protected override void OnDataBound(EventArgs e)
    {
        base.OnDataBound(e);
    }
    private void RefreshData()
    {
        this.DataBind();
    }
    private void imgPg_OnCommand(object sender, CommandEventArgs e)
    {
        switch (e.CommandName)
        {
            case "FirstPage":
                this.OnFirstPageClicked(EventArgs.Empty);
                break;
            case "LastPage":
                this.OnLastPageClicked(EventArgs.Empty);
                break;
            case "PrevPage":
                this.OnPreviousPageClicked(EventArgs.Empty);
                break;
            case "NextPage":
                this.OnNextPageClicked(EventArgs.Empty);
                break;
        }
    }
    private void drpPageSz_SelectedIndexChanged(object sender, EventArgs e)
    {
        DropDownList drpPgSz = (sender as DropDownList);

        if (drpPgSz != null)
        {
            this.PageSize = int.Parse(drpPgSz.SelectedValue);
            this.OnPageSizeChanged(e);
        }
        else
            throw new Exception("Unable to determine page size: cannot cast sender as DropDownList.");
    }

实际的事件处理程序位于底部。 “RefreshData”方法就在那里,因为我在调用“DataBind”之前尝试了从网格中清除控件的不同方法。到目前为止,我尝试的所有内容都会导致整个网格在回发后无法渲染。

我在使用Render和CreateChildControls做了很多工作,但是标题生成本身完全是System.Web.UI.WebControls.GridView控件的内部。这是我的渲染代码,如果它有帮助的话:

    protected override void OnPreRender(EventArgs e)
    {
        Control link = this.Page.Header.FindControl("CustomGridViewCss");
        if (link == null)
        {
            System.Web.UI.HtmlControls.HtmlLink newLink = new System.Web.UI.HtmlControls.HtmlLink();
            newLink.ID = "CustomGridViewCss";
            newLink.Attributes.Add("href", this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.style.CustomGridView.css"));
            newLink.Attributes.Add("type", "text/css");
            newLink.Attributes.Add("rel", "stylesheet");
            this.Page.Header.Controls.Add(newLink);
        }

        base.OnPreRender(e);
        this.EnsureChildControls();
    }
    protected override void Render(HtmlTextWriter writer)
    {

        if (this._imgFPg != null)
            this.Page.ClientScript.RegisterForEventValidation(this._imgFPg.UniqueID);
        if (this._imgPrevPg != null)
            this.Page.ClientScript.RegisterForEventValidation(this._imgPrevPg.UniqueID);
        if (this._imgNextPg != null)
            this.Page.ClientScript.RegisterForEventValidation(this._imgNextPg.UniqueID);
        if (this._imgLastPg != null)
            this.Page.ClientScript.RegisterForEventValidation(this._imgLastPg.UniqueID);
        if (this._drpPageSz != null)
            this.Page.ClientScript.RegisterForEventValidation(this._drpPageSz.UniqueID);

        if (this.HeaderRow != null)
            for (int i = 1; i < this.HeaderRow.Cells.Count - 2; i++)
                if (i < this.Columns.Count && this.Columns[i] is SortableField && ((this.Columns[i] as SortableField).ShowSort))
                {
                    ImageButton img = (this.HeaderRow.Cells[i].FindControl("imgSort_" + i.ToString()) as ImageButton);
                    if (img != null)
                        this.Page.ClientScript.RegisterForEventValidation(img.UniqueID);
                }
        base.Render(writer);
    }
    protected override Table CreateChildTable()
    {
        this.PagerSettings.Visible = false;
        this.GridLines = GridLines.None;
        Table tbl = base.CreateChildTable();
        tbl.Attributes.Add("name", this.UniqueID);
        return tbl;
    }
    protected override int CreateChildControls(System.Collections.IEnumerable dataSource, bool dataBinding)
    {
        this.GridLines = GridLines.None;
        int iCount = base.CreateChildControls(dataSource, dataBinding);

        // Modify footer row
        System.Web.UI.WebControls.GridViewRow ftr = this.FooterRow;
        // NOTE: We're modifying the footer first, because we're looking at the
        //   total number of rows in the header for the ColSpan property we
        //   use in the footer and we want the row count *before* we modify
        //   the header.
        ftr.Cells.Clear();
        this.BuildFooter(this.FooterRow);

        // Modify Header Row
        System.Web.UI.WebControls.GridViewRow hdr = this.HeaderRow;
        hdr.CssClass = "GridViewHeader";

        for (int c = 0; c < hdr.Cells.Count; c++)
        {
            hdr.Cells[c].CssClass = "GridViewHeaderTC";
            if (c > 0)
                hdr.Cells[c].Style.Add("border-left", "solid 1px #ccccd3");

            if (c < this.Columns.Count && this.Columns[c] is SortableField && ((this.Columns[c] as SortableField).ShowSort))
            {
                hdr.Cells[c].Controls.Clear();

                Label lblHdrText = new Label();
                lblHdrText.ID = "lblHdrText_" + c.ToString();
                lblHdrText.Text = hdr.Cells[c].Text;
                hdr.Cells[c].Controls.Add(lblHdrText);

                ImageButton imgSort = new ImageButton();
                imgSort.ID = "imgSort_" + c.ToString();
                imgSort.CssClass = "GridViewHeaderSort";
                imgSort.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.images.gridView.Sort.png");
                imgSort.AlternateText = "";
                imgSort.CommandArgument = (this.Columns[c] as BoundField).DataField;
                imgSort.CommandName = "Sort";
                imgSort.Command += new CommandEventHandler(this.imgSort_OnCommand);
                hdr.Cells[c].Controls.Add(imgSort);
                imgSort.Attributes.Add("name", imgSort.UniqueID);
            }
        }

        TableCell tdTL = new TableCell();
        tdTL.Style.Add(HtmlTextWriterStyle.Width, "6px");
        tdTL.CssClass = "GridViewHeaderTL";
        hdr.Cells.AddAt(0, tdTL);

        TableCell tdTR = new TableCell();
        tdTR.Style.Add(HtmlTextWriterStyle.Width, "6px");
        tdTR.Style.Add("border-left", "1px solid #ccccd3;");
        tdTR.CssClass = "GridViewHeaderTR";
        hdr.Cells.Add(tdTR);

        // Modify individual rows
        for (int i = 0; i < this.Rows.Count; i++)
        {
            System.Web.UI.WebControls.GridViewRow tr = this.Rows[i];
            tr.CssClass = (i % 2 == 0) ? "GridViewLineAlt" : "GridViewLine";

            for (int c = 0; c < tr.Cells.Count - 1; c++)
                tr.Cells[c].Style.Add("border-right", "solid 1px #ccccd3");

            TableCell tdL = new TableCell();
            tdL.CssClass = "GridViewLineLeft";
            tr.Cells.AddAt(0, tdL);

            TableCell tdR = new TableCell();
            tdR.CssClass = "GridViewLineRight";
            tr.Cells.Add(tdR);
        }

        return iCount;
    }
    protected void BuildFooter(GridViewRow tr)
    {
        TableCell tdBL = new TableCell();
        tdBL.Style.Add(HtmlTextWriterStyle.Width, "6px");
        tdBL.CssClass = "GridViewFooterBL";
        tr.Cells.Add(tdBL);

        int colCount = this.HeaderRow.Cells.Count;

        TableCell td = new TableCell();
        td.ID = "tdFooterControls";
        td.CssClass = "GridViewFooterBC";
        td.ColumnSpan = colCount;

        this._spanPgBtns = new Label();
        this._spanPgBtns.ID = "spanPgButtons";
        this._spanPgBtns.Style.Add("float", "right");
        this._spanPgBtns.Style.Add("margin-right", "20px");

        this._imgFPg = new ImageButton();
        this._imgFPg.ID = "imgFPg";
        this._imgFPg.CssClass = "FirstPg";
        this._imgFPg.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.images.gridView.FstPg.png");
        this._imgFPg.ImageAlign = ImageAlign.Middle;
        this._imgFPg.CommandName = "FirstPage";
        this._imgFPg.Command += new CommandEventHandler(this.imgPg_OnCommand);
        this._spanPgBtns.Controls.Add(this._imgFPg);

        this._imgPrevPg = new ImageButton();
        this._imgPrevPg.ID = "imgPrevPg";
        this._imgPrevPg.CssClass = "PrevPg";
        this._imgPrevPg.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.images.gridView.PrevPg.png");
        this._imgPrevPg.ImageAlign = ImageAlign.Middle;
        this._imgPrevPg.CommandName = "PrevPage";
        this._imgPrevPg.Command += new CommandEventHandler(this.imgPg_OnCommand);
        this._spanPgBtns.Controls.Add(this._imgPrevPg);

        Label lblPageNum = new Label();
        lblPageNum.ID = "lblPageNum";
        lblPageNum.Width = new Unit("50px");
        lblPageNum.Text = string.Format("{0} / {1}", this.PageIndex + 1, this.PageCount);
        lblPageNum.Style.Add(HtmlTextWriterStyle.TextAlign, "center");
        this._spanPgBtns.Controls.Add(lblPageNum);

        this._imgNextPg = new ImageButton();
        this._imgNextPg.ID = "imgNextPg";
        this._imgNextPg.CssClass = "NextPg";
        this._imgNextPg.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.images.gridView.NextPg.png");
        this._imgNextPg.ImageAlign = ImageAlign.Middle;
        this._imgNextPg.CommandName = "NextPage";
        this._imgNextPg.Command += new CommandEventHandler(this.imgPg_OnCommand);
        this._spanPgBtns.Controls.Add(this._imgNextPg);

        this._imgLastPg = new ImageButton();
        this._imgLastPg.ID = "imgLastPg";
        this._imgLastPg.CssClass = "LastPg";
        this._imgLastPg.ImageUrl = this.Page.ClientScript.GetWebResourceUrl(typeof(ITCWebToolkit.Web.UI.Controls.GridView), "ITCWebToolkit.Web.UI.Controls.images.gridView.LstPg.png");
        this._imgLastPg.ImageAlign = ImageAlign.Middle;
        this._imgLastPg.CommandName = "LastPage";
        this._imgLastPg.Command += new CommandEventHandler(this.imgPg_OnCommand);
        this._spanPgBtns.Controls.Add(this._imgLastPg);

        td.Controls.Add(this._spanPgBtns);

        Label spanPageSz = new Label();
        spanPageSz.ID = "spanPageSz";
        spanPageSz.Style.Add("margin-left", "20px");

        this._drpPageSz = new DropDownList();
        this._drpPageSz.ID = "drpPageSzSelect";
        this._drpPageSz.AutoPostBack = true;
        this._drpPageSz.SelectedIndexChanged += new EventHandler(drpPageSz_SelectedIndexChanged);
        this._drpPageSz.Items.Add(new ListItem("10", "10"));
        this._drpPageSz.Items.Add(new ListItem("25", "25"));
        this._drpPageSz.Items.Add(new ListItem("50", "50"));
        this._drpPageSz.Items.Add(new ListItem("100", "100"));
        spanPageSz.Controls.Add(this._drpPageSz);
        td.Controls.Add(spanPageSz);

        Label lblRecVis = new Label();
        lblRecVis.ID = "lblRecordsCount";
        lblRecVis.Style.Add("margin-left", "20px");
        lblRecVis.Text = string.Format("Displaying {0} of {1} records.", Math.Min(this.PageSize, this.Rows.Count - (this.PageIndex * this.PageSize)), this.Rows.Count);
        lblRecVis.Text = "Total Record Display";
        td.Controls.Add(lblRecVis);
        tr.Cells.Add(td);

        TableCell tdBR = new TableCell();
        tdBR.Style.Add(HtmlTextWriterStyle.Width, "6px");
        tdBR.CssClass = "GridViewFooterBR";
        tr.Cells.Add(tdBR);

        this._imgFPg.Attributes.Add("name", this._imgFPg.UniqueID);
        this._imgPrevPg.Attributes.Add("name", this._imgPrevPg.UniqueID);
        this._imgNextPg.Attributes.Add("name", this._imgNextPg.UniqueID);
        this._imgLastPg.Attributes.Add("name", this._imgLastPg.UniqueID);
        this._drpPageSz.Attributes.Add("name", this._drpPageSz.UniqueID);
    }

我在自定义服务器控件上只有6/10左右,所以我确定至少有一件事我在这里做错了:)

提前感谢您的帮助!

1 个答案:

答案 0 :(得分:0)

行。我终于找到了一个参考并回答了我自己的问题。诀窍是覆盖“PerformSelect”方法并在那里处理DataSource和DataSourceID。

有关如何执行此操作的详细信息,请访问此MSDN页面:

http://msdn.microsoft.com/en-us/library/ms366539(v=vs.90).aspx

查找标题为“启动数据检索”的部分,稍微超过一半。