一切福田,不離方寸,從心而覓,感無不通。

Asp.net控件开发学习笔记(九)—-服务器控件事件

 

EventCollection

如果在单个控件中有多个事件,那么使用System.ComponentModel.EventHandlerList对事件进行保存将会在内存占用上有不错的提高。EventHandlerList对一个类内发布多个事件提供了一个列表容器。下面是多个事件和使用EventHandlerList的对比示意:


第一步是实例化一个EventHandlerList的实例:

protected EventHandlerList eventList = new EventHandlerList();

第二步是声明一个容器用于保存事件的key

privatestaticreadonlyobject ClickEvent = newobject();

最后一步是像往常一样声明一个事件,但有所不同的是就像属性的get和set程序块一样,对于事件C#提供了add和remove关键字:

publiceventEventHandler Click

        {

add

            {

                Events.AddHandler(ClickEvent, value);

            }

remove

            {

                Events.RemoveHandler(ClickEvent, value);

            }

      }

而在这时的事件调用方法就会像下面代码:

protectedvirtualvoid OnClick(EventArgs e)

        {

EventHandler clickEventDelegate = (EventHandler)Events[ClickEvent];

if (clickEventDelegate != null)

{

                clickEventDelegate(this, e);

            }

     }

上面代码首先从事件列表中通过索引器以第一步中保存事件的key为参数提取出事件并检查客户端是否注册到此事件,如果是,则激发事件。

 

Command事件和事件冒泡

Command事件是System.Web.UI.WebControls命名空间里的强大模式。这个最好的例子是GridView

在GridView的Row里嵌套的button点击会触发Command事件,后台可以根据CommandArgument的不同来决定是执行edit操作还是delete操作等。而事件冒泡有些像javascript里的事件冒泡,但有所不同的是这里的事件冒泡到能够处理这个事件的地方停止,比如上图中command事件会冒泡到DataGrid里的ItemCommand里停止,因为ItemCommand事件可以对command事件进行处理.

在定义Command事件时会和前面大同小异,不同之处在于首先需要一个继承与System.EventArgs的CommandEventArgs类来进行参数传递,代码如下

publicclassCommandEventArgs : EventArgs

