2013-04-21 41 views
1

首先,我發現了一些類似的問題。其中之一是here,它沒有正確的答案。服務器控件事件無法正確觸發

我正在寫自定義服務器控件,其中有文本屬性和點擊事件。一切都很好(點擊事件正在觸發和發件人對象具有正確的值),但只有當我只在頁面上的一個地方使用

此示例工作正常(如果SimpleControl1.Text具有價值「第一控制」,在響應我收到正確的值):

protected void SimpleControl1_Click(object sender, EventArgs e) 
    { 
     SimpleControl sc = sender as SimpleControl; 
     if(sc != null) 
     { 
      Response.Write(sc.Text); 
     } 
    } 

但是,如果我在同一個加第二控制頁面(SimpleControl2文本「二控制」),我的第一個控制器的點擊事件將不再工作:

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

編輯

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" /> 

附:我也刪除了控制狀態支持,但它沒有解決問題。

+0

則可以使用該控制 – 2013-04-21 10:25:23

+0

的裁判我認爲**對象狀態= base.SaveControlState()**狀態可以爲空。 – 2013-04-21 13:56:44

+0

@minhcat_vo控制狀態不能產生此問題。我完全刪除了控制狀態支持並更改爲ViewState,但它仍然觸發第二個事件。 – 2013-04-21 14:08:32

回答

3

你如何約束你的事件?你也可以顯示標記嗎?我會假定當你綁定事件時會發生奇怪的事情,並且不知何故,你已經將第二個事件綁定到第一個控件,或者沿着這些線條。

+1

+1正是我的想法 – 2013-04-21 12:15:21

+0

不,這不會產生問題。我在DataList中使用這個控件作爲模板控件,只有最後添加的控件的事件觸發。即使我點擊任何其他控件。 – 2013-04-21 14:13:07

0

我想@Crwydryn猜測是非常現貨,如果功能是你之後(或有點相似)。您可以將兩個或多個控件綁定到SimpleControl_Click。發佈你的標記會有幫助。

0

問題是對象狀態= base.SaveControlState()狀態可能爲空。根據MSDN

返回服務器控件的當前狀態。如果沒有與控件關聯的狀態,則此方法返回null。此方法的狀態

Page.RegisterRequiresRaiseEvent(this); 

在MSDN:

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