拦截和取消WinForms按钮的Click事件 [英] Intercepting and cancelling the Click event of a WinForms Button

查看:416
本文介绍了拦截和取消WinForms按钮的Click事件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有没有办法从父控件捕获一个Button的Click事件,如果父控件中的变量为真,则会阻止它发生?

Is there a way to capture the Click event of a Button from the parent Control and prevent it occuring if a variable within the parent Control is true?

例如:

For example:

private void AssignEventOverrides()
{
    foreach (Button button in Buttons) 
    {
        // Get the event assigned at design time
        var someUnknownEventHandler = GetTheClickHandlerSomehow(button);

        // Unsubscribe the unknown event
        button.Click -= SomeUnknownEventHandler;

        // Assign the intercepting event
        button.Click += button_Click;
    }
}

private void button_Click(object sender, EventArgs e)
{
    if (!preventClick)
    {
        // Fire the intercepted event that was previously unsubscribed
    }
}

希望有比上述例子更好的方法来做到这一点。只是要注意,我没有任何控制分配给内容的按钮的事件。他们在其他地方订阅,我只需要防止他们发生,如果一个变量在消费父控件上是真的。

Hopefully there's a nicer way to do this than the above example. Just to note, I don't have any control over the events assigned to the afforementioned buttons. They're subscribed elsewhere and I just need to prevent them happening if a variable is true on the consuming parent Control.

我的真实场景:

我使用Windows Mobile 6.5(旧版应用程序重写)我创建了一个可以包含N个子控件的面板控件。面板控件允许iPhone样式垂直滚动。我订阅了孩子 Control MouseMove 事件,并设置一个变量 _isScrolling true 。在 MouseUp 事件中,我将 _isScrolling 设置为 false

I'm using Windows Mobile 6.5 (legacy application rewrite) I've created a panel control that can contain N number of child controls. The panel control allows for iPhone style vertical scrolling. I subscribe to the MouseMove event of the child Control and set a variable _isScrolling to true. In the MouseUp event I set _isScrolling to false.

As 点击发生在 MouseUp 之前,我可以在单击事件以确保按下按钮时没有发生滚动。所以基本上,如果我的面板滚动发生,我需要防止Click事件(在设计时订阅)触发。

As Click occurs before MouseUp I can check within the Click event to ensure a scroll hadn't occured when the button was pressed. So basically, if a scroll of my panel occurs, I need to prevent the Click event (subscribed at design time) from firing.

推荐答案

p>感谢 Heheraffles答案,这里是我想出的解决方案:

Thanks to Hehewaffles answer, here's the solution I came up with:

/// <summary>
/// Dictionary for holding the controls design time Click EventHandlers.
/// </summary>
private Dictionary<Control, EventHandler> _interceptedClickEventHandlers;

/// <summary>
/// Recursively moves through the child controls assigning events for scrolling and replacing Click events 
/// with an interception EventHandler that prevents the Click event occuring if the Panel was scrolled.
/// </summary>
/// <param name="control">The control to handle the events for and whose children to recurse through.</param>
private void RecursivelySubscribeChildEvents(Control control)
{
    if (!(control is IPanelItem))
    {
        return;
    }

    // Subscribe the events for the scroll handling
    control.MouseDown += new MouseEventHandler(UIPanel_MouseDown);
    control.MouseMove += new MouseEventHandler(UIPanel_MouseMove);
    control.MouseUp += new MouseEventHandler(UIPanel_MouseUp);

    // Intercept the click event
    FieldInfo eventClickField = typeof(Control).GetField("Click", BindingFlags.NonPublic | BindingFlags.Instance);
    if (eventClickField != null)
    {
        if (_interceptedClickEventHandlers == null)
        {
            _interceptedClickEventHandlers = new Dictionary<Control, EventHandler>();
        }

        // Get the original event and store it against the control for actioning later
        EventHandler eventClick = (EventHandler)eventClickField.GetValue(control);
        _interceptedClickEventHandlers.Add(control, eventClick);

        // Unsubscribe the old event and assign the interception event
        control.Click -= (EventHandler)eventClick;
        control.Click += new EventHandler(UIPanel_ChildClick);
    }

    // Recurse the event subscription operation
    foreach (Control child in control.Controls)
    {
        RecursivelySubscribeChildEvents(child);
    }
}

private void UIPanel_ChildClick(object sender, EventArgs e)
{
    EventHandler interceptedHandler = _interceptedClickEventHandlers[(Control)sender];
    if (interceptedHandler != null)
    {
        // Fire the originally subscribed event if the panel is not scrolling
        if (!_isScrolling)
        {
            interceptedHandler(sender, e);
        }
    }
}

这篇关于拦截和取消WinForms按钮的Click事件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