由事件触发的动作

时间:2012-02-03 18:28:42

标签: c# events action

我有两个列表,一个包含事件,一个包含Actions(函数)

列表的原因是允许用户通过接口将两者连接在一起。所以我正在尝试创建一个接收事件并添加操作的方法。

我希望能够执行TheEvent += TheAction,然后可以稍后使用 - =删除它。

我很抱歉,如果这样做很明显,我无法找到合适的搜索关键词,“将动作连接到事件”是我想到的最好的,在搜索中它是无用的。 / p>

我想出的任何内容都不允许我为一个事件添加动作,但也许我错了。关于允许用户选择事件和从事件触发的功能的最佳方式的任何建议将不胜感激。

2 个答案:

答案 0 :(得分:0)

不确定您的问题...为什么不从事件处理程序中调用您的Action?

internal class Program
{
    private static Test test = new Test();
    private static Action action = ActionHandler;

    private static void ActionHandler()
    {
        // Detaches the event handler
        test.MyEvent -= test_MyEvent;
    }

    private static void Main(string[] args)
    {
        // Attaches the event handler
        test.MyEvent += test_MyEvent;

        test.DoTheTest();

        Console.ReadKey();
    }

    private static void test_MyEvent(object sender, EventArgs e)
    {
        // Executes the method defined in the Action
        action();
    }
}


public class Test
{
    public event EventHandler MyEvent;

    public void DoTheTest()
    {
        if (this.MyEvent != null)
        {
            this.MyEvent(this, EventArgs.Empty);
        }
    }
}

答案 1 :(得分:0)

事件是不可变的。如果添加或删除事件处理程序,则会创建新事件(或多播委托)。这也意味着,在向列表添加事件时必须小心。这不起作用

public event EventHandler Event0;
public event EventHandler Event1;
public event EventHandler Event2;

public List<EventHandler> Events;

public void AddEvents( )
{
    Events = new List<EventHandler> { Event0, Event1, Event2 };
    Event0 += new EventHandler(EventHandler0);
    Events[1] += new EventHandler(EventHandler1);
}

如果向Event0添加事件处理程序,相应的列表条目仍将引用旧的Event0!如果您向Events[1]添加事件处理程序,则Event1将不会更新!


我不知道这是不是你的意思,但是,如果你有这两个列表

public List<EventHandler> Events;
public List<Action<object, EventArgs>> Actions;

您可以将en event hander(一个动作)添加到这样的事件中:

Events[i] += new EventHandler(Actions[j]);

并举起像这样的活动

EventHandler eh = Events[i];
if (eh != null) {
    eh(this, EventArgs.Empty);
}

编辑(回复您的评论):

在此,您必须对原始事件列表执行操作,而不是对作为参数传递的事件执行操作,因为上面解释了此不可变问题。如有必要,您还可以将列表本身作为附加参数传递。

public void AddActionToEvent(Action<object, EventArgs> action, int eventIndex)
{
    Events[eventIndex] += new EventHandler(action);
}

关于如何让用户选择事件和动作的其他问题,我建议要么有四个列表,其中事件和动作列表将与两个对应的字符串列表并列,其中包含事件和动作的名称。或者,您可以将事件和操作包装在包含它们的类及其名称

public class EventWrapper
{
    public string Name { get; set; }
    public event EventHandler Event;

    public override string ToString()
    {
        return Name;
    }

    public void RaiseEvent(object sender)
    {
        EventHandler eh = Event;
        if (eh != null) {
            eh(sender, EventArgs.Empty);
        }
    }
}

public class ActionWrapper
{
    public string Name { get; set; }
    public Action<object, EventArgs> Action { get; set; }

    public override string ToString()
    {
        return Name;
    }
}

然后你会定义像这样的列表

public List<EventWrapper> EventsWithNames;
public List<ActionWrapper> ActionsWithNames;

现在,您可以直接将这些列表用作组合框或列表框中的数据源。包装器的重写ToString方法自动提供要显示的字符串。

现在可以将add方法重写为

public void AddActionToEvent(ActionWrapper actionWrapper, EventWrapper eventWrapper)
{
    eventWrapper.Event += new EventHandler(actionWrapper.Action);
}

包装器也会化解不可变的情况,因为我们不将事件作为参数传递,而是将其包装。