ASP.NET中实现定制自己的委托和事件参数类

本文实例讲述了ASP.NET中实现定制自己的委托和事件参数类的方法,对于学习ASP.NET有很好的参考借鉴价值。具体方法如下:

一般在实际开发中,对于事件不需要传递数据信息时,像上面的KingTextBox控件的事件,在引发事件时传递的参数为EventArgs.Empty,如下所示:

OnTextChanged(EventArgs.Empty);

这是因为控件KingTextBox的TextChanged事件比较简单,这里不需要参数对象传递数据。但像一些复杂的控件比如GridView的按钮命令事件,必须得有参数命令表示单击了哪个按钮;翻页事件,需要EventArgs参数对象把当前页信息传递到页面后台代码的事件体的第二个参数中,然后开发人员根据此页参数从数据库取得对应页的数据;还有像ItemDataBound事件,也需要把当前Row信息和索引等数据作为EventArgs参数传递到事件实例中。

当遇到以上这些情况,我们就需要定义自己的事件参数类和委托,而不使用默认的System.EventArgs类。下面就以Grid控件的翻页功能说明一下定义事件参数类和委托的方法,请看以下代码:

/// <summary>
///
/// </summary>
public delegate void GridPageChangedEventHandler(object source, GridPage ChangedEventArgs e);
public class GridPageChangedEventArgs : System.EventArgs
{
  public GridPageChangedEventArgs()
  {
  }

  private int intCurrentPageIndex;
  public new int CurrentPageIndex
  {
    get { return intCurrentPageIndex; }
    set { intCurrentPageIndex = value; }
  }

  private int intPageCount;
  public new int PageCount
  {
    get { return intPageCount; }
    set { intPageCount = value; }
  }

  private int intPageSize;
  public new int PageSize
  {
    get { return intPageSize; }
    set { intPageSize = value; }
  }
}

以上代码定义了一个存储翻页相关信息的参数类,此参数类派生于System.EventArgs类,在这里系统不强制要求一定继承于该类,不继承它也是可以的,但继承于该类有一点好处。先看一下System.EventArgs基类的代码:

/// <summary>
///
/// </summary>
public class EventArgs
{
  //表示没有事件数据的事件
  public static readonly EventArgs Empty;
  //初始化 System.EventArgs 类的新实例
  public EventArgs();
}

EventArgs中除了一个构造方法外,还有一个它本身类型的Empty属性,从这里可以知道前面在调用时通过OnTextChanged(EventArgs.Empty);格式,把EventArgs.Empty作为空参数传入事件引发方法时的用途了。这里要说明的是如果我们的GridPageChangedEventArgs类是从EventArgs继承而来,则不但可以传递GridPageChangedEventArgs类对象,而且可以使用GridPageChangedEventArgs.Empty的形式传递空参数对象。

在GridPageChangedEventArgs方法体中定义了一些属性;分别表示当前页(CurrentPageIndex)、页总数(PageCount)和页尺寸(PageSize)。这些都是我们自定义的页信息数据。

代码中的这句:

public delegate void GridPageChangedEventHandler(object source, GridPage ChangedEventArgs e);

定义了一个委托GridPageChangedEventHandler。该委托可以指定这样的一个事件方法:第一个参数为object类型,第二个参数即为上面我们定义的页参数类对象GridPageChanged EventArgs。在注册事件时,该委托可以保证在页面后面代码中自动产生的事件体的两个参数类型与自己的两个参数类型一致。下面是在页面中注册的事件后台代码:

protected void Grid1_PageIndexChanged(object source,GridPageChangedEventArgs e)
{
  int intCurrentPageIndex = e.CurrentPageIndex;
  int intPageSize = e.PageSize;
  //获取数据逻辑
}

可以看到第二个参数类型即我们定义的GridDocPageChangedEventArgs类型,在事件方法体中,可以直接通过e.CurrentPageIndex和e.PageSize获取数据,这种应用就比较多了。
现在页参数对象和委托定义好了,下面说一下在主控件内部是如何应用它们的。声明事件代码如下:

/// <summary>
///
/// </summary>
private new static readonly object EventPageIndexChanged = new object();
[Category("Action"), Description("翻页事件")]
public event GridPageChangedEventHandler PageIndexChanged
{
  add
  {
    base.Events.AddHandler(Grid.EventPageIndexChanged, value);
  }
  remove
  {
    base.Events.RemoveHandler(Grid.EventPageIndexChanged, value);
  }
}

