首先,我发现了一些类似的问题。其中一个是 here ,它没有正确答案。
我正在编写自定义服务器控件,它具有 Text 属性和 Click 事件。一切都很好(点击事件正在触发,发件人对象具有正确的值),但仅当我仅在页面上的一个地方使用它时
此示例正常工作(如果 SimpleControl1.Text 具有值“First control”,作为响应我收到了正确的值):
protected void SimpleControl1_Click(object sender, EventArgs e)
{
SimpleControl sc = sender as SimpleControl;
if(sc != null)
{
Response.Write(sc.Text);
}
}
但如果我在同一页面上添加第二个控件( SimpleControl2 ,文本“Second Control”),我的第一个控件的 Click 事件将会不再工作:
protected void SimpleControl2_Click(object sender, EventArgs e)
{
SimpleControl sc = sender as SimpleControl;
if (sc != null)
{
Response.Write(sc.Text);
}
}
所以如果我点击第一个控件,我就会收到“Second control”文本。
我想我错过了什么,但我不确定是什么。
如何解决此问题?
这是我简单的Web控件:
public class SimpleControl : WebControl, IPostBackEventHandler
{
public string Text { get; set; }
protected override void OnInit(EventArgs e)
{
Page.RegisterRequiresRaiseEvent(this);
Page.RegisterRequiresControlState(this);
base.OnInit(e);
}
private static readonly object EventClick = new object();
protected virtual void OnClick(EventArgs e)
{
EventHandler eventHandler = (EventHandler)Events[SimpleControl.EventClick];
if (eventHandler != null) { eventHandler(this, e); }
}
public event EventHandler Click
{
add { Events.AddHandler(EventClick, value); }
remove { Events.RemoveHandler(EventClick, value); }
}
protected override object SaveControlState()
{
object state = base.SaveControlState();
return new object[] { state, Text };
}
protected override void LoadControlState(object state)
{
object[] states = state as object[];
if (states != null)
{
base.LoadControlState(states[0]);
Text = (string)states[1];
}
}
protected override void RenderContents(System.Web.UI.HtmlTextWriter writer)
{
writer.AddAttribute(HtmlTextWriterAttribute.Id, this.ClientID);
writer.AddAttribute(HtmlTextWriterAttribute.Name, this.UniqueID);
writer.AddAttribute(HtmlTextWriterAttribute.Onclick, Page.ClientScript.GetPostBackEventReference(this, "Click"));
writer.RenderBeginTag("div");
writer.Write(Text);
writer.RenderEndTag();
base.RenderContents(writer);
}
public void RaisePostBackEvent(string eventArgument)
{
this.OnClick(EventArgs.Empty);
}
}
修改
markap
<cc1:SimpleControl ID="SimpleControl1" runat="server"
Text="First control" OnClick="SimpleControl1_Click" />
<cc1:SimpleControl ID="SimpleControl2" runat="server"
Text="Second Control" OnClick="SimpleControl2_Click" />
P.S。我还删除了控制状态支持,但它没有解决问题。
答案 0 :(得分:3)
你如何约束你的活动?你能展示标记吗?当你绑定事件时,我会假设发生了一些奇怪的事情,不知怎的,你已经将第二个事件绑定到第一个控件,或者沿着这些线路绑定了什么。
答案 1 :(得分:3)
从OnInit
Page.RegisterRequiresRaiseEvent(this);
此方法的msdn声明:
每页请求只能注册一个服务器控件。
http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerrequiresraiseevent.aspx
答案 2 :(得分:0)
我想@Crwydryn猜测如果该功能是你所追求的(或有些相似),那就非常有用了。您可以绑定到SimpleControl_Click以获取两个或更多控件。发布您的标记会很有帮助。
答案 3 :(得分:0)
问题是对象状态= base.SaveControlState()状态可能为null。根据MSDN
返回服务器控件的当前状态。如果没有与控件关联的状态,则此方法返回null。
public override object SaveControlState()
{
object obj = base.SaveControlState();
// Your problem is here
// return new object[] { obj, Text };
if (!string.IsNullOrEmpty(Text))
{
if (obj != null)
{
return new object[] { obj, Text };
}
else
{
return Text;
}
}
else
{
return obj;
}
}
public override void LoadControlState(object state)
{
if (state != null)
{
object obj = state as object[];
if (obj != null)
{
base.LoadControlState(obj[0]);
Text = (string)obj[1];
}
else
{
if (state is string)
{
Text = (string)state;
}
else
{
base.LoadControlState(state);
}
}
}
}