简体   繁体   中英

Use Multiple ASP.NET controls with the same ID

I am trying to dynamically add controls to an asp.net page. The page is rendering correctly but after posting back, I get the following error:

[HttpException (0x80004005): Multiple controls with the same 

ID 'ParentTextBox_ChildTextBox_TV_PostRender' were found. FindControl requires that controls have unique IDs.]
   System.Web.UI.Control.FillNamedControlsTable(Control namingContainer, ControlCollection controls) +273
   System.Web.UI.Control.EnsureNamedControlsTable() +61
   System.Web.UI.Control.FindControl(String id, Int32 pathOffset) +222
   System.Web.UI.Control.FindControl(String id, Int32 pathOffset) +327
   System.Web.UI.Page.FindControl(String id) +38
   System.Web.UI.Page.ProcessPostData(NameValueCollection postData, Boolean fBeforeLoad) +232
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1434

I have tried several different things a none of which work. I thought removing the control in OnInit or on page_load like this

Control c = Page.FindControl("ParentTextBox_ChildTextBox_TV_PostRender");
Page.Controls.Remove(c);

will work but it doesn't

Code of custom tree view control

// file ContainerTreeView.cs

using System.Web.UI;
using System.Web.UI.WebControls;
using System;
namespace DASHBOARD
{
    [ToolboxData("<{0}:ContainerTreeView runat=server></{0}:ContainerTreeView>")]
    public class ContainerTreeView : TreeView, INamingContainer
    {
        public ContainerTreeView()
            : base()
        {
            PathSeparator = ClientIDSeparator;
        }

        protected override void OnInit(EventArgs e)
        {
            // Initialize Child Controls
            RecurseUpdateNodes(Nodes);

            base.OnInit(e);
        }

        protected const String s_strNodeValueSeparator = "_TV_";
        protected virtual void RecurseUpdateNodes(TreeNodeCollection parrNodes)
        {
            if (parrNodes == null || parrNodes.Count == 0)
                return;

            foreach (TreeNode pNode in parrNodes)
            {
                ContainerTreeNode pContainerNode = pNode as ContainerTreeNode;
                if (pContainerNode != null)
                {
                    // update node pre / post rendering control IDs id
                    if (pContainerNode.PreRenderContainer != null)
                    {
                        pContainerNode.PreRenderContainer.ID = pContainerNode.PreRenderContainer.ID.Insert(0, pNode.ValuePath + s_strNodeValueSeparator);
                        Controls.Add(pContainerNode.PreRenderContainer);
                    }
                    if (pContainerNode.PostRenderContainer != null)
                    {
                        pContainerNode.PostRenderContainer.ID = pContainerNode.PostRenderContainer.ID.Insert(0, pNode.ValuePath + s_strNodeValueSeparator);
                        Controls.Add(pContainerNode.PostRenderContainer);
                    }
                }

                // update children
                RecurseUpdateNodes(pNode.ChildNodes);
            }
        }

        public ContainerTreeNode CreateTreeNode()
        {
            return new ContainerTreeNode(this, false);
        }
        protected override TreeNode CreateNode()
        {
            return CreateTreeNode();
        }

        // collection of child controls
        protected override ControlCollection CreateControlCollection()
        {
            return new ControlCollection(this);
        }
        protected override void RenderChildren(HtmlTextWriter writer)
        {
            // do not render children as they will be rendered within treeview nodes
            // base.RenderChildren(writer);
        }
    }
}

This is the page where I am adding the tree:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using System.Xml.Linq;

namespace DASHBOARD
{
    public partial class testTreeEdit : System.Web.UI.Page
    {
        ContainerTreeView m_pTreeView = null;



        protected override void OnInit(EventArgs e)
         {

                 Control c = Page.FindControl("ParentTextBox_ChildTextBox_TV_PostRender");
                 Page.Controls.Remove(c);
                 tb.Text += "Removed Control";

             base.OnInit(e);
         } 

        #region main
        protected void Page_Load(object sender, EventArgs e)
        {



            if (CheckBox1.Checked)
            {


                renderEditTree();


            }
            else 
            { 
               makeTree();
               TreeView1.ExpandAll();
            }





        }
        #endregion

        #region editableTreeView

