Asp.net 具有相同ID的多个控件的自定义控件问题?

Asp.net 具有相同ID的多个控件的自定义控件问题?,asp.net,Asp.net,我有一个非常简单的自定义控件,定义如下: public class TestCtrl : WebControl { protected override void OnInit(EventArgs e) { var btn = new Button() { ID = "test", Text = "text"}; this.Controls.Add(btn); } } 然而,当我想把它们的多个实例放在同一页上时,我得到 '找到具有相同ID

我有一个非常简单的自定义控件,定义如下:

public class TestCtrl : WebControl
{
    protected override void OnInit(EventArgs e)
    {
        var btn = new Button() { ID = "test", Text = "text"};
        this.Controls.Add(btn);
    }
}
然而,当我想把它们的多个实例放在同一页上时,我得到

'找到具有相同ID的多个控件'test'

…当单击btn时

    protected void Page_Init(object sender, EventArgs e)
    {
        var ctrl1 = new TestCtrl() { ID = "ctrl1" };
        plc.Controls.Add(ctrl1);
        var ctrl2 = new TestCtrl() { ID = "ctrl2" };
        plc.Controls.Add(ctrl2);
    }
有没有干净的方法来阻止这种事情发生?我尝试将ClientIDMode设置为“自动”,但没有成功,因为呈现标记的
name
属性在两个按钮上都是
“test”


编辑:通过向控件添加“InAdminContainer”解决
公共类TestCtrl:WebControl,在MingContainer{…}

中,因为您在OnInit方法中已将btn的ID指定为等于“test”,因此当您将控件添加到页面时,它会为控件设置ID=test。我认为没有必要在OnInit()方法中设置ID属性。将以下代码添加到渲染方法中

protected override void OnInit(EventArgs e)
{
    var btn = new Button() { Text = "text"}; // No need to add ID property
    this.Controls.Add(btn);
}

编辑:通过在控件公共类TestCtrl:WebControl中添加'INamingContainer',INamingContainer{…}

解决了这个问题

 public class TestCtrl : WebControl, INamingContainer {

     private button btn;

     [Bindable(true), Category("Content"), DefaultValue(""), Description("Gets or Sets the Fields that are to be added to the ListItems")]
     public string TextField {
        get { EnsureChildControls(); return btn.Text; } 
        set { EnsureChildControls(); btn.Text = value; }
     }

     [Bindable(true), Category("Content"), DefaultValue(""), Description("Gets or Sets another field of your choice")]
     public string SomeStringField{
        get { return ViewState["_someStringField"] != null ? ViewState["_someStringField"].ToString() : String.Empty ;  }
        set { ViewState["_someStringField"] = value; }
     }

     protected override void OnInit(EventArgs e) {
         base.OnInit(e);
     }

     protected override void CreateChildControls() {
         btn = new button();
         btn.id = "btn";

         this.Controls.Add(btn);
     }

     protected override void Render(HtmlTextWriter writer) {
         writer.Write(<b>SomeStringField + ":</b>");
         btn.RenderControl(writer);
     }

 }
public类TestCtrl:WebControl,INamingContainer{
专用按钮btn;
[Bindable(true)、Category(“Content”)、DefaultValue(“”)、Description(“获取或设置要添加到ListItems中的字段”)]
公共字符串文本字段{
获取{ensureChildControl();返回btn.Text;}
set{EnsureChildControls();btn.Text=value;}
}
[Bindable(true)、Category(“Content”)、DefaultValue(“”)、Description(“获取或设置您选择的另一个字段”)]
公共字符串字段{
获取{return ViewState[“\u someStringField”!=null?ViewState[“\u someStringField”].ToString():String.Empty;}
设置{ViewState[“\u someStringField”]=value;}
}
受保护的覆盖无效OnInit(事件参数e){
碱基.奥尼特(e);
}
受保护的覆盖无效CreateChildControls(){
btn=新按钮();
btn.id=“btn”;
this.Controls.Add(btn);
}
受保护的覆盖无效渲染(HtmlTextWriter编写器){
writer.Write(SomeStringField+“:”);
btn.渲染控制(编写器);
}
}
将其添加到页面后

这将显示一个标签,然后显示旁边的按钮。您希望删除CreateChildControls中的id,以便为其分配唯一的id。EnsureChildControls将确保正确加载属性。你可以在控件的任何地方调用这个方法,但我会在OnInit之后调用。如果没有,则Id将被混淆。有时他们会工作,而另一些则不会。Jquery的Javascript也会让你头疼

我会参考微软的例子。他们有很多,非常有用


尝试在TestCtrl类上创建一个属性并设置值否,这不是个好主意。如果在没有id的情况下重新创建控件,它将采用新的id/name属性,因此即使在以下回发中也不会触发任何附加的属性。@maxp是否创建自定义服务器控件?是,根据上面的示例,@maxp但您尚未重写呈现方法?@maxp对于自定义服务器控件,在设计时不必为属性赋值。当我们使用控件时,我们为属性赋值。当您将此控件放置在一个页面上时,一个新的ID会自动分配给该控件,因此不可能重新分配ID。