这里继续采用高效率事件集合列表对象base.Events,事件的名称为PageIndexChanged,委托类型为之前我们定义的委托类型GridPageChangedEventHandler。
引发事件的核心代码如下:

/// <summary>
///
/// </summary>
protected override bool OnBubbleEvent(object source, EventArgs e)
{
  bool handled = false;
  if (e is GridCommandEventArgs)
  {
    if ((((GridCommandEventArgs)(e)).CommandSource) is LinkButton)
    {
      LinkButton lb=((LinkButton)(((GridCommandEventArgs)(e)). Command Source));
      if (lb.CommandName == "Page")
      {
        if (lb.CommandArgument == "ButtonFirst")
        {
          GridPageChangedEventArgs ee = new GridPageChangedEventArgs();
          if (this.CurrentPageIndex != 0)
          {
            this.CurrentPageIndex = 0;
            ee.CurrentPageIndex = this.CurrentPageIndex;
            ee.PageCount = this.PageCount;
            ee.PageSize = this.PageSize;
            this.OnPageIndexChanged(ee);
          }
          handled = true;
        }

        if (lb.CommandArgument == "ButtonNext")
        {
          GridPageChangedEventArgs ee = new GridPageChangedEventArgs();
          if (this.CurrentPageIndex < this.PageCount - 1)
          {
            this.CurrentPageIndex += 1;
            ee.CurrentPageIndex = this.CurrentPageIndex;
            ee.PageCount = this.PageCount;
            ee.PageSize = this.PageSize;
            this.OnPageIndexChanged(ee);
          }
          handled = true;
        }

        if (lb.CommandArgument == "ButtonPrev")
        {
          GridPageChangedEventArgs ee = new GridPageChangedEventArgs();
          if (this.CurrentPageIndex > 0)
          {
            this.CurrentPageIndex -= 1;
            ee.CurrentPageIndex = this.CurrentPageIndex;
            ee.PageCount = this.PageCount;
            ee.PageSize = this.PageSize;
            this.OnPageIndexChanged(ee);
          }
          handled = true;
        }

        if (lb.CommandArgument == "ButtonLast")
        {
          GridPageChangedEventArgs ee = new GridPageChangedEventArgs();
          if (this.CurrentPageIndex != this.PageCount - 1)
          {
            this.CurrentPageIndex = this.PageCount - 1;
            ee.CurrentPageIndex = this.CurrentPageIndex;
            ee.PageCount = this.PageCount;
            ee.PageSize = this.PageSize;
            this.OnPageIndexChanged(ee);
          }
          handled = true;
        }
      }
    }
  }
  return handled || base.OnBubbleEvent(source, e);
}

以上OnBubbleEvent方法主要应用于复合控件中,采用冒泡形式处理子控件事件,后面介绍复合控件冒泡处理事件机制时再详细讲解此方法。另外,在控件的翻页栏中预先放置了四个翻页功能的按钮,分别表示“首页”、“上一页”、“下一页”、“末页”,并设置它们的属性CommandName都为“Page”,CommandArgument分别为“ButtonFirst”,“ButtonPrev”,“ButtonNext”,“ButtonLast”。
这样就可以根据按钮的命令和参数确定执行什么样的逻辑。这里仅拿按钮“下一页”(Command="Page"&&CommandArgument="ButtonNext")为例解释一下代码逻辑:

/// <summary>
///
/// </summary>
if (lb.CommandArgument == "ButtonNext")
{
    GridPageChangedEventArgs ee = new GridPageChangedEventArgs();
    if (this.CurrentPageIndex < this.PageCount - 1)
    {
      this.CurrentPageIndex += 1;
      ee.CurrentPageIndex = this.CurrentPageIndex;
      ee.PageCount = this.PageCount;
      ee.PageSize = this.PageSize;
      this.OnPageIndexChanged(ee);
    }
    handled = true;
}

代码中首先定义一个页参数类对象,然后通过条件语句判断当前是否是最后一页,如果不是最后一页,则从主控件上读取当前页信息(当前页、页数、页记录数),并赋值给GridPageChangedEventArgs对象,然后以页参数对象作为参数调用this.OnPageIndexChanged方法引发事件。另外,注意LinkButton的CommandName和CommandArgument属性的组合用法。
最后,看一下OnPageIndexChanged方法代码:

/// <summary>
/// </summary>
protected new void OnPageIndexChanged(GridPageChangedEventArgs e)
{
  GridPageChangedEventHandler handler1 = (GridPageChangedEventHandler)base. Events[Grid.EventPageIndexChanged];
  if (handler1 != null)
  {
    handler1(this, e);
  }
}

