![](/img/trans.png)
[英]Intercepting click event for all controls in an app in C# (WinForms)
[英]Intercepting and cancelling the Click event of a WinForms Button
有没有一种方法可以从父控件中捕获Button的Click事件,并防止在父控件中的变量为true时发生该事件?
例如:
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
}
}
希望有比上述示例更好的方法来执行此操作。 只是要注意,我对分配给上述按钮的事件没有任何控制权。 它们已在其他位置订阅,并且如果使用方父控件上的变量为true,则只需阻止它们发生。
我的真实情况是:
我正在使用Windows Mobile 6.5(旧版应用程序重写),我创建了一个面板控件,其中可以包含N个子控件。 面板控件允许iPhone样式的垂直滚动。 我订阅了子Control
的MouseMove
事件,并将变量_isScrolling
设置为true
。 在MouseUp
事件中,我将_isScrolling
设置为false
。
由于Click
在MouseUp
之前发生,因此我可以在Click
事件中进行检查,以确保在按下按钮时没有发生滚动。 因此,基本上,如果发生面板滚动,则需要防止触发Click事件(在设计时订阅)。
这可能会提供一些有用的见解
具体来说,看看
private void RemoveClickEvent(Button b)
{
FieldInfo f1 = typeof(Control).GetField("EventClick",
BindingFlags.Static | BindingFlags.NonPublic);
object obj = f1.GetValue(b);
PropertyInfo pi = b.GetType().GetProperty("Events",
BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)pi.GetValue(b, null);
list.RemoveHandler(obj, list[obj]);
}
作为解决问题的另一种方法,为什么不只是对托管表单进行子类化并寻找目标的点击。 如果您的preventClick
为true,则将消息标记为已处理,以防止其传递给孩子。
禁用按钮而不是将父控件中的变量设置为true怎么办?
更新:设置button.Enabled = false
肯定会阻止Click事件引发:)
更新2(针对真实场景):考虑创建自定义按钮
public class ScrollableButton : Button
{
private bool _isScrolling;
protected override void OnMouseMove(MouseEventArgs mevent)
{
_isScrolling = true;
base.OnMouseMove(mevent);
}
protected override void OnMouseUp(MouseEventArgs mevent)
{
base.OnMouseUp(mevent);
_isScrolling = false;
}
public bool IsScrolling { get; set; }
protected override void OnClick(EventArgs e)
{
if (!_isScrolling)
base.OnClick(e);
}
}
只需将默认按钮替换为可滚动按钮即可。
感谢Hehewaffles的回答 ,这是我想出的解决方案:
/// <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);
}
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.