我有一个WPF UserControl,我尝试在其中实现自定义 MouseClick(因为 WPF(用户)控件上没有MouseClick
事件)事件。
我得到了以下内容:
一些代码:
/// <summary>
/// Occurs when users left clicks the MyControl.
/// </summary>
public event MouseButtonEventHandler MouseClick { add { AddHandler(MouseClickEvent, value); } remove { RemoveHandler(MouseClickEvent, value); } }
protected virtual void OnMouseClick(MouseButtonEventArgs e)
{
base.RaiseEvent(e);
//this.RaiseEvent(new RoutedEventArgs(MouseClickEvent, this));
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (!this.movedAfterMouseDown)
{
OnMouseClick(e);
}
this.gotLeftButtonDown = false;
this.movedAfterMouseDown = false;
}
那么,问题在哪里?
protected virtual void OnMouseClick(MouseButtonEventArgs e)
{
//base.RaiseEvent(e);
MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton);
this.RaiseEvent(args);
}
值不能为空。 参数名称:routedEvent
我成功实施的其他自定义事件(无问题) - SelectedChanged
:
static void OnIsSelectedChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
{
var s = (MyControl)source;
s.RaiseEvent(new RoutedEventArgs(SelectedChangedEvent, s));
}
System.Windows.Controls.Control的OnPreviewMouseDoubleClick实现:
protected virtual void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
{
base.RaiseEvent(e);
}
class Foo : FrameworkElement
{
event EasterCameEvent; // I named it MouseClick
public DoSomething()
{
EasterCameArgs args= ...
if (Date.Now = EasterDate)
OnEasterCame(args)
}
protected virtual void OnEasterCame(EasterCameArgs e)
{
base.RaiseEvent(e);
}
}
答案 0 :(得分:3)
您需要从自定义用户控件的所有部分中删除base.RaiseEvent(e)。这是堆栈溢出的原因。
如果您从UserControl继承,则已经为您实现了单击事件。你不需要重新实现。你可能需要处理它们,但很可能你不需要处理它们。
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
// handle the event if you need to do something with the data.
// this is not over-riding the event, this is attaching a custom handler to the event
this.gotLeftButtonDown = false;
this.movedAfterMouseDown = false;
}
这不会超越事件。这是事件被引发时的处理程序!您的控件的用户将像这样编写处理程序。不要重新实现它。除非您需要对数据执行某些操作,否则甚至不要处理它。这些事件已经为您编写。
编辑:
虽然我的答案是错误的,因为它没有解决问题,但理解为什么发生stackoverflow异常仍然有帮助。
protected virtual void OnMouseClick(MouseButtonEventArgs e)
{
base.RaiseEvent(e);
/* this will raise the OnMouseLeftButtonUp event if the MouseButtonEventArgs
designates that it came from the MouseLeftButtonUp event.
That will then call the OnMouseLeftButtonUp because e.RoutedEvent equals
MouseLeftButtonUpEvent.
The accepted answer does the following, to stop OnMouseLeftButtonUp being
called again, and the whole process repeating itself in an infinite loop.
args.RoutedEvent = MouseClickEvent;
base.RaiseEvent(e); // No longer fires MouseLeftButtonUp, breaking cycle.
// Changes the event to be fired, avoiding the cycle of
// OnMouseLeftButtonUp -> OnMouseClick -> OnMouseLeftButtonUp etc
*/
}
protected override void OnMouseLeftButtonUp(MouseButtonEventArgs e)
{
base.OnMouseLeftButtonUp(e);
if (!this.movedAfterMouseDown)
{
OnMouseClick(e); // This will call OnMouseClick handler
}
this.gotLeftButtonDown = false;
this.movedAfterMouseDown = false;
}
控制流程为:
接受的答案改为:
这是我在其他答案的评论中试图解释的。如果我不够清楚,我为此道歉。我相信serhio和我不同步,我试图解释stackvoverflow的原因,当他正在寻找修复代码时。如果我错了,请纠正我。
答案 1 :(得分:3)
protected virtual void OnMouseClick(MouseButtonEventArgs e)
{
MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton);
// Don't forget this
args.RoutedEvent = MouseClickEvent;
base.RaiseEvent(args);
}
答案 2 :(得分:2)
我认为这是在这一行:
base.RaiseEvent(e);
如果您正在处理鼠标单击,则不希望再次引发该事件,因为这样只会再次调用您的处理程序,这将引发事件....