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。