Asp.net控件开发学习笔记(九)----服务器控件事件
2013-11-05 14:28
751 查看
EventCollection
如果在单个控件中有多个事件,那么使用System.ComponentModel.EventHandlerList对事件进行保存将会在内存占用上有不错的提高。EventHandlerList对一个类内发布多个事件提供了一个列表容器。下面是多个事件和使用EventHandlerList的对比示意:
第一步是实例化一个EventHandlerList的实例:
protected EventHandlerList
eventList = new EventHandlerList();
第二步是声明一个容器用于保存事件的key
private static readonly object ClickEvent
= new object();
最后一步是像往常一样声明一个事件,但有所不同的是就像属性的get和set程序块一样,对于事件C#提供了add和remove关键字:
public event EventHandler Click
{
add
{
Events.AddHandler(ClickEvent, value);
}
remove
{
Events.RemoveHandler(ClickEvent, value);
}
}
而在这时的事件调用方法就会像下面代码:
protected virtual void 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类来进行参数传递,代码如下
public class CommandEventArgs : EventArgs
{
public CommandEventArgs(string
_commandName,string _commandArgument)
{
CommandName=_commandName;
CommandArgument=_commandArgument;
}
private string commandname;
private string commandArgument;
public virtual string CommandName
{
get
{
return commandname;
}
set
{
commandname = value;
}
}
public virtual string CommandArgument
{
get
{
return commandArgument;
}
set
{
commandArgument = value;
}
}
}
然后在需要定义的控件里定义这两个属性,代码如下:
public virtual string CommandName
{
get
{
object name
= ViewState["CommandName"];
if (name
== null)
return string.Empty;
else
return (string)name;
}
set
{
ViewState["CommandName"]
= value;
}
}
public virtual string CommandArgument
{
get
{
object arg
= ViewState["CommandArgument"];
if (arg
== null)
return string.Empty;
else
return (string)arg;
}
set
{
ViewState["CommandArgument"]
= value;
}
}
然后重复前面的步骤,在控件内部定义命令事件:
private static readonly object CommandKey
= new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(CommandKey, value);
}
remove
{
Events.RemoveHandler(CommandKey, value);
}
}
最后一步和前面说的引发事件的OnXXX的实现都略有不同,这里在控件内部实现的代码如下:
protected virtual void 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>")]
public class ButtonDemo : Control, IPostBackEventHandler
{
public delegate void CommandEventHandler(object sender,CommandEventArgs e);
public virtual string Text
{
get
{
object text
= ViewState["Text"];
if (text
== null)
return string.Empty;
else
return (string)text;
}
set
{
ViewState["Text"]
= value;
}
}
private static readonly object ClickKey
= new object();
public event EventHandler Click
{
add
{
Events.AddHandler(ClickKey, value);
}
remove
{
Events.RemoveHandler(ClickKey, value);
}
}
protected virtual void OnClick(EventArgs e)
{
EventHandler clickEventDelegate
= (EventHandler)Events[ClickKey];
if (clickEventDelegate
!= null)
{
clickEventDelegate(this,
e);
}
}
private static readonly object CommandKey
= new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(CommandKey, value);
}
remove
{
Events.RemoveHandler(CommandKey, value);
}
}
public virtual string CommandName
{
get
{
object name
= ViewState["CommandName"];
if (name
== null)
return string.Empty;
else
return (string)name;
}
set
{
ViewState["CommandName"]
= value;
}
}
public virtual string CommandArgument
{
get
{
object arg
= ViewState["CommandArgument"];
if (arg
== null)
return string.Empty;
else
return (string)arg;
}
set
{
ViewState["CommandArgument"]
= value;
}
}
protected virtual void OnCommand(CommandEventArgs ce)
{
CommandEventHandler commandEventDelegate
= (CommandEventHandler)Events[CommandKey];
if (commandEventDelegate
!= null)
{
commandEventDelegate(this,
ce);
}
RaiseBubbleEvent(this,
ce);
}
public void RaisePostBackEvent(string argument)
{
OnCommand(new CommandEventArgs(CommandName,
CommandArgument));
//OnClick(EventArgs.Empty);
}
protected override void 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("
/>");
}
}
public class CommandEventArgs : EventArgs
{
public CommandEventArgs(string _commandName, string _commandArgument)
{
CommandName = _commandName;
CommandArgument = _commandArgument;
}
private string commandname;
private string commandArgument;
public virtual string CommandName
{
get
{
return commandname;
}
set
{
commandname = value;
}
}
public virtual string CommandArgument
{
get
{
return commandArgument;
}
set
{
commandArgument = value;
}
}
}
}
前台代码:
首先注册页面控件:
<%@ Register Namespace="DemoButton" TagPrefix="cc" %>
前台代码:
<cc:ButtonDemo runat="server" Text="第一个按钮" ID="bt1" CommandName="bt1"
CommandArgument="第一个button的参数" oncommand="bt1_Command" ></cc:ButtonDemo>
<cc:ButtonDemo runat="server" Text="第二个按钮" ID="bt2" CommandName="bt1"
CommandArgument="第二个button的参数" oncommand="bt1_Command" ></cc:ButtonDemo>
事件处理程序:
protected void bt1_Command(object sender,
DemoButton.CommandEventArgs e)
{
if (e.CommandName
== "bt1")
{
Response.Write("第一个button被点击了,参数是"+e.CommandArgument);
}
else if (e.CommandArgument
== "bt12")
{
Response.Write("第二个button被点击了,参数是" +
e.CommandArgument);
}
}
Demo的结果很简单,就不演示了:-)
如果在单个控件中有多个事件,那么使用System.ComponentModel.EventHandlerList对事件进行保存将会在内存占用上有不错的提高。EventHandlerList对一个类内发布多个事件提供了一个列表容器。下面是多个事件和使用EventHandlerList的对比示意:
第一步是实例化一个EventHandlerList的实例:
protected EventHandlerList
eventList = new EventHandlerList();
第二步是声明一个容器用于保存事件的key
private static readonly object ClickEvent
= new object();
最后一步是像往常一样声明一个事件,但有所不同的是就像属性的get和set程序块一样,对于事件C#提供了add和remove关键字:
public event EventHandler Click
{
add
{
Events.AddHandler(ClickEvent, value);
}
remove
{
Events.RemoveHandler(ClickEvent, value);
}
}
而在这时的事件调用方法就会像下面代码:
protected virtual void 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类来进行参数传递,代码如下
public class CommandEventArgs : EventArgs
{
public CommandEventArgs(string
_commandName,string _commandArgument)
{
CommandName=_commandName;
CommandArgument=_commandArgument;
}
private string commandname;
private string commandArgument;
public virtual string CommandName
{
get
{
return commandname;
}
set
{
commandname = value;
}
}
public virtual string CommandArgument
{
get
{
return commandArgument;
}
set
{
commandArgument = value;
}
}
}
然后在需要定义的控件里定义这两个属性,代码如下:
public virtual string CommandName
{
get
{
object name
= ViewState["CommandName"];
if (name
== null)
return string.Empty;
else
return (string)name;
}
set
{
ViewState["CommandName"]
= value;
}
}
public virtual string CommandArgument
{
get
{
object arg
= ViewState["CommandArgument"];
if (arg
== null)
return string.Empty;
else
return (string)arg;
}
set
{
ViewState["CommandArgument"]
= value;
}
}
然后重复前面的步骤,在控件内部定义命令事件:
private static readonly object CommandKey
= new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(CommandKey, value);
}
remove
{
Events.RemoveHandler(CommandKey, value);
}
}
最后一步和前面说的引发事件的OnXXX的实现都略有不同,这里在控件内部实现的代码如下:
protected virtual void 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>")]
public class ButtonDemo : Control, IPostBackEventHandler
{
public delegate void CommandEventHandler(object sender,CommandEventArgs e);
public virtual string Text
{
get
{
object text
= ViewState["Text"];
if (text
== null)
return string.Empty;
else
return (string)text;
}
set
{
ViewState["Text"]
= value;
}
}
private static readonly object ClickKey
= new object();
public event EventHandler Click
{
add
{
Events.AddHandler(ClickKey, value);
}
remove
{
Events.RemoveHandler(ClickKey, value);
}
}
protected virtual void OnClick(EventArgs e)
{
EventHandler clickEventDelegate
= (EventHandler)Events[ClickKey];
if (clickEventDelegate
!= null)
{
clickEventDelegate(this,
e);
}
}
private static readonly object CommandKey
= new object();
public event CommandEventHandler Command
{
add
{
Events.AddHandler(CommandKey, value);
}
remove
{
Events.RemoveHandler(CommandKey, value);
}
}
public virtual string CommandName
{
get
{
object name
= ViewState["CommandName"];
if (name
== null)
return string.Empty;
else
return (string)name;
}
set
{
ViewState["CommandName"]
= value;
}
}
public virtual string CommandArgument
{
get
{
object arg
= ViewState["CommandArgument"];
if (arg
== null)
return string.Empty;
else
return (string)arg;
}
set
{
ViewState["CommandArgument"]
= value;
}
}
protected virtual void OnCommand(CommandEventArgs ce)
{
CommandEventHandler commandEventDelegate
= (CommandEventHandler)Events[CommandKey];
if (commandEventDelegate
!= null)
{
commandEventDelegate(this,
ce);
}
RaiseBubbleEvent(this,
ce);
}
public void RaisePostBackEvent(string argument)
{
OnCommand(new CommandEventArgs(CommandName,
CommandArgument));
//OnClick(EventArgs.Empty);
}
protected override void 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("
/>");
}
}
public class CommandEventArgs : EventArgs
{
public CommandEventArgs(string _commandName, string _commandArgument)
{
CommandName = _commandName;
CommandArgument = _commandArgument;
}
private string commandname;
private string commandArgument;
public virtual string CommandName
{
get
{
return commandname;
}
set
{
commandname = value;
}
}
public virtual string CommandArgument
{
get
{
return commandArgument;
}
set
{
commandArgument = value;
}
}
}
}
前台代码:
首先注册页面控件:
<%@ Register Namespace="DemoButton" TagPrefix="cc" %>
前台代码:
<cc:ButtonDemo runat="server" Text="第一个按钮" ID="bt1" CommandName="bt1"
CommandArgument="第一个button的参数" oncommand="bt1_Command" ></cc:ButtonDemo>
<cc:ButtonDemo runat="server" Text="第二个按钮" ID="bt2" CommandName="bt1"
CommandArgument="第二个button的参数" oncommand="bt1_Command" ></cc:ButtonDemo>
事件处理程序:
protected void bt1_Command(object sender,
DemoButton.CommandEventArgs e)
{
if (e.CommandName
== "bt1")
{
Response.Write("第一个button被点击了,参数是"+e.CommandArgument);
}
else if (e.CommandArgument
== "bt12")
{
Response.Write("第二个button被点击了,参数是" +
e.CommandArgument);
}
}
Demo的结果很简单,就不演示了:-)
相关文章推荐
- Asp.net控件开发学习笔记(八)----服务器控件事件
- Asp.net控件开发学习笔记(九)----服务器控件事件
- 【转】Asp.net控件开发学习笔记整理篇 - 服务器控件事件
- Asp.net控件开发学习笔记(八)----服务器控件事件
- Asp.net控件开发学习笔记(十一)----服务器控件模板
- 【转】Asp.net控件开发学习笔记整理篇 - 服务器控件生命周期
- Asp.net控件开发学习笔记(十一)----服务器控件模板
- Asp.net控件开发学习笔记(十)----服务器控件生命周期
- Asp.net控件开发学习笔记整理篇 - 复习大纲
- ASP.NET控件开发学习笔记--第6回 ViewState
- [ASP.NET学习笔记] 控件事件
- Asp.net控件开发学习笔记(五)---Asp.net客户端状态管理
- ASP.Net WebForm学习笔记:一、aspx与服务器控件探秘
- Asp.net控件开发学习笔记(三)-控件开发基础
- ASP.Net WebForm学习笔记:一、aspx与服务器控件探秘
- ASP.NET控件开发学习笔记--第7回 从WebControl继承
- Asp.net控件开发学习笔记(十二)----数据绑定
- 《纵向切入ASP.NET 3.5控件和组件开发技术》笔记:高效率事件集合对象
- ASP.NET 3.5核心编程学习笔记(4):服务器控件简介
- 学习笔记:ASP.NET TextBox 服务器控件源码