2013-03-19 4 views
1

OK. J'ai longtemps utilisé ce site comme référence, mais j'ai maintenant trouvé mon propre mur.Contrôle de serveur GridView personnalisé DataBind entraîne une erreur d'ID de contrôle en double

Je crée un contrôle serveur personnalisé qui hérite de la classe System.Web.UI.WebControls.GridView. Son but est simplement d'afficher une grille avec un format très défini. Il lie et charge les données correctement, mais si vous tentez d'activer une partie de la pagination, une exception indiquant "Plusieurs contrôles ayant le même ID 'lblHdrText_2' a été trouvée." FindControl requiert que les contrôles aient des ID uniques. ". Je pouvais simplement lancer l'événement à l'utilisateur et lui laisser faire la pagination, mais l'un des objectifs était de permettre à ce contrôle de gérer sa propre pagination, comme le fait déjà le contrôle GridView.

J'ai le même problème pour trier et modifier la taille de la page. Fondamentalement chaque fois que j'appelle "DataBind" dans le contrôle après qu'il a déjà été rendu.

Voici le code pour gérer ces événements:

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."); 
    } 

Les gestionnaires d'événements réels sont en bas. La méthode "RefreshData" est juste là parce que j'expérimentais différentes manières d'effacer les contrôles de la grille avant d'appeler "DataBind". Jusqu'à présent, tout ce que j'ai essayé de résultats dans la grille entière ne rend pas après la publication.

Je fais un peu avec Render et CreateChildControls, mais la génération d'en-tête elle-même est complètement interne au contrôle System.Web.UI.WebControls.GridView. Voici mon code de rendu, si elle aide à tous:

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

Je suis seulement 6/10 sur les contrôles de serveur personnalisés, donc je suis sûr qu'il ya au moins une chose que je fais mal ici :)

Merci d'avance pour toute aide!

+0

OK. J'ai finalement trouvé une référence et répondu à ma propre question. L'astuce consiste à remplacer la méthode "PerformSelect" et à gérer DataSource vs DataSourceID. http://msdn.microsoft.com/fr-fr/library/ms366539(v=vs.90).aspx –

Répondre

0

OK. J'ai finalement trouvé une référence et répondu à ma propre question. L'astuce consiste à remplacer la méthode "PerformSelect" et à gérer DataSource vs DataSourceID.

Détails sur la façon de faire se trouvent sur cette page MSDN:

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

Recherchez la section intitulée « Initier de récupération de données » un peu plus à mi-chemin vers le bas.

Questions connexes