using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; namespace WebControls.Test { public class PBLink:WebControl,IPostBackEventHandler { [Category("Behavior")] [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)] public string Text { get { object o = ViewState["Text"]; return o == null ? String.Empty : (string)o; } set { ViewState["Text"] = value; } } protected override void OnPreRender(EventArgs e) { if (Page != null) Page.RegisterRequiresPostBack(this); base.OnPreRender(e); } protected override void Render(HtmlTextWriter writer) { if (Page != null) Page.VerifyRenderingInServerForm(this); base.Render(writer); } protected override void RenderContents(HtmlTextWriter writer) { writer.Write(Text); } #region IPostBackEventHandler members public void RaisePostBackEvent(string eventArgument) { throw new NotImplementedException(); } #endregion protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.A; } } } }
运行后会报错:
“/WebSite”应用程序中的服务器错误。
只能对实现 IPostBackDataHandler 的控件调用 Page.RegisterRequiresPostBack。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.Web.HttpException: 只能对实现 IPostBackDataHandler 的控件调用 Page.RegisterRequiresPostBack。
源错误:
|
源文件: C:\MyProjects\csharp\test\controls\Controls\WebControls\Test\PBLink.cs 行: 29
至少说明
Page.RegisterRequiresPostBack 是和 IPostBackDataHandler 一起用的。
而
Page.RegisterRequiresRaiseEvent 一次只接受一个控件。
例如:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Web.UI.WebControls; using System.Web.UI; using System.Collections.Specialized; using System.ComponentModel; namespace WebControls.BookSample { public class SimpleTextBoxTextChangedEventArgs : EventArgs { private string m_OldText; private string m_NewText; public SimpleTextBoxTextChangedEventArgs(string oldTxt, string newTxt) { m_OldText = oldTxt; m_NewText = newTxt; } public string OldText { get { return m_OldText; } } public string NewText { get { return m_NewText; } } } public delegate void SimpleTextBoxTextChange(object sender,SimpleTextBoxTextChangedEventArgs e); public class SimpleTextBox:WebControl,IPostBackDataHandler,IPostBackEventHandler { private const string textKey = "Text"; private static readonly object textChangedKey = new object(); private static readonly object postBackKey = new object(); private string eventOldText; private string eventNewText; [Category("Action"), Description("This happens after changed!")] public event SimpleTextBoxTextChange TextChanged { add { Events.AddHandler(textChangedKey, value); } remove { Events.RemoveHandler(textChangedKey, value); } } protected void OnTextChanged(SimpleTextBoxTextChangedEventArgs e) { SimpleTextBoxTextChange handler = Events[textChangedKey] as SimpleTextBoxTextChange; if (handler != null) handler(this, e); } [Bindable(true), Category("Behavior"), DefaultValue(""), Description("text in textbox")] public string Text { get { object o = ViewState[textKey]; return o == null ? String.Empty : (string)o; } set { ViewState[textKey] = value; } } [Category("Action"),Description("Nonsense")] public event EventHandler PostBackEvent { add { Events.AddHandler(postBackKey, value); } remove { Events.RemoveHandler(postBackKey, value); } } public void OnPostBackEvent(EventArgs e) { EventHandler handler = Events[postBackKey] as EventHandler; if (handler != null) handler(this, e); } protected override HtmlTextWriterTag TagKey { get { return HtmlTextWriterTag.Input; } } //protected override void OnPreRender(EventArgs e) //{ // if (Page != null) // Page.RegisterRequiresPostBack(this); // base.OnPreRender(e); //} protected override void Render(HtmlTextWriter writer) { if (Page != null) Page.VerifyRenderingInServerForm(this); base.Render(writer); } protected override void AddAttributesToRender(HtmlTextWriter writer) { base.AddAttributesToRender(writer); writer.AddAttribute(HtmlTextWriterAttribute.Name, UniqueID); writer.AddAttribute(HtmlTextWriterAttribute.Value, Text); writer.AddAttribute(HtmlTextWriterAttribute.Type, "text"); } #region IPostBackDataHandler members public bool LoadPostData(string postDataKey, NameValueCollection postCollection) { eventOldText = Text; eventNewText = postCollection[UniqueID]; bool hasChanged = (eventOldText != eventNewText); Text = eventNewText; Page.RegisterRequiresRaiseEvent(this); return hasChanged; } public void RaisePostDataChangedEvent() { OnTextChanged(new SimpleTextBoxTextChangedEventArgs(eventOldText, eventNewText)); } #endregion #region IPostBackEventHandler members void IPostBackEventHandler.RaisePostBackEvent(string eventArgument) { OnPostBackEvent(EventArgs.Empty); } #endregion } }
当把SimpleTextBox一个以上数量的实例放置到页面上时,RaisePostBackEvent不执行,只有一个的时候却可以。
猜测并总结一下:
在一般情况下, IPostBackDataHandler 的方法由页面回传的Name去寻找控件并调用。当这种寻找并调用无法正常工作时,偏向于使用 Page.RegisterRequiresPostBack 将控件强行加入数据处理事件链中。
同样的,通常 IPostBackEventHandler 的方法由控件上的__doPostBack的脚本函数之类(这种函数多通过 Page.ClientScript.GetPostBackEventReference 和 Page.ClientScript.GetPostBackClientHyperlink来产生脚本调用代码)激发。 非正常情况可能就需要 Page.RegisterRequiresRaiseEvent的帮助