代码之家  ›  专栏  ›  技术社区  ›  serhio

PresentationCore.dll中出现“System.StackOverflowException”

  •  5
  • serhio  · 技术社区  · 14 年前

    我有一个wpf用户控件,尝试在其中实现 习俗 鼠标点击(因为 没有 MouseClick WPF(用户)控件上的事件 )事件。

    我得到了以下信息:

    alt text

    一些代码:

    /// <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;
        }
    

    那么,问题在哪里?

    更新1

    protected virtual void OnMouseClick(MouseButtonEventArgs e)
    {
        //base.RaiseEvent(e);
        MouseButtonEventArgs args = new MouseButtonEventArgs(e.MouseDevice, e.Timestamp, e.ChangedButton);
        this.RaiseEvent(args);
    }
    

    值不能为空。 参数名称:routedevent

    alt text

    更新2

    我成功实施的另一个自定义事件(毫无问题地工作)- SelectedChanged :

    static void OnIsSelectedChanged(DependencyObject source, DependencyPropertyChangedEventArgs e)
    {
        var s = (MyControl)source;
    
        s.RaiseEvent(new RoutedEventArgs(SelectedChangedEvent, s));
    }
    

    更新3

    System.Windows.Controls.Control的OnPreviewMouseDoubleClick实现:

    protected virtual void OnPreviewMouseDoubleClick(MouseButtonEventArgs e)
    {
        base.RaiseEvent(e);
    }
    

    更新5(油箱内人员)

    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);
        }
    }
    
    3 回复  |  直到 14 年前
        1
  •  3
  •   moldovanu    14 年前
    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
  •  3
  •   Josh Smeaton    14 年前

    您需要从自定义用户控件的所有部分删除base.raiseEvent(e)。这就是堆栈溢出的原因。

    如果您从UserControl继承,那么已经为您实现了Click事件。您不需要重新实现。不过,您可能需要处理它们,但很可能您不需要。

    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;
    }
    

    控制流程为:

    1. 用户生成mouseLeftButtonupEvent
    2. 在OnMouseLeftButtonUp处理程序中调用OnMouseClick
    3. OnMouseClick引发MouseLeftButtonUp事件
    4. 转到2。

    接受的答案将更改为:

    1. 用户生成mouseLeftButtonupEvent
    2. 在OnMouseLeftButtonUp处理程序中调用OnMouseClick
    3. onmouseclick将路由事件更改为mouseclickevent
    4. onmouseclick抬起mouseclickevent
    5. 控制恢复

    这就是我在评论其他答案时试图解释的。如果我不够清楚,我会为此道歉。我相信Serhio和我不同步,因为我试图解释stackvoverflow的原因,当时他正在寻找代码的修复方法。如果我错了就纠正我。

        3
  •  2
  •   ChrisF toni    14 年前

    我想是这样的:

    base.RaiseEvent(e);
    

    如果您正在处理鼠标单击,则不希望再次引发事件,因为这只会再次调用处理程序,从而引发事件….