      /**  //function to render editable tree view
        protected void renderEditTree()
        {
            m_pTreeView = new ContainerTreeView();

            ContainerTreeNode pNodeParent = m_pTreeView.CreateTreeNode();
            pNodeParent.Value = "Parent";
            pNodeParent.Text = "Parent";
            pNodeParent.Expanded = true;
            m_pTreeView.Nodes.Add(pNodeParent);

            /**ContainerTreeNode pNodeChildDropDown = m_pTreeView.CreateTreeNode();
            pNodeChildDropDown.Value = "ChildDropDown";
            pNodeChildDropDown.Text = String.Empty;
            DropDownList pList = new DropDownList();
            pList.ID = "ID_DropDown";
            pList.Items.Add("AAA");
            pList.Items.Add("BBB");
            pList.Items.Add("CCC");
            pNodeChildDropDown.PostRenderControls.Add(pList);
            pNodeParent.ChildNodes.Add(pNodeChildDropDown);

            /**ContainerTreeNode pNodeChildButton = m_pTreeView.CreateTreeNode();
            pNodeChildButton.Value = "ChildButton";
            pNodeChildButton.Text = String.Empty;
            Button pButton = new Button();
            pButton.ID = "ID_Button";
            pButton.Text = "PostBack";
            pNodeChildButton.PostRenderControls.Add(pButton);
            pNodeParent.ChildNodes.Add(pNodeChildButton);

          /**  ContainerTreeNode pNodeChildTextBox = m_pTreeView.CreateTreeNode();
            pNodeChildTextBox.Value = "ChildTextBox";
            pNodeChildTextBox.Text = String.Empty;
            TextBox pTextBox = new TextBox();
            pTextBox.ID = "ID_TextBox";
            pTextBox.Text = "Some text";
            pNodeChildTextBox.PostRenderControls.Add(pTextBox);
            pNodeParent.ChildNodes.Add(pNodeChildTextBox);


            this.treeViewContainer.Controls.Add(m_pTreeView);


        }*/

        //load XML file and use it to make the tree view
        public void renderEditTree()
        {


            m_pTreeView = new ContainerTreeView();


            XDocument document = XDocument.Load(Server.MapPath("~/Releases_files/releases.xml"));
            foreach (XElement element in document.Descendants("Release"))
            {

                XName name0 = "version";
                XAttribute a0 = element.Attribute(name0);
                string temp0 = a0.Value;

                ContainerTreeNode pmTextBox = m_pTreeView.CreateTreeNode();
                pmTextBox.Value = "ParentTextBox";
                pmTextBox.Text = String.Empty;

                TextBox pTextBox = new TextBox();
                pTextBox.ID = temp0;
                pTextBox.Text = temp0;

                pmTextBox.PostRenderControls.Add(pTextBox);
                m_pTreeView.Nodes.Add(pmTextBox);
                //n0.Text = temp0;
                //TreeView1.Nodes.Add(n0);

                foreach (XElement myElement in element.Descendants("Feature"))
                {

                    XName name = "Name";
                    XAttribute a = myElement.Attribute(name);
                    string temp = a.Value;

                    ContainerTreeNode pcTextBox = m_pTreeView.CreateTreeNode();
                    pcTextBox.Value = "ChildTextBox";
                    pcTextBox.Text = String.Empty;

                    TextBox p2TextBox = new TextBox();

                    p2TextBox.ID = temp;
                    p2TextBox.Text = temp;
                    pcTextBox.PostRenderControls.Add(p2TextBox);
                    pmTextBox.ChildNodes.Add(pcTextBox);

                }
                this.treeViewContainer.Controls.Add(m_pTreeView);
            }
        }

        #endregion


        #region simpleTreeView

        //old code

        //load XML file and use it to make the tree view
        public void makeTree()
        {
            TreeView1.Nodes.Clear();
            XDocument document = XDocument.Load(Server.MapPath("~/Releases_files/releases.xml"));
            foreach (XElement element in document.Descendants("Release"))
            {
                TreeNode n0 = new TreeNode();
                XName name0 = "version";
                XAttribute a0 = element.Attribute(name0);
                string temp0 = a0.Value;
                n0.Text = temp0;
                TreeView1.Nodes.Add(n0);

                foreach (XElement myElement in element.Descendants("Feature"))
                {
                    TreeNode n = new TreeNode();
                    XName name = "Name";
                    XAttribute a = myElement.Attribute(name);
                    string temp = a.Value;
                    n.Text = temp;

                    n0.ChildNodes.Add(n);

                }
            }
        }