此方法的功能是从base.Events对象中取出以Grid.EventPageIndexChanged为Key的事件引用句柄,假如句柄不为null(开发人员注册了翻页事件),则引发事件方法体。
最后,说明非常重要的一点:如果自定义了事件参数类,并要求在开发人员注册的事件体中自动显示改变参数对象的类型,如:

protected void Grid1_PageIndexChanged(object source, GridPageChangedEventArgs e)
{
  //… …
}

其中的第二个参数显示为GridPageChangedEventArgs类型,而不是默认的EventArgs类型,我们也必须定义自己的委托(如本例定义了委托GridPageChangedEventHandler);而默认的委托EventHandler对应的参数类型为基类System.EventArgs,即如果这里将默认的委托EventHandler和GridPageChangedEventArgs类一起使用的话,则生成以下的代码语句:

protected void Grid1_PageIndexChanged(object source, EventArgs e)
{
  //… …
}

可以看出参数变为EventArgs类型了。这样就不能利用我们自己定义的GridPage ChangedEventArgs类中的数据了。虽然可以使用(GridPageChangedEventArgs)EventArgs的方式转换一下也可以取得GridPageChangedEventArgs对象中的数据,但据笔者了解还没有开发人员这么用,因为没有人知道还有个GridPageChangedEventArgs类。

本文主要讲解如何定制自己的参数类和委托,并以Grid的分页功能为例演示其在实际开发中的应用。

感兴趣的读者可以参考本文所述调试运行本文示例,相信会有新的收获。

(0)

