2013-03-19 92 views
1

好的。我长期以来一直使用这个网站作为参考,但现在我已经打到了我自己的一面墙。自定义GridView服务器控件DataBind会导致重复控件ID的错误

我正在创建一个继承自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,所以我敢肯定有至少有一件事我做错了:)

在此先感谢您的帮助!

+0

好的。我终于找到了一个参考,并回答了我自己的问题。技巧在于覆盖“PerformSelect”方法并在那里处理DataSource和DataSourceID。 http://msdn.microsoft.com/en-us/library/ms366539(v=vs.90).aspx – 2013-10-28 20:03:06

回答

0

好的。我终于找到了一个参考,并回答了我自己的问题。技巧在于覆盖“PerformSelect”方法并在那里处理DataSource和DataSourceID。如何做到这一点

详细信息可以在这个MSDN网页上找到:

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

查找标题为“启动数据检索”略超过一半一路下滑。

相关问题