{

public CommandEventArgs(string _commandName,string _commandArgument)

{

    CommandName=_commandName;

    CommandArgument=_commandArgument;

privatestring commandname;

privatestring commandArgument;

publicvirtualstring CommandName

        {

get

            {

return commandname;

            }

set

            {

                commandname = value;

            }

        }

publicvirtualstring CommandArgument

        {

get

            {

return commandArgument;

            }

set

            {

                commandArgument = value;

            }

        }

}

然后在需要定义的控件里定义这两个属性,代码如下:

publicvirtualstring CommandName

         {

get

            {

object name = ViewState["CommandName"];

if (name == null)

returnstring.Empty;

else

return (string)name;

            }

set

            {

                ViewState["CommandName"] = value;

            }

        }

publicvirtualstring CommandArgument

        {

get

            {

object arg = ViewState["CommandArgument"];

if (arg == null)

returnstring.Empty;

else

return (string)arg;

}

set

            {

                ViewState["CommandArgument"] = value;

            }

        }

然后重复前面的步骤,在控件内部定义命令事件:

privatestaticreadonlyobject CommandKey = newobject();

publiceventCommandEventHandler Command

        {

add

            {

                Events.AddHandler(CommandKey, value);

            }

remove

            {

                Events.RemoveHandler(CommandKey, value);

            }

        }

最后一步和前面说的引发事件的OnXXX的实现都略有不同,这里在控件内部实现的代码如下:

protectedvirtualvoid OnCommand(CommandEventArgs ce)

        {

CommandEventHandler commandEventDelegate =(CommandEventHandler)Events[CommandKey];

if (commandEventDelegate != null)

            {

                commandEventDelegate(this, ce);

            }

            RaiseBubbleEvent(this, ce);

        }

注意最后一句,RaiseBubbleEvent方法.这个方法可以将控件的事件传递到它的父容器上。

到这里很多人都会好奇,那CommandName和CommandArgument两个参数是如何传入到CommandEventArgs里去的呢?

其实是在引发事件时传入的,代码如下:

  OnCommand(new CommandEventArgs(CommandName, CommandArgument));

 

DEMO 带Command事件的Button

其实这个Demo就是把上面的代码全部拼装起来,代码可能会有点长,代码如下:

namespace DemoButton

{

[ToolboxData("<{0}:superbutton runat=server></{0}:superbutton>")]

publicclassButtonDemo : ControlIPostBackEventHandler

    {

publicdelegatevoidCommandEventHandler(object sender,CommandEventArgs e);

publicvirtualstring Text

        {

get

            {

object text = ViewState["Text"];

if (text == null)

returnstring.Empty;

else

return (string)text;

            }

set

            {

                ViewState["Text"] = value;

            }

        }

privatestaticreadonlyobject ClickKey = newobject();

publiceventEventHandler Click

        {

add

            {

                Events.AddHandler(ClickKey, value);

            }

remove

            {

                Events.RemoveHandler(ClickKey, value);

            }

        }

protectedvirtualvoid OnClick(EventArgs e)

        {

EventHandler clickEventDelegate = (EventHandler)Events[ClickKey];

if (clickEventDelegate != null)

            {

                clickEventDelegate(this, e);

            }

        }

privatestaticreadonlyobject CommandKey = newobject();

publiceventCommandEventHandler Command

        {

add

            {

                Events.AddHandler(CommandKey, value);

            }

remove

            {

                Events.RemoveHandler(CommandKey, value);

            }

        }

publicvirtualstring CommandName

        {

get

            {

object name = ViewState["CommandName"];

if (name == null)

returnstring.Empty;

else

return (string)name;

            }

set

            {

                ViewState["CommandName"] = value;

            }

        }

publicvirtualstring CommandArgument

        {

get

            {

object arg = ViewState["CommandArgument"];

if (arg == null)

returnstring.Empty;

else

return (string)arg;

            }

set

            {

                ViewState["CommandArgument"] = value;

            }

        }

protectedvirtualvoid OnCommand(CommandEventArgs ce)

        {

CommandEventHandler commandEventDelegate = (CommandEventHandler)Events[CommandKey];

if (commandEventDelegate != null)

            {

                commandEventDelegate(this, ce);

            }

            RaiseBubbleEvent(this, ce);

        }

publicvoid RaisePostBackEvent(string argument)

        {

            OnCommand(newCommandEventArgs(CommandName, CommandArgument));

//OnClick(EventArgs.Empty);

        }

protectedoverridevoid Render(HtmlTextWriter writer)

        {

base.Render(writer);

            Page.VerifyRenderingInServerForm(this);

            writer.Write("<INPUT type=""submit""");

            writer.Write(" name=""" + this.UniqueID + """");

            writer.Write(" id=""" + this.UniqueID + """");

            writer.Write(" value=""" + Text + """");

            writer.Write(" />");

        }

    }

 

publicclassCommandEventArgs : EventArgs

    {

public CommandEventArgs(string _commandName, string _commandArgument)

        {

            CommandName = _commandName;

            CommandArgument = _commandArgument;

        }

privatestring commandname;

privatestring commandArgument;

publicvirtualstring CommandName

        {

get

            {

return commandname;

            }

set

            {

                commandname = value;

            }

        }

publicvirtualstring CommandArgument

        {

get

            {

return commandArgument;

            }

set

            {

                commandArgument = value;

            }

        }

    }

}

前台代码:

首先注册页面控件:

<%@RegisterNamespace="DemoButton"TagPrefix="cc"%>

前台代码:

<cc:ButtonDemorunat="server"Text="第一个按钮"ID="bt1"CommandName="bt1"

CommandArgument="第一个button的参数"oncommand="bt1_Command"></cc:ButtonDemo>

<cc:ButtonDemorunat="server"Text="第二个按钮"ID="bt2"CommandName="bt1"

CommandArgument="第二个button的参数"oncommand="bt1_Command"></cc:ButtonDemo>

事件处理程序:

protectedvoid bt1_Command(object sender, DemoButton.CommandEventArgs e)

    {

if (e.CommandName == "bt1")

        {

            Response.Write("第一个button被点击了,参数是"+e.CommandArgument);

        }

elseif (e.CommandArgument == "bt12")

        {

            Response.Write("第二个button被点击了,参数是" + e.CommandArgument);

        }

}

 

Demo的结果很简单,就不演示了:-)

http://www.cnblogs.com/CareySon/archive/2009/10/14/1582906.html