本页面由 Flash 保存计划 从 Internet Archive 存档还原 · 快照 2004-12-09 · 原址 http://bbs.flash8.net/forums/1800994/ShowPost.aspx ← Flash 保存计划
欢迎光临 闪吧论坛 登录 | 注册 | FAQ | 搜索
Print Search
帖子排序:    
帖子发起人:czclk   发起时间:2006-02-04 02:40 上午   回复:3
czclk 离线,最后访问时间:2006-4-14 0:49:25 czclk

等级:Flash 2

等级:FLASH 2
注册:2001-08-20
发贴:212
积分:11
2006-02-04, 02:40 上午   IP 地址:已记录  报告  收藏  楼主
[原创]关于服务器控件开发中两个接口的理解

  • 好久没上闪吧了,发个原创,跟大家打个招呼!

       一般的,我们在开发.net服务器控件的时候,经常要实现两个接口,才能正常地使到这个控件正常工作。他们就是IPostBackDataHandler和IPostBackEventHandler。关于这两个接口的用法及实现原理,经常是服务器控件开发中的难点,接下来,我将通过一个实例来说明这两个接口。
        例子如下,我们将建立一个解决方案,来做这个例子,在这个例子中,我们可以看到,图中用八个小方块围起来的部分,是我们即将开发的服务器控件,这个控件主要是用来验证我们输入的密码的。但实际上,并不能真正实现修改、取回密码的功能,主要是通过这个例子来学习IPostBackDataHandler和IPostBackEventHandler接口。在控件的下方,还有三个Label控件,这三个Label控件,是用来显示服务器事件结果的。 为了保证数据的正确,我们将三个控件的Viewstate给关掉。

    Label_check用来显示两次输入密码的验证结果,如果两次输入不一致,就会出现“测试不通过”的字样。

    Label_Event是用来显示我们是否通过“忘记密码”或者“重置密码”引发了回送,并告诉是由哪个按钮引发的回送。

    Label_test是用来验证,是不是在每次回送的同时,都进行了回送数据的检测。



    按此在新窗口浏览图片screen.width-400)this.width=screen.width-400" border=0>
    首先,我们先来看看关于IPostBackDataHandler和IPostBackEventHandler接口在.net Framkwork上的介绍

    关于IPostBackDataHandler

    如果希望设计的服务器控件检查客户端回发到服务器的窗体数据,则必须实现 IPostBackDataHandler 接口。该接口定义的合同允许服务器控件确定其状态是否在回发发生后更改,并引发适当的事件。

    关于IPostBackEventHandler

    若要创建从浏览器捕获窗体提交信息的服务器控件,必须实现该接口。

    接下来,我们将通过实现这两个接口,开发一个上图中用八个小方块围起来的服务器控件

    源码如下:

    Imports System.ComponentModel
    Imports System.Web.UI

    ")> Public Class WebCustomControl2
        Inherits System.Web.UI.WebControls.WebControl
        Implements IPostBackDataHandler, IPostBackEventHandler
        '建立委托,当两次输入的密码不一致时,引发相应的服务器端程序
        Public Event InvalidPasswordConfirmation As EventHandler

        Public Event TestEventTime As EventHandler

        '建立委托,当忘记密码,要取回时,引发相应的服务器端程序

        Public Event ForgotPassword As EventHandler
        '建立委托,当要重置密码时,引发相应的服务器端程序
        Public Event ResetPassword As EventHandler

        '控件的实现
        Protected Overrides Sub Render(ByVal writer As System.Web.UI.HtmlTextWriter)
            writer.RenderBeginTag(HtmlTextWriterTag.Table)
            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.Write("Ole Password")
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            '我们需要指定这个按钮的name属性为这个控件的UniqueID,为什么要这样呢,因为如果在一个窗体上,放置有多个控件,就不知道是哪个控件引发了事件,由于控件与控件间的事件是独立的,所以,在将整个窗体回送到服务器时,就要让服务器知道,是哪个控件引发了事件,起到一个标志的作用。
            writer.Write("")
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.Write("New Password")
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            ’这个文本框与下面的一个文本框,是用来校对两次输入的密码是否一样的,那怎么在服务器端取得这个文本框的值呢?我们同样也是来设置它的name属性,而由于这个控件是动态生成的,所以,它的name属性也应该是动态生成的,因此,我们可以通过组合UniqueID与一个固定的字符串,来实现这个控件在窗体中的唯一性。通过这个组合而成的属性值,我们就可以在接下来的LoadPostData函数中,找到这个文本框回送的数值。        writer.Write("")
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.Write("Comfirm Password")
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            '这个文本框与上个文本框是用来验证密码输入的,同样的道理,也是通过组合UniqueID与一个固定的字符串,实现这个控件在窗体中的唯一性。在接下来 LoadPostData函数中,通过组合而成的属性值,找到这个文本框回送的数值,与上一个文本框进行比对。
            writer.Write("")
            writer.RenderEndTag()
            writer.RenderEndTag()
            '最后一行
            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.AddAttribute(HtmlTextWriterAttribute.Colspan, "2")
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "submit")
            writer.AddAttribute(HtmlTextWriterAttribute.value, "提交检查")
            writer.RenderBeginTag(HtmlTextWriterTag.Input)
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderEndTag()

            writer.RenderBeginTag(HtmlTextWriterTag.Tr)
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            '默认情况下,只有一部分的控件能够引发回送,那怎么样才能使到我们可以自定义地引发回送呢,就是调用Page.GetPostBackEventReference方法,这个方法有两个参数,一个是引发回送的html元素,一个是参数,这个参数有什么作用呢?当在控件中,我们要实现多个自定义的可回送机制时,就需要在服务器端判断是当前的回送,是由哪个控件来引发的(就是下面的RaisePostBackEvent方法),从而调用相应的事件。在这里,我们设置了一个button,这个button是一个html表单元素,在默认的情况下,是不能引发回送的,但如果我们给他的onClick属性,使到按下按钮时,就引发回送
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "button")
            writer.AddAttribute(HtmlTextWriterAttribute.value, "忘记密码")
            writer.AddAttribute(HtmlTextWriterAttribute.onclick, Page.GetPostBackEventReference(Me, "Forgot"))
            writer.RenderBeginTag(HtmlTextWriterTag.Input)
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderBeginTag(HtmlTextWriterTag.Td)
            writer.AddAttribute(HtmlTextWriterAttribute.Type, "button")
            writer.AddAttribute(HtmlTextWriterAttribute.value, "重置密码")
            writer.AddAttribute(HtmlTextWriterAttribute.onclick, Page.GetPostBackEventReference(Me, "Reset"))
            writer.RenderBeginTag(HtmlTextWriterTag.Input)
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderEndTag()
            writer.RenderEndTag()
        End Sub
        '这个函数是实现IPostBackDataHandler接口的,主要是通过提取回送的数据,来判断我们我浏览器中输入的两次密码是否一样,
        Public Function LoadPostData(ByVal postDataKey As String, ByVal postCollection As System.Collections.Specialized.NamevalueCollection) As Boolean Implements System.Web.UI.IPostBackDataHandler.LoadPostData
            RaiseEvent TestEventTime(Me, New System.EventArgs)
            '通过我们组合而成的name属性,获取第一个文本框里的密码
            Dim newPassword As String = CType(postCollection(Me.UniqueID & ":NewPWD"), String)
            '通过我们组合而成的name属性,获取第二个文本框里的密码
            Dim conPassword As String = CType(postCollection(Me.UniqueID & ":ComPWD"), String)
            '判断这两个数值是否一样,如果不一样,函数值返回True,并引发下面的RaisePostDataChangedEvent函数;否则返回False,
            If newPassword = conPassword Then
                Return False
            Else
                Return True
            End If
        End Function
        
        '这个方法,同样是实现IPostBackDataHandler接口的方法,如果LoadPostData返回的是True,这个方法就会被调用,通过这个方法,调用相应的事件。告诉服务器,验证失败了。
        Public Sub RaisePostDataChangedEvent() Implements System.Web.UI.IPostBackDataHandler.RaisePostDataChangedEvent
            RaiseEvent InvalidPasswordConfirmation(Me, New System.EventArgs)
        End Sub

        'RaisePostBackEvent是IPostBackEventHandler接口的函数之一,用来判断自定义引发的事件。
        Public Sub RaisePostBackEvent(ByVal eventArgument As String) Implements System.Web.UI.IPostBackEventHandler.RaisePostBackEvent
            '通过eventArgument参数,让服务器知道,是哪个按钮引发了回送,并引发相应的事件。
            If eventArgument = "Reset" Then
                RaiseEvent ResetPassword(Me, New EventArgs)
            End If
            If eventArgument = "Forgot" Then
                RaiseEvent ForgotPassword(Me, New EventArgs)
            End If
        End Sub
    End Class

    接下来,我们就可以编译这个控件,并在窗体中使用了。

        '当验证两次输入的密码不一样时,这个事件引发,在并窗体中告知客户,两次输入的结果不一样,不能通过验证
        Private Sub WebCustomControl21_InvalidPasswordConfirmation(ByVal sender As Object, ByVal e As System.EventArgs) Handles WebCustomControl21.InvalidPasswordConfirmation
            Me.Label_result.Text = "测试不通过"
        End Sub

        '当按下重置密码按钮时,这个服务器端事件将被引发
        Private Sub WebCustomControl21_ResetPassword(ByVal sender As Object, ByVal e As System.EventArgs) Handles WebCustomControl21.ResetPassword
            Me.Label_result.Text = "你使用了重置密码的功能"
        End Sub

        '当按下忘记密码按钮时,这个服务器端事件将被引发
        Private Sub WebCustomControl21_ForgotPassword(ByVal sender As Object, ByVal e As System.EventArgs) Handles WebCustomControl21.ForgotPassword
            Me.Label_result.Text = "你使用了取回密码的功能"
        End Sub

        至此,我们已经基本了解了这两个接口的含义,IPostBackDataHandler接口,主要是用来实现回送数据的验证,并引发相应的事件,可以说,它是面向数据的;而IPostBackEventHandler接口,这用来实现多个子控件可进行回送时,判断是哪个控件引发自定义回送,并调用相应的事件程序。可以立,它是面向控件的。

        然而,是不是我们在引发自定义回送同时,也有对回送数据进行验证呢,我们可以再建立一个委托,大家可以看看在这个控件定义的前部分,我们有一个委托TestEventTime,这个委托,什么时候通过这个委托调用事件程序呢?我们可以把它放在RaisePostDataChangedEvent方法中,然后引发相应的事件,告诉服务器。因为就有了下面的事件程序

        Private Sub WebCustomControl21_TestEventTime(ByVal sender As Object, ByVal e As System.EventArgs) Handles WebCustomControl21.TestEventTime
            Me.Label_test.Text = "LoadPostData过程已经被调用"
        End Sub

        运行窗体,我们可以看到,如果两次输入的密码在服务器端不一样,就会在Label_check中显示出来

    按此在新窗口浏览图片screen.width-400)this.width=screen.width-400" border=0>

        如果按下“忘记密码”或者“重置密码”,服务器端同样也能知道是哪个控件引发了回送,并调用相应的事件程序。并在Label_Event中显示出来



    按此在新窗口浏览图片screen.width-400)this.width=screen.width-400" border=0>

    按此在新窗口浏览图片screen.width-400)this.width=screen.width-400" border=0>

        而我们同时也可以看到,在按下“忘记密码”或者“重置密码”的同时,都对回送的数据进行了验证,如果看出来呢?可以从Label_test中显示出来。


    菜啊,好菜啊我
    coldstone 离线,最后访问时间:2006-5-19 22:17:23 coldstone

    等级:Flash MX


    等级:博客管理员
    头衔:河姆渡性感农民
    注册:2001-11-11
    发贴:3,895
    积分:120
    访问我的Blog
    2006-02-06, 14:54 下午   IP 地址:已记录  报告  收藏  第2楼
    Re:[原创]关于服务器控件开发中两个接口的理解

  • 如是原创但未在闪吧首发请注明首发地址。

    其实。。我是一个演员。。
    czclk 离线,最后访问时间:2006-4-14 0:49:25 czclk

    等级:Flash 2

    等级:FLASH 2
    注册:2001-08-20
    发贴:212
    积分:11
    2006-02-06, 20:13 下午   IP 地址:已记录  报告  收藏  第3楼
    Re:[原创]关于服务器控件开发中两个接口的理解

  • 哦,原来是这样,呵呵,不好意思!
    这篇文章首发是在小桥流水论坛
    地址如下:http://www.521000.com/bbs/dispbbs.asp?boardID=9&ID=148804

    菜啊,好菜啊我
    coldstone 离线,最后访问时间:2006-5-19 22:17:23 coldstone

    等级:Flash MX


    等级:博客管理员
    头衔:河姆渡性感农民
    注册:2001-11-11
    发贴:3,895
    积分:120
    访问我的Blog
    2006-02-07, 12:13 下午   IP 地址:已记录  报告  收藏  第4楼
    Re:[原创]关于服务器控件开发中两个接口的理解

  • 鼓励原创,已加分,谢谢分享。

    其实。。我是一个演员。。
    快速回复帖子

     




    标题: