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

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


本文转自CareySon博客园博客,原文链接:http://www.cnblogs.com/CareySon/archive/2009/10/14/1582906.html,如需转载请自行联系原作者
相关文章
|
21天前
|
消息中间件 网络协议 Java
【消息队列开发】 实现BrokerServer类——本体服务器
【消息队列开发】 实现BrokerServer类——本体服务器
|
10天前
|
开发框架 前端开发 .NET
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
集成于VS 2019,EXT.NET前端和ASP.NET后端,搭配MSSQL 2018数据库。系统覆盖样品管理、数据分析、报表和项目管理等实验室全流程。应用广泛,包括生产质检(如石化、制药)、环保监测、试验研究等领域。随着技术发展,现代LIMS还融合了临床、电子实验室笔记本和SaaS等功能,以满足复杂多样的实验室管理需求。
20 3
LIMS(实验室)信息管理系统源码、有哪些应用领域?采用C# ASP.NET dotnet 3.5 开发的一套实验室信息系统源码
|
2天前
|
前端开发 安全 Java
Java服务器端开发实战:利用Servlet和JSP构建动态网站
【6月更文挑战第23天】**Servlet和JSP在Java Web开发中扮演关键角色。Servlet处理业务逻辑,管理会话,JSP则结合HTML生成动态页面。两者协同工作,形成动态网站的核心。通过Servlet的doGet()方法响应请求,JSP利用嵌入式Java代码创建动态内容。实战中,Servlet处理数据后转发给JSP展示,共同构建高效、稳定的网站。虽然新技术涌现,Servlet与JSP仍为Java Web开发的基石,提供灵活且成熟的解决方案。**
|
2天前
|
存储 缓存 安全
Servlet与JSP在Java服务器端开发中的实践与优化
【6月更文挑战第23天】本文探讨了Java中Servlet与JSP在在线书店系统开发中的应用,强调了它们在动态网站构建和Web效率中的作用。通过实例,展示了Servlet如何作为控制器处理用户登录,JSP则利用EL表达式呈现数据。此外,文章提及了性能优化如分页和缓存,以及安全措施如防止SQL注入和XSS攻击,强调了全面掌握和应用这些技术的重要性,以创建高效、安全的Web应用。
|
3天前
|
前端开发 测试技术 C#
如何开发一套基于C#和.NET 6.0手术麻醉系统? 手术麻醉系统源码
如何开发一套基于C#和.NET 6.0手术麻醉系统?
12 1
|
20天前
|
开发框架 JavaScript 前端开发
分享7个.NET开源、功能强大的快速开发框架
分享7个.NET开源、功能强大的快速开发框架
|
27天前
|
开发框架 .NET C#
使用C#进行.NET框架开发:深入探索与实战
【5月更文挑战第28天】本文探讨了C#在.NET框架中的应用,展示了其作为强大编程语言的特性,如类型安全、面向对象编程。C#与.NET框架的结合,提供了一站式的开发环境,支持跨平台应用。文中介绍了C#的基础知识,如数据类型、控制结构和面向对象编程,以及.NET的关键技术,包括LINQ、ASP.NET和WPF。通过一个实战案例,展示了如何使用C#和ASP.NET开发Web应用,包括项目创建、数据库设计、模型和控制器编写,以及视图和路由配置。本文旨在揭示C#在.NET开发中的深度和广度,激发开发者探索更多可能性。
|
21天前
|
移动开发 HTML5
详解 HTML5 服务器发送事件(Server-Sent Events)
详解 HTML5 服务器发送事件(Server-Sent Events)
23 0
|
27天前
|
开发框架 NoSQL .NET
记一次asp.net 8 服务器爆满的解决过程
该文档描述了一次服务器性能问题及其解决方案。配置包括1台2c4g CentOS服务器作为API反代,1台8c16g Windows 2019服务器运行IIS、SQL Server、MongoDB和Redis。服务器处理数据导入和用户查询,使用Asp.net core、easycaching、freesql和redis技术。问题是在晚上10点后,CPU占用率飙升,特别是MongoDB,导致数据处理延迟。解决方案包括优化导入流程、关闭MongoDB的WriteConcern、添加ResponseCache、关闭Nginx日志、限制Nginx速率及排查出前端代码错误导致的自我DDoS。
|
4天前
|
存储 弹性计算 Linux
阿里云账号注册、完成实名认证、试用云服务器和购买云服务器流程参考
本文为大家介绍新手用户从注册阿里云账号,完成实名认证,然后试用云服务器和购买云服务器的主要流程,适合初次购买和试用阿里云服务器的新手用户参考。
阿里云账号注册、完成实名认证、试用云服务器和购买云服务器流程参考