        //action to do when selected node is changed
        protected void TreeView1_SelectedNodeChanged(object sender, EventArgs e)
        {
            XDocument document = XDocument.Load(Server.MapPath("~/Releases_files/releases.xml"));


            //debug
            //Label1.Text = TreeView1.SelectedNode.Text;
            //Label5.Text = Convert.ToString(TreeView1.SelectedNode.Depth);

            //case1: feature selected
            if (TreeView1.SelectedNode.Depth > 0)
            {
                string featureName = TreeView1.SelectedNode.Text;
                string releaseName = TreeView1.SelectedNode.Parent.Text;

                foreach (XElement element in document.Descendants("Release"))
                {
                    //find the right release in XML 
                    XName name = "version";
                    XAttribute a = element.Attribute(name);
                    string versionAttribute = a.Value;
                    if (releaseName.Equals(versionAttribute))
                    {
                        foreach (XElement myElement in element.Descendants("Feature"))
                        {
                            //find the right feature in XML
                            XName name1 = "Name";
                            XAttribute a1 = myElement.Attribute(name1);
                            string versionAttribute1 = a1.Value;

                            if (featureName.Equals(versionAttribute1))
                            {
                                //found the right node, now populate the Fields
                                IEnumerable<XElement> dates = element.Descendants("Date");
                                XElement date = dates.First<XElement>();
                                Label5.Text = date.Value;
                                IEnumerable<XElement> statuses = element.Descendants("Status");
                                XElement status = statuses.First<XElement>();
                                Label6.Text = status.Value;
                                IEnumerable<XElement> types = myElement.Descendants("Type");
                                XElement type = types.First<XElement>();
                                Label7.Text = type.Value;
                                IEnumerable<XElement> developers = myElement.Descendants("Developer");
                                XElement developer = developers.First<XElement>();
                                Label8.Text = developer.Value;
                                IEnumerable<XElement> details = myElement.Descendants("Detail");
                                XElement detail = details.First<XElement>();
                                tb.Text = detail.Value;
                            }
                        }

                    }

                }
            }
            //case2: Release selected
            else
            {
                string releaseName = TreeView1.SelectedNode.Text;
                foreach (XElement element in document.Descendants("Release"))
                {
                    //find the right release in XML 
                    XName name = "version";
                    XAttribute a = element.Attribute(name);
                    string versionAttribute = a.Value;
                    if (releaseName.Equals(versionAttribute))
                    {
                        //found the right node, now populate the Fields
                        IEnumerable<XElement> dates = element.Descendants("Date");
                        XElement date = dates.First<XElement>();
                        Label5.Text = date.Value;
                        IEnumerable<XElement> statuses = element.Descendants("Status");
                        XElement status = statuses.First<XElement>();
                        Label7.Text = " ";
                        Label8.Text = " ";
                        tb.Text = " ";
                    }
                }
            }
        }

        #endregion


        #region userInputs
        protected void Button2_Click(object sender, EventArgs e)
        {

        }

        //edit tree check box
        protected void CheckBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (CheckBox1.Checked )//&& TreeView1.Visible==true)
            {


                TreeView1.Visible = false;
                if (m_pTreeView != null)
                {
                    m_pTreeView.Visible = true;
                }
                Label5.Enabled = false;
                Label6.Enabled = false;
                Label7.Enabled = false;
                Label8.Enabled = false;
                tb.Enabled = false;


            }
            else
            {

                TreeView1.Visible = true;
                if (m_pTreeView != null)
                {
                    m_pTreeView.Visible = false;
                }
                Label5.Enabled = true;
                Label6.Enabled = true;
                Label7.Enabled = true;
                Label8.Enabled = true;
                tb.Enabled = true;


            }
        }
        #endregion

    }
}

You need to set the ID property of the control to some unique value before adding it to the page. There are a number of tricks you can use to make this work out. If you provide more code, we can provide some ideas for solutions tailored to your situation.

Edit

It looks like you've got some pretty complicated stuff going on here, so I'm not grokking it fully. However, I'd look at setting the IDs of your ContainerTreeNodes when they're instantiated, rather than during the OnInit phase. I'd also make the ContainerTreeNode architecture support a means of traversing and removing a node within itself, rather than trying to manually remove a node based on a Control ID from outside the tree.

I may be misunderstanding the code a bit, but if the PreRenderContainer and PostRenderContainer properties implement INamingcontainer and you change their IDs, I think you might not be letting them do their job. It should automatically give you unique ids. Like ctl00, ctl01 etc...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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