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的结果很简单,就不演示了:-)

转载于:https://www.cnblogs.com/CareySon/archive/2009/10/14/1582906.html

Asp.net控件开发学习笔记(九)----服务器控件事件相关推荐

  1. 【转】Asp.net控件开发学习笔记整理篇 - WebControl基类

    最近一直在做MVC项目,对于WEBFORM 好像快忘记了.周末无聊,顺带看看他人的笔记.再次温习下. 复习大纲: 导航.页面生命周期及其它导论 一.服务器控件生命周期 二.控件开发基础 三.Asp.n ...

  2. 【转】Asp.net控件开发学习笔记整理篇 - Asp.net客户端状态管理

    最近一直在做MVC项目,对于WEBFORM 好像快忘记了.周末无聊,顺带看看他人的笔记.再次温习下. 复习大纲: 导航.页面生命周期及其它导论 一.服务器控件生命周期 二.控件开发基础 三.Asp.n ...

  3. 【转】Asp.net控件开发学习笔记整理篇 - 数据回传

    最近一直在做MVC项目,对于WEBFORM 好像快忘记了.周末无聊,顺带看看他人的笔记.再次温习下. 复习大纲: 导航.页面生命周期及其它导论 一.服务器控件生命周期 二.控件开发基础 三.Asp.n ...

  4. Asp.net控件开发学习笔记(三)-控件开发基础

    封装      在asp.net中,控件被分为两类.用户控件和自定义服务器控件.前者就是我们经常用来将一些可复用的内容封装成的.ascx文件.这里主要研究后者. 创建自定义服务器控件      创建自 ...

  5. Asp.net控件开发学习笔记(六)----数据回传

    在Asp.net中,利用Http Post的回传机制意味着可以再客户端存储状态并且可以在服务器接收.Asp.net中大部分控件都提供了存储自身状态的功能并且在自身状态改变时引发对应事件.IPostDa ...

  6. Asp.net控件开发学习笔记(四)---Asp.net服务端状态管理

    Asp.net请求处理构架 当一个客户端浏览器对IIS发起访问请求资源时(比如一个.aspx文件),Asp.net会初始化并维护一个包含了多个Response和Request的Http Session ...

  7. ActiveX 控件开发学习笔记1

    1.  char * 型的变量downloadip赋初值的时候用menset(downloadip, 0, strlen(downloadip)): cstring型的变量sourceip赋初值可用, ...

  8. 一起谈.NET技术,asp.net控件开发基础(18)

    本篇继续上篇的讨论,可能大家已经在使用asp.net2.0了,DataSource属性不再使用,而是跟数据源控件搭配使用.现在讨论的绑定技术都是基于1.1版本,先熟悉一下,本质上是一样的,这样一步步的 ...

  9. 一起谈.NET技术,asp.net控件开发基础(20)

    上面我们讨论了数据绑定控件的做法,但都未涉及到asp.net2.0中数据源控件的用法,让用惯了数据源控件的人可能感觉不适应.这次我们就开始讨论在asp.net2.0中,我们该如何重新定义数据绑定控件. ...

最新文章

  1. 嵌入式linux应用程序升级,基于嵌入式Linux平台的应用升级机制的研究与设计
  2. python opencv 旋转图片
  3. 知识点讲解八:Python中的尾递归
  4. Linux服务器Zookeeper+Dubbo环境搭建
  5. 腾讯或联姻优酷,微信嫁女模式引发互联网通婚潮流
  6. JAVA对象JSON数据互相转换的四种常见情况
  7. C++新特性探究(十七):chrono计時器
  8. 只要32万8,国产特斯拉带回家,官方:月供低至1100
  9. echart 饼图标题title的详细参数配置
  10. 宝塔面板+PM2布署nodejs
  11. Efficient polynomial commitment schemes for multiple points and polynomials学习笔记
  12. 高中数学解题方法技巧之秒杀解三角形难题(图文讲解)
  13. Type number trivially inferred from a number literal, remove type annotation.
  14. webscraper多页爬取_Web Scraper 翻页——控制链接批量抓取数据(Web Scraper 高级用法)| 简易数据分析 05...
  15. Django models常用Field介绍以及常见错误解决
  16. 计算机的最新应用有哪些内容是什么,善用Wink,将电脑操作录屏为flash (更新图片)...
  17. 基于神经网络的专家系统,清华大学认知神经科学
  18. C语言_求1到某个数之间的所有素数
  19. 高精度数字高程数据1m的dem
  20. matlab 双目 景深,双照相机景深分析的思路

热门文章

  1. 网站优化离不开内容更新
  2. 浅析SEO网站优化的三点高质量外链优化技巧
  3. mysql 数据库 限制大小_MySQL数据库表各种大小限制小结
  4. java打字母小游戏总结与收获,java:打字母小游戏demo
  5. 数据不够怎么训练深度学习模型?不妨试试迁移学习 ——重用神经网络的结构2...
  6. win7 cmd执行vue不是内部命令解决办法
  7. 2019春第一次课程设计实验报告
  8. 网络编程- 解决黏包现象方案一(六)
  9. MySQL安装时MySQL server一直安装失败日志显示This application requires Visual Studio 2013 Redistributable...
  10. 重载[] int operator[ ]( )