LoadPostData vs RaisePostBack
按照MSDN的说法,页面上每一个实现了IPostBackDataHandler接口的控件在回传时都会执行自己的LoadPostData方法来更新自己的状态(参见“处理回发数据”),前提是要在自定义控件内添加一个“Name”属性和自定义控件的UniqueId相同的元素(参见[url=http://www.daima.com.cn/Info/34/Info34563/]引发自定义控件LoadPostData方法的必要条件)。那为什么为一个submit添加和为Text/hidden添加就不同呢,当为Submit添加这个属性时(就是与自定义控件UniqueId相同的Name属性),在回传的时候就只会执行触发回传的那个控件的LoadPostData事件(假设页面上有多个这种自定义控件的实例),而其它控件的LoadPostData事件就不会执行;而当为text/hidden添加这个属性时,不管由页面上哪个控件引起的回传,所有控件的LoadPostData方法都会执行(要的就是这个效果)。
但是用一个text/hidden来设置属性时在实现IPostBackEventHandler接口时又会遇到问题:就是不管哪个控件引起回传都只会执行最后一个控件的RaisePostBackEvent方法(所有的LoadPostBack方法都是执行了的。),但是需要的不是这样,需要的是哪个引起的回传就执行哪个的回传事件(RaisePostBackEvent)。
按照MSDN的说法,页面上每一个实现了IPostBackDataHandler接口的控件在回传时都会执行自己的LoadPostData方法来更新自己的状态(参见“处理回发数据”),前提是要在自定义控件内添加一个“Name”属性和自定义控件的UniqueId相同的元素(参见[url=http://www.daima.com.cn/Info/34/Info34563/]引发自定义控件LoadPostData方法的必要条件)。那为什么为一个submit添加和为Text/hidden添加就不同呢,当为Submit添加这个属性时(就是与自定义控件UniqueId相同的Name属性),在回传的时候就只会执行触发回传的那个控件的LoadPostData事件(假设页面上有多个这种自定义控件的实例),而其它控件的LoadPostData事件就不会执行;而当为text/hidden添加这个属性时,不管由页面上哪个控件引起的回传,所有控件的LoadPostData方法都会执行(要的就是这个效果)。
但是用一个text/hidden来设置属性时在实现IPostBackEventHandler接口时又会遇到问题:就是不管哪个控件引起回传都只会执行最后一个控件的RaisePostBackEvent方法(所有的LoadPostBack方法都是执行了的。),但是需要的不是这样,需要的是哪个引起的回传就执行哪个的回传事件(RaisePostBackEvent)。
LoadPostData方法问题。。 这里把自定义控件的Render方法贴出来: protected override void Render(HtmlTextWriter writer) { writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Type,"hidden"); [color=red]writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Name,this.UniqueID);[/color] writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Value,""); writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Input); writer.RenderEndTag(); writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Type,"submit"); [color=red]writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Name,this.UniqueID);[/color] writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Value,"Click Me"); writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Input); writer.RenderEndTag(); } 有兴趣的兄弟可以自己建一个项目试一试,很简单,就从System.Web.Ui.Control继承,然后实现IPostBackDataHandler和IPostBackEventHandler接口,在重写Render方法就Ok了。 注意红色部分的代码,给不同元素(这里只有hidden和submit啦)的Name赋值this.UniqueID时回传时执行会有不同,请接着看下面的回复贴。。。。 |
LoadPostData方法问题。。 1:hidden.Name=this.UniqueID,submit.Name<>this.UniqueID 执行全部控件的LoadPostData,执行最后一个控件的RaisePostBackEvent 2:hidden.Name=this.UniqueID,submit.Name=this.UniqueID 执行全部控件的LoadPostData,执行最后一个控件的RaisePostBackEvent 3:hidden.Name<>this.UniqueID,submit.Name=this.UniqueID 执行引起回传的那个控件的LoadPostData和RaisePostBackEvent方法 4:hidden.Name<>this.UniqueID,submit.Name<>this.UniqueID 不会执行任何一个控件的LoadPostData和RaisePostBackEvent方法(这个好理解,一个没有当然不行) 真不明白,要怎样设置元素的UniqueId才能达到执行所有控件的LoadPostData方法和只执行回传控件的RaisePostBackEvent方法的目的。 UniqueId是怎样影响这两个方法的执行的,我在网上查了半天资料,看了一大堆,没一个说清楚了 :confused: |
该贴我会长期顶,顶到问题解决为止。 顺便说声,的发贴题目的字数限制太小啦。。。。。。。 |
没大看明白你的意思,说一下我的理解 不知道你说的“达到执行所有控件的”和“执行回传控件的”是什么意思,按照我的理解,放在里面的两个input现在是一个控件了,你如果想分别取它们的值,可以这样做 hidden.Name=this.UniqueID,submit.Name=“another” public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { //hidden的值,这里的postDataKey和UniqueID的值是一样的 text=postCollection[postDataKey]; //another的值 text=postCollection["another"]; return false; } 2.如果想要分别让这个控件里的input触发不同的事件,可以自己定义若干事件,然后这样 public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { //hidden的值,这里的postDataKey和UniqueID的值是一样的 text=postCollection[postDataKey]; //another的值 text2=postCollection["another"]; return true; } public void RaisePostDataChangedEvent() { if(text!=null) //触发事件1 if(text2!=null) //触发事件2 } 这个我没测试过,因为现在没有时间,如果你感兴趣,可以试试 |
还有,如果要让里面的input实现自己的事件,需要实现IPostBackEventHandler接口 |
首先感谢planRED的回复 上面说得太多,可能核心问题被忽略了(这个问题可能是控件开发初学者都会遇到的一个问题) 问题主要不是从postCollection取值并在RaisePostDataChangedEvent方法里面调用不同委托,而是RaisePostDataChangedEvent和 LoadPostData这两个方法的执行问题。就是我在3楼列出来的那4种情况没有一个符合要求的(这4种情况已经是所有可能的组合了) 在说明下前提: 1。控件实现了IPostBackDataHandler和IPostBackEventHandler接口 2。假设在测试页面放了3个该控件(“执行最后一个控件的RaisePostBackEvent”就是执行页面上排最后的那个控件的RaisePostBackEvent方法,而排前面的控件的这个方法就没有执行) |
还是不明白你要问什么,每个控件都有自己的事件,你触发了最后一个的,怎么可能会让第一个起反应? |
planRED在上个帖子中说 问题就在这里了,如果点击最后一个控件确实应该执行最后一个控件的回传事件,但是我点击第一个控件,它仍然执行了最后一个控件的回传事件而没有执行它本身的回传事件。 |
为了说明方便,这里把那个控件的代码贴上,大家可以复制过去试一试:(注意下红色的吧),再建个测试页面,往上面拖三个这个控件。 using System; using System.Web.UI; using System.Web.UI.WebControls; using System.ComponentModel; namespace WebControlLibrary { /// <summary> /// TTTT 的摘要说明。 /// </summary> [DefaultProperty("Text"), ToolboxData("<{0}:TTTT runat=server></{0}:TTTT>")] public class TTTT : System.Web.UI.Control,IPostBackEventHandler,IPostBackDataHandler { protected override void Render(HtmlTextWriter writer) { writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Type,"text"); [color=red]writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Name,this.UniqueID);[/color] writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Value,""); writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Input); writer.RenderEndTag(); writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Type,"submit"); [color=red]writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Name,this.UniqueID[/color]); writer.AddAttribute(System.Web.UI.HtmlTextWriterAttribute.Value,"Click Me"); writer.RenderBeginTag(System.Web.UI.HtmlTextWriterTag.Input); writer.RenderEndTag(); } public void RaisePostBackEvent(string eventArgument) { int m = 0;//这句没什么具体作用,主要用来打断点跟踪程序的-^_^ } public void RaisePostDataChangedEvent() { // } public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) { [color=red]Page.RegisterRequiresRaiseEvent(this);//难道这句有问题?[/color] return false; } } } |