65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 事件参数库

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.20/5 (9投票s)

2008年3月9日

CPOL

1分钟阅读

viewsIcon

40107

downloadIcon

292

一个包含常用事件参数类的库。

引言

有很多种你经常需要的事件参数,例如 CancelEventArgs。这个库包含了一系列事件参数。

背景

接口

我将事件参数的不同能力放入了以下接口中

interface IValueEventArgs<T> { T Value { get; } }
interface ICancelEventArgs { bool IsCanceled { get; } void Cancel(); }
interface INewValueEventArgs<T> { T NewValue { get; set; } }
interface IOldValueEventArgs<T> { T OldValue { get; } }
interface IIndexEventArgs { int Index { get; } }
interface IRangeEventArgs : IIndexEventArgs { int Count { get; } }

这些接口允许你使用一个处理程序函数轻松处理多个事件。

ICancelEventArgs 包含两个成员(bool IsCanceled { get; }, void Cancel();)以防止事件处理程序通过类似以下的代码将 Canceled 属性设置为 false

e.Canceled = !condition;

然后,我在类中实现了这些接口的组合

class ValueEventArgs<T> : IValueEventArgs<T>
class CancelEventArgs : ICancelEventArgs
class ValueCancelEventArgs<T> : IValueEventArgs<T>, ICancelEventArgs

class ValueChangingEventArgs<T> : IValueEventArgs<T>,  INewValueEventArgs<T>
class ValueChangedEventArgs<T> : IValueEventArgs<T>,  IOldValueEventArgs<T>

class ValueIndexEventArgs<T> : IValueEventArgs<T>,  IIndexEventArgs
class ValueIndexChangingEventArgs<T> : IValueEventArgs<T>, 
      INewValueEventArgs<T>, IIndexEventArgs
class ValueIndexChangedEventArgs<T> : IValueEventArgs<T>, 
      IOldValueEventArgs<T>, IIndexEventArgs 

class RangeEventArgs : IRangeEventArgs
class RangeCancelEventArgs : IRangeEventArgs, ICancelEventArgs

在实践中,这些类相互派生,以编写更少的代码。

委托(Delegates)

该库包含以下事件处理程序委托

public delegate void EventHandler<TEventArgs, TSender>(TEventArgs e, TSender sender)
       where TEventArgs : EventArgs;

这个处理程序允许你使用第二个泛型参数指定发送者的类型。

使用代码

作为一个例子,我开发了一个提供以下事件的通知列表

public event EventHandler<ValueIndexCancelEventArgs<T>, NotifyList<T>> Inserting;
public event EventHandler<ValueIndexEventArgs<T>, NotifyList<T>> Inserted;
public event EventHandler<ValueIndexChangingEventArgs<T>, NotifyList<T>> Setting;
public event EventHandler<ValueIndexChangedEventArgs<T>, NotifyList<T>> Set;
public event EventHandler<ValueIndexCancelEventArgs<T>, NotifyList<T>> Removing;
public event EventHandler<ValueIndexEventArgs<T>, NotifyList<T>> Removed;
public event EventHandler<CancelEventArgs, NotifyList<T>> Clearing;
public event EventHandler<EventArgs, NotifyList<T>> Cleared; 

我实现了 IList<T>ICollection<T>IEnumerable<T> 以提供基本列表功能。内部使用 List<T>

事件触发

作为一个事件触发的例子,我将向你展示 Insert 函数

public void Insert(int index, T item)
{
    if (this.OnInserting(item, index))
    {
        this.list.Insert(index, item);
        this.OnInserted(item, index);
    }
}

protected bool OnInserting(T item, int index)
{
    if (this.Inserting != null)
    {
        ValueIndexCancelEventArgs<T> evArgs = 
           new ValueIndexCancelEventArgs<T>(item, index);
        this.Inserting(this, evArgs);
        return !evArgs.IsCanceled;
    }
    else
        return true;
}

protected void OnInserted(T item, int index)
{
    if (this.Inserted != null)
    {
        ValueIndexEventArgs<T> eventArgs = 
           new ValueIndexEventArgs<T>(item, index);
        this.Inserted(this, eventArgs);
    }
}

如你所见,事件触发封装在一个 protected 函数中,该函数实例化事件参数类,如果事件处理程序没有取消该操作,则返回 true

事件处理

作为一个事件处理的例子,我将向你展示如何防止所提到的 NotifyList 以任何方式更改

static void Main(string[] args)
{
    NotifyList<string> myLst = new NotifyList<string>();

    myLst.Add("test");
    myLst.Add("qwert");

    myLst.Inserting += new EventHandler<ValueIndexCancelEventArgs<string>, 
                       NotifyList<string>>(myLst_Changing);
    myLst.Setting += new EventHandler<ValueIndexChangingEventArgs<string>, 
                     NotifyList<string>>(myLst_Changing);
    myLst.Removing += new EventHandler<ValueIndexCancelEventArgs<string>, 
                      NotifyList<string>>(myLst_Changing);
    myLst.Clearing += new EventHandler<CancelEventArgs, 
                      NotifyList<string>>(myLst_Changing);

    myLst.Clear();
    myLst.Add("hello world");
    myLst.Add("test123");
    myLst.RemoveAt(0);
    myLst.Insert(1, "hello universe");

    foreach (string itm in myLst)
        Console.WriteLine(itm);
    //Output:
    //test
    //qwert

    Console.ReadLine();
}

static void myLst_Changing(NotifyList<string> sender, ICancelEventArgs e)
{
    e.Cancel();
}

如你所见,所有事件只有一个处理程序。这是因为库提供的接口所致。

历史

  • 星期日 3 月 9:创建文章。
  • 星期一 3 月 10:添加示例;更正了 ValueIndexCancelEventArgs<T> 类中的错误实现。
  • 星期三 3 月 12:添加了 IRangeEventArgs 接口。
© . All rights reserved.