更改活动的顺序

时间:2014-11-26 12:23:54

标签: c# winforms

我有一个控件(按钮),其中包含一个消息框,其中包含文本"测试A"并添加了一个代表与另一个消息"测试B"。下面的代码首先显示了#34;测试A`"然后"测试B":

c.Click += delegate(object sender, EventArgs e)
{
    MessageBox.Show("Test B");        
};

我需要类似于我所做的不能正常工作的代码:

EventHandler handler;
c.click -= handler;
handler = delegate(Object sender, EventArgs e)
{
     MessageBox.Show("Test B");
};
c.Click += handler;

我需要更改顺序,即显示消息"测试B"然后"测试A"。有可能吗?

2 个答案:

答案 0 :(得分:3)

您可以取消注册并重新注册:

button1.Click -= button1_Click; // unregister main event

            button1.Click += delegate(object sender, EventArgs e) // reigster new one
            {
                MessageBox.Show("Test B");
            };

            button1.Click += button1_Click; // register again old

按钮点击事件:

private void button1_Click(object sender, EventArgs e)
{
   MessageBox.Show("Test A");
}

现在它将首先调用Call 测试B ,然后再调用测试A

答案 1 :(得分:2)

您提到您的程序包含某种类型的编译器,并且用户可以指定其代码是在现有代码之前还是之后运行。在我看来,您可以简单地处理您自己的事件处理程序中的用户代码,该处理程序以所需的顺序运行您的和用户代码(正如Nikola已经提到的那样)。

换句话说,不要直接将这些事件公开给用户代码,而是用自己的事件处理程序“包装”它们。从用户的角度来看,没有任何变化 - 他们仍然认为他们可以直接访问该事件。但是您可以控制处理用户代码的方式,因此您可以在中间插入一层以保证正确的执行顺序:

c.Click += (sender, e) =>
{
    if (hasUserEventHandler && runUserEventHandlerFirst)
        UserEventHandler(sender, e);

    StandardEventHandler(sender, e);

    if (hasUserEventHandler && !runUserEventHandlerFirst)
        UserEventHandler(sender, e);
};

我的意思是,你可以做这样的事情:

public void SwapDelegateOrder(object obj, string eventName)
{
    // Fetch the underlying event handler field (let's *assume* it has the same name):
    var delegateField = obj.GetType().GetField(eventName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    var mcDelegate = delegateField.GetValue(obj) as MulticastDelegate;
    if (mcDelegate == null)
        return;

    // Get the add and remove methods:
    var evt = obj.GetType().GetEvent(eventName);
    var add = evt.GetAddMethod(true);
    var remove = evt.GetRemoveMethod(true);

    // Remove all invocations...
    var invocations = mcDelegate.GetInvocationList();
    foreach (var invocation in invocations)
        remove.Invoke(obj, new object[] { invocation });

    // ...and add them back in, in reverse order (*assuming* that invocations are called in the order they're added):
    foreach (var invocation in invocations.Reverse())
        add.Invoke(obj, new object[] { invocation });
}

但这是基于对编译器和运行时实现(事件字段名称和执行顺序)的假设。如果在编译器更新或下一个.NET框架版本中更改了其中一些细节,该怎么办?您无法控制,但您可以控制自己的代码。