1

首先,我发现了几个类似的问题。其中之一是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);
        }
    }

因此,如果我单击第一个控件,我将收到“第二个控件”文本。

我想我错过了一些东西,但我不确定是什么。

如何解决这个问题?

这是我的简单 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);
    }
}

编辑

标记

<cc1:SimpleControl ID="SimpleControl1" runat="server" 
Text="First control" OnClick="SimpleControl1_Click"  />
<cc1:SimpleControl ID="SimpleControl2" runat="server" 
Text="Second Control" OnClick="SimpleControl2_Click" />

ps 我还删除了控制状态支持,但它并没有解决问题。

4

4 回答 4

3

你如何绑定你的事件?你也可以显示标记吗?我会假设当你绑定事件时发生了一些奇怪的事情,并且你以某种方式将第二个事件绑定到第一个控件,或者类似的东西。

于 2013-04-21T12:12:38.607 回答
3

删除此行OnInit

Page.RegisterRequiresRaiseEvent(this);

此方法的 msdn 指出:

每个页面请求只能注册一个服务器控件。

http://msdn.microsoft.com/en-us/library/system.web.ui.page.registerrequiresraiseevent.aspx

于 2013-04-21T14:28:29.273 回答
0

我猜@Crwydryn 猜测该功能是否是您所追求的(或有点相似)。您可以为两个或多个控件绑定到 SimpleControl_Click。发布您的标记将很有帮助。

于 2013-04-21T12:24:13.697 回答
0

问题是对象状态 = base.SaveControlState()状态可能为空。根据 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);
            }
        }
    }
}
于 2013-04-21T12:47:02.197 回答