使用具有相同ID的多个ASP.NET控件

时间:2010-08-05 18:21:50

标签: c# asp.net visual-studio controls

我正在尝试动态地将控件添加到asp.net页面。页面正确呈现但在回发后,我收到以下错误:

[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

我尝试过几种不同的东西。我想在OnInit或page_load上删除控件就像这样

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

会起作用但不会

自定义树视图控件代码

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

这是我添加树的页面:

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

    }
}

2 个答案:

答案 0 :(得分:2)

在将控件的ID属性添加到页面之前,需要将其设置为某个唯一值。您可以使用许多技巧来完成这项工作。如果您提供更多代码,我们可以根据您的具体情况提供一些解决方案。

修改

看起来你在这里遇到了一些非常复杂的东西,所以我并没有完全满足它。但是,我会在实例化时设置ContainerTreeNodes的ID,而不是在OnInit阶段。我还要使ContainerTreeNode体系结构支持遍历和删除自身内部节点的方法,而不是尝试从树外部手动删除基于控件ID的节点。

答案 1 :(得分:2)

我可能会误解代码,但如果PreRenderContainer和PostRenderContainer属性实现INamingcontainer并且您更改了ID,我认为您可能不会让他们完成自己的工作。它应该自动为您提供独特的ID。像ctl00,ctl01等......