为了账号安全,请及时绑定邮箱和手机立即绑定

Asp.net服务器控件事件

标签:
C#

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

https://img1.sycdn.imooc.com//5af17d5c0001468006890364.jpg


 第一步是实例化一个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

https://img1.sycdn.imooc.com//5af17d68000105f305370399.jpg   

 在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);
        }
}
点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消