相关推荐

  • ASP.NET页面按钮单击事件失效的解决方法

    今天,再次运行以前的项目时,发现按钮的单击事件不起作用了,加了断点之后发现根本没有触发该事件.... 按照网上找到的答案,有的说把控件删掉重新拖拽一个进去,虽然以前也遇到过控件失效,重新拖拽有效的时候,但这次没有起作用. 而后,继续寻找答案,有的说可能是form嵌套,可是查看源代码没有这个问题. 无意中,尝试在按钮中加了一个客户端单击事件: 复制代码 代码如下: OnClientClick="return true" 竟然有效了: 复制代码 代码如下: <asp:ImageBut

  • asp.net页面触发事件panel滚动条高度不变的实现方法

    此文是为解决asp.net页面按钮点击触发事件后panel滚动条非自动回到顶端的解决方案,对于页面触发一个事件后,panel滚动条重新回到顶端,做下面的工作每次都要往下拉一下,特别是选择TreeView的时候,这个问题非常头疼,受到this.MaintainScrollPositionOnPostBack = true;的启示有感而发. 原理是在点击时保存panel滚动条的位置,页面触发事件完成后加载时重新赋值.保证页面每次点击都保存,就包含所有的按钮和别的点击事件. 步骤: 1.脚本 <hea

  • 详解ASP.NET页面生命周期事件

    下面是ASP.NET页面初始的过程:1. Page_Init();2. Load ViewState;3. Load Postback data;4. Page_Load();5. Handle control events;6. Page_PreRender();7. Page_Render();8. Unload event;9. Dispose method called; 下面对其中的一些过程作下描述:1. Page_Init();这个过程主要是初始化控件,每次页面载入执行这个初始过程,

  • Asp.net TextBox的TextChanged事件使用介绍

    在博客园里有位兄弟问了我一个问题,动态创建的控件是如何加载视图状态,还提到ProcessPostData方法的调用.这里我就用TextBox的TextChanged事件来说说视图数据的加载以及事件的触发. 我们首先还是来看一个demo吧: 代码如下: 运行结果如图: 现在我们来修改文本框的值,然后点击按钮提交页面,看看有什么事情发生 TextBox的TextChanged事件这时候发生了,运行结果如图: 现在我们什么也不做,再次点击按钮提交,看看会有什么效果: 这是为什么了,TextBox的Te

  • asp.net中c#自定义事件的实现方法详解

    本文实例讲述了asp.net中c#自定义事件的实现方法.分享给大家供大家参考.具体分析如下: c#自定义事件分为六步,声明关于事件的委托,声明事件,编写引发事件的函数,事件处理,这里我们就来具体的介绍一下. C#自定义事件的具体实现步骤如下: 1.声明一个delegate: (用于事件的类型的定义) 如: 复制代码 代码如下: public delegate void 事件名称EventHandler(object serder, EventArgs e); 事件名称用你的自己的来代替,随后的E

  • ASP.NET的事件模型(很适合学习的文章)

    在Default.aspx的页面中第一行是一条页面指令: <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="AspxEventsModel._Default" %> 其中CodeBehind属性指定代码隐藏页面的名称,Inherits指定所属的命名空间和类,AutoEventWireup属性是可以

  • Asp.net 图片文件防盗链(尊重劳动成果)及BeginRequest事件学习

    关于图片盗链这个问题,毕竟是自己的劳动成功,很多人不希望别人就那么轻易地偷走了. 这个功能在很多的论坛上都具有,可能是因为盗链的行为太多了吧 反盗链的程序其实很简单,熟悉ASP.NET 应用程序生命周期的话很容易就可以写一个,运用HttpModule在BeginRequest事件中拦截请求就ok了,剩下的工作就是过滤,再过滤! 如果不熟悉HttpModule的话,可以去MSDN上查阅,介绍非常详细,地址:ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStu

  • ASP.NET 页面事件执行顺序介绍

    复制代码 代码如下: #region 控件事件 第六步 protected void Button1_Click(object sender, EventArgs e) { //用这些事件来处理特定控件事件,如 Button 控件的 Click 事件或 TextBox 控件的 TextChanged 事件. //注意 //在回发请求中,如果页包含验证程序控件,请在执行任何处理之前检查 Page 和各个验证控件的 IsValid 属性. } #endregion #region OnLoadCom

  • Asp.Net 不同的OnClick事件区别小结(onserverclick,onclientclick)

    1. HTML控件,如IMG的输入按钮等 的 onclick ( 客户端 )和 onserverclick( 服务端 )事件,注意 runat="server"... 此处的onclick先于onserverclick执行.2.WEB控件,如<asp:button 按钮等 的 onclientclick( 客户端 ) 和 onclick ( 服务端 )事件... 此处的onclientclick先于onclick执行.onclientclick  事件来自2.0, 它用来取代下列

  • asp.net错误捕获(错误处理)page_error事件使用方法

    ASP.NET 提供了三种用于在出现错误时捕获和响应错误的主要方法:page_error事件.application_error 事件以及应用程序配置文件 (Web.config). 这三种方法的主要作用无非是创建自定义的错误报告,创建自定义错误报告的作用无非是:出于安全方面的考虑,还有就是为了向用户展示友好的错误页面,提高程序的友好性. Page_Error 事件,现举例说明如下: 此示例在浏览器中显示了详细的错误信息,提供此示例只是为了进行说明.向应用程序的最终用户展示出错的详细信息是非常危

  • ASP.NET中事件如何依次发生?

    本文通过实战的方法简单介绍ASP.NET中的事件执行顺序. 方法/步骤 新建C# WebForm项目,如下图: 在Defualt.aspx文件中添加一个Button控件并命名为Button1,然后为该控件各个事件添加事件处理程序,并添加断点,如下图: 打开Global.asax文件并添加断点,如下图: 打开Site.Master的代码文件Site.Master.cs,并添加断点,如下图: 按F5调试运行,查看代码运行顺序:Application_Start→Session_Start→Butto

  • asp.net在事件中启动线程来打开一个页面的实现方法

    在页面点击一个按钮,其目的是在按钮中做两件事情,一件需要点击按钮马上完成,另一件事情是点击按钮后做其他事情.如果按顺序一次做完感觉特别耗时,下面简单罗列一下. protected void Button1_Click(object sender, EventArgs e) { Label1.Text = TextBox1.Text; //在这做第一件事情 dowork(); //做完后马上启动线程 System.Threading.Thread thread = new System.Threa

  • php 模拟 asp.net webFrom 按钮提交事件的思路及代码

    由于公司需要php方面的项目开发,php刚刚入门,在写按钮提交过程中,asp.net里的按钮事件更好些.先看下面的代码, 复制代码 代码如下: <?require_once '../inc/EventHelper.php'; function Page_Load(){    echo '在任何时候都会运行<br>'; if(!Page::IsPostBack())    {        echo '加载产品分类<br>';        if($_GET['cmd']=='

  • asp.net错误处理Application_Error事件示例

    ASP.NET错误处理方法Application_Error事件举例如下: 新建web程序--新建AppEvent.aspx页面--在该页面中添加如下代码: 复制代码 代码如下: <SCRIPT language=C# runat="server">void Page_Load(object sender, System.EventArgs e){throw(new ArgumentNullException());}</SCRIPT> 然后呢,将Applica

随机推荐