在事件处理程序的调用者退出后运行代码

3
在下面的例子中,是否可以在控件的Do Y完成后执行Do X(即退出调用我的事件处理程序的方法)?似乎Do X的操作会干扰Do Y,因此需要在Do Y完成后执行Do X
//at form initialisation
someThirdPartyControl.MouseDoubleClick += MyHandler;

void MyHandler(...)
{
    e.Handled = true;
    //Do X
}

//The control's code may be something like
class SomeThirdPartyControl:Control
{
  void override OnMouseDoubleClick(...)
  {
     //call event handlers
     //Do Y
  }
}
Do X 可能会改变控件的大小,导致项目的位置可能会发生变化,当这种情况发生时,控件会错误地选择双击后鼠标指针所在的项目。例如,我双击了项目4,但是Do X更改了控件的大小,在完成Do X之后,项目2位于鼠标指针下方,控件选择了项目2。我的要求是保持选定的项目为项目4

这似乎是一个 xy 问题。你能解释一下你想要解决什么问题吗? - Steve
我已经添加了控制问题。 - Damn Vegetables
3个回答

1

只有通过子类化 SomeControl 并像这样重写 OnMouseDoubleClick 才能实现此操作:

class MyControl:SomeControl
{
  void override OnMouseDoubleClick(MouseEventArgs e)
  {
     base.OnMouseDoubleClick(e)
     //call event handlers
     //Do X
  }
}

你甚至可以定义一个新事件AfterMouseDoubleClick,并在OnMouseDoubleClick中触发该事件,而不是调用X。
class MyControl:SomeControl
{
  public event MouseButtonEventHandler AfterMouseDoubleClick;

  void override OnMouseDoubleClick(MouseEventArgs e)
  {
     base.OnMouseDoubleClick(e)
     //call event handlers
     OnAfterMouseDoubleClick(e)
  }

  void virtual OnAfterMouseDoubleClick(MouseEventArgs e)
  {
     if(AfterMouseDoubleClick != null)
       AfterMouseDoubleClick(this, e)
  }
}

然而,您应该认真考虑在X中做了什么来搞乱Y。


基本上,“Do X” 可能会改变控件的大小,因此项目的位置可能会发生变化。当这种情况发生时,控件会错误地选择鼠标指针所在的项目进行双击(所选项目不应更改)。 - Damn Vegetables
这里我编辑了我的答案,使它与你的不同,而你不得不去更新它 :p - Scott Chamberlain
1
@DamnVegetables,你可以将会导致大小改变的工作排队,并在this.BeginInvoke调用中执行。这将在事件队列中处理完所有其他事项后执行更改大小的代码。 - Scott Chamberlain
抱歉,我已经提到过AfterMouseDown的可能性,然后想我也应该提供一些示例代码。 - P. Kouvarakis

0

是的,这很容易,你只需要从SomeThirdPartyControl继承。你甚至可以将它转换成另一个事件并以这种方式使用。

class MyWrapperControl : SomeThirdPartyControl
{
  public event MouseEventHandler AfterMouseDoubleClick;

  protected void override OnMouseDoubleClick(MouseEventArgs e)
  {
     base.OnMouseDoubleClick(e); //This will Do X.

     OnAfterMouseDoubleClick(e);
  }

  protected virtal void OnAfterMouseDoubleClick(MouseEventArgs e)
  {
       var temp = AfterMouseDoubleClick;
       if(temp != null)
           temp(this, e);
  }
}

用法如下。

//at form initialisation
myWrapperControl.AfterMouseDoubleClick += MyHandler;

void MyHandler(object sender, MouseEventArgs e)
{
    //This event is fired after all MouseDoubleClick events have been handled.

    //Do X
}

0

OnMouseDoubleClick 的基本实现调用事件,因此:

  1. 如果你不从OnMouseDoubleClick()中调用基本实现,MyHandler将不会被触发。

  2. 您可以通过在需要的位置放置base.OnMouseDoubleClick()来控制调用顺序。

    void override OnMouseDoubleClick(...)
    {
        // ...
        // Do Y
        base.OnMouseDoubleClick(); // 其他操作中包括X...
    }
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接