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

  本文笔记选自《庖丁解牛:纵向切入ASP.NET 3.5控件和组件开发技术》一书

一般在实际开发中,对于事件不需要传递数据信息时,像上面的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);
    }
}
这里继续采用5.3.1小节讲的高效率事件集合列表对象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>
/// 获得本书更多内容,请看:
/// http://blog.csdn.net/ChengKing/archive/2008/08/18/2792440.aspx
/// </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的分页功能为例演示其在实际开发中的应用。下一节开始讲解复合控件的事件机制。

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

时间: 2024-10-06 02:59:35

ASP.NET中定制自己的委托和事件参数类的相关文章

asp.net中通过单例保存全局参数

摘要 有这样一个service,需要运行的asp.net站点上,但要保证这个示例是唯一的.这时候就想到使用单例了. Demo 单例类 using System; using System.Collections.Generic; using System.Linq; using System.Web; namespace Wolfy.SingleDemo.Models { public class SingleParameter { private static SingleParameter

4.1.6EventHandler自定义事件参数类

需要两个参数 this 高考 ------ 三种方法都可以 激发事件 __________________________ 第二版 第三版 推拉模式 e 是推过来的   sender 是拉过来的 -------------- 第四版 第五版 第六版 <>  泛型的应用 把原来的EventArgs弱类型固化成 放榜Args 强类型 事件是特殊的委托 委托是主动去调用 事件是经过事件源激发 事件只能用 += 事件只能由内部激发,外部激发不了 委托里面外面都可以激发 小结 作业

ASP.NET中常用的几个李天平开源公共类LTP.Common,Maticsoft.DBUtility,LtpPageControl

ASP.NET中常用的几个开源公共类: LTP.Common.dll: 通用函数类库     源码下载Maticsoft.DBUtility.dll 数据访问类库组件     源码下载LtpPageControl.dll    Web分页控件   源码下载 本博客下载地址: LTP.Common.dll: 通用函数类库     源码下载Maticsoft.DBUtility.dll 数据访问类库组件     源码下载LtpPageControl.dll    Web分页控件   源码下载 来自:

ASP.net中DateTime获取当前系统时间的大全

在c# / ASP.net中我们可以通过使用DataTime这个类来获取当前的时间.通过调用类中的各种方法我们可以获取不同的时间:如:日期(2008-09-04).时间(12:12:12).日期+时间(2008-09-04 12:11:10)等. //获取日期+时间   DateTime.Now.ToString();                    // 2008-9-4 20:02:10   DateTime.Now.ToLocalTime().ToString();         

关于asp.net中页面事件加载的先后顺序

一.ASP.NET 母版页和内容页中的事件 母版页和内容页都可以包含控件的事件处理程序.对于控件而言,事件是在本地处理的,即内容页中的控件在内容页中引发事件,母版页中的控件在母版页中引发事件.控件事件不会从内容页发送到母版页.同样,也不能在内容页中处理来自母版页控件的事件. 在某些情况下,内容页和母版页中会引发相同的事件.例如,两者都引发 Init 和 Load 事件.引发事件的一般规则是初始化事件从最里面的控件向最外面的控件引发,所有其他事件则从最外面的控件向最里面的控件引发. 请记住,母版页

快速理解C#中的委托与事件

以下内容只是个人理解,仅供参考. 什么是委托? 先看最简单的委托例子: namespace DelegateTest { public delegate void MessageDelegate(string name); class Program { private static void SaySomething(string name) { Console.WriteLine("You said " + name); } static void Main(string[] ar

C# 中的委托和事件

http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html 文中代码在VS2005下通过,由于VS2003(.Net Framework 1.1)不支持隐式的委托变量,所以如果在一个接受委托类型的位置直接赋予方法名,在VS2003下会报错,解决办法是显式的创建一个委托类型的实例(委 托变量).例如:委托类型 委托实例 = new 委托类型(方法名); 欢迎浏览本文的后续文章: C#中的委托和事件(续) 引言 委托 和 事件在

C#中的委托和事件(续)

C#中的委托和事件(续) 引言 如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为细节的问题,包括一些大家常问到的问题,以及事件访问器.异常处理.超时处理和异步方法调用等内容. 为什么要使用事件而不是委托变量? 在 C#中的委托和事件 中,我提出了两个为什么在类型中使用事件向外部提供方法注册,而不是直接使用委托变量的原因.主要是从封装性和易用性上去考虑,但是还漏掉了一点,事件应该

(转)C# 中的委托和事件

C# 中的委托和事件 引言 委托 和 事件在 .Net Framework中的应用非常广泛,然而,较好地理解委托和事件对很多接触C#时间不长的人来说并不容易.它们就像是一道槛儿,过了这个槛的人,觉得真是太容易了,而没有过去的人每次见到委托和事件就觉得心里别(biè)得慌,混身不自在.本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码也做了讨论. 将方法作为方法的参