Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Silverlight鼠标事件:MouseEnter和MouseLeave冲突_Silverlight_Events_Animation_Silverlight 4.0_Mouseevent - Fatal编程技术网

Silverlight鼠标事件:MouseEnter和MouseLeave冲突

Silverlight鼠标事件:MouseEnter和MouseLeave冲突,silverlight,events,animation,silverlight-4.0,mouseevent,Silverlight,Events,Animation,Silverlight 4.0,Mouseevent,我有一个网格中的按钮集合。对于这些按钮中的每一个,我都想处理MouseEnter和MouseLeave事件来设置按钮高度的动画(并做一些其他有趣的事情)。这一切都很好,直到我开始在按钮上移动鼠标太快,最终导致事件在另一个按钮完成之前发生。确保事件在触发前等待对方的最佳方式是什么 更新: 按照x0r的建议,我将代码重构为一个内部类,该类继承自按钮,并具有执行动画所需的方法。不幸的是,这并没有真正解决问题,因为——我想——我在两个不同的地方处理第一个动画的完成事件。(如果我错了,请纠正我)。这是我的

我有一个网格中的按钮集合。对于这些按钮中的每一个,我都想处理MouseEnter和MouseLeave事件来设置按钮高度的动画(并做一些其他有趣的事情)。这一切都很好,直到我开始在按钮上移动鼠标太快,最终导致事件在另一个按钮完成之前发生。确保事件在触发前等待对方的最佳方式是什么

更新:

按照x0r的建议,我将代码重构为一个内部类,该类继承自
按钮
,并具有执行动画所需的方法。不幸的是,这并没有真正解决问题,因为——我想——我在两个不同的地方处理第一个动画的
完成事件。(如果我错了,请纠正我)。这是我的密码:

internal class MockButton : Button
{
    #region Fields

    private Storyboard _mouseEnterStoryBoard;
    private Storyboard _mouseLeaveStoryBoard;
    private Double _width;

    #endregion

    #region Properties

    internal Int32 Index { get; private set; }

    #endregion

    #region Ctors

    internal MockButton(Int32 index) : this(index, 200)
    {

    }

    internal MockButton(Int32 index, Double width)
    {
        this.Index = index;
        this._width = width;
    }

    #endregion

    #region Event Handlers

    internal void OnMouseEnter(Action action, Double targetAnimationHeight)
    {
        if (_mouseEnterStoryBoard == null)
        {
            _mouseEnterStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.From = 10;
            heightAnimation.To = targetAnimationHeight;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseEnterStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseEnterStoryBoard.Children.Add(heightAnimation);
        }
        _mouseEnterStoryBoard.Completed += (s, e) =>
        {
            action.Invoke();
        };
        _mouseEnterStoryBoard.Begin();
    }

    internal void OnMouseLeave()
    {
        if (_mouseLeaveStoryBoard == null)
        {
            _mouseLeaveStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.To = 10;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseLeaveStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseLeaveStoryBoard.Children.Add(heightAnimation);
        }
        if (_mouseEnterStoryBoard.GetCurrentState() != ClockState.Stopped)
        {
            _mouseEnterStoryBoard.Completed += (s, e) =>
            {
                _mouseLeaveStoryBoard.Begin();
            };
        }
        else
        {
            _mouseLeaveStoryBoard.Begin();
        }
    }

    #endregion
}
更新2:

某些事件被多次触发。一个例子是我的
规则
对象的关闭按钮上的
单击
事件

    public Rule(Action<Int32> closeAction)
    {
        this.Style = Application.Current.Resources["RuleDefaultStyle"] as Style;
        this.CloseAction = closeAction;
        this.Loaded += (s, e) =>
        {
            if (_closeButton != null)
            {
                _closeButton.Click += (btn, args) =>
                {
                    if (this.CloseAction != null)
                    {
                        this.CloseAction.Invoke(this.Index);
                    }
                };
                if (_closeButtonShouldBeVisible)
                {
                    _closeButton.Visibility = System.Windows.Visibility.Visible;
                }
            }
        };
    }
更新3:

为了避免动画运行太早,我想我可以延迟
MouseEnter
事件,因此如果用户只是在项目上滚动过快,它就不会启动。但我现在有一个问题:假设用户将鼠标移到项目上,然后将鼠标移出。如果我使用
Storyboard.BeginTime
属性,那就不能安全地防止这种行为,因为即使动画被延迟,它最终还是会开始。。。那么,我有没有办法防止这种情况发生


有什么建议吗

如果第一个情节提要仍在运行,请检查您的
mouseleave
eventhandler,如果是这种情况,请将第二个情节提要的开头附加到第一个情节提要的
已完成的
事件上:

private void OnOddRowMouseLeave(object sender, MouseEventArgs e)
{
    ...

    if(_firstStoryboard.GetCurrentState() != ClockState.Stopped)
        _firstStoryboard.Completed += (s,e) =>   _secondStoryboard.Begin();
    else
        _secondStoryboard.Begin()

Silverlight所做的一切都是异步的,因此最有可能发生的情况是,由于您正在快速地进出框,所以在鼠标指针有机会完成之前,鼠标左键被触发。你可以设置你的两个事件,以便它们有一个指示器来指示另一个事件是否正在进行中。例如,你可以这样做

bool mouseOut =false;
bool mouseIn =false;

void OnMouseEnter(Action action, Double targetAnimationHeight)
{
    if(!this.mouseOut)
    {
        this.mouseIn = true;

        if (_mouseEnterStoryBoard == null)
        {
            _mouseEnterStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.From = 10;
            heightAnimation.To = targetAnimationHeight;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseEnterStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseEnterStoryBoard.Children.Add(heightAnimation);
        }
        _mouseEnterStoryBoard.Completed += (s, e) =>
        {
            action.Invoke();
        };
        _mouseEnterStoryBoard.Begin();

        if(this.mouseOut)
        {
            this.OnMouseLeave();
        }

        this.mouseIn = false;
    }
}

void OnMouseLeave()
{
    if(!this.mouseIn)
    {
        this.mouseOut = false;

        if (_mouseLeaveStoryBoard == null)
        {
            _mouseLeaveStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.To = 10;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseLeaveStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseLeaveStoryBoard.Children.Add(heightAnimation);
        }
        if (_mouseEnterStoryBoard.GetCurrentState() != ClockState.Stopped)
        {
            _mouseEnterStoryBoard.Completed += (s, e) =>
            {
                _mouseLeaveStoryBoard.Begin();
            };
        }
        else
        {
            _mouseLeaveStoryBoard.Begin();
        }
    }
    else
    {
        this.mouseOut = true;
    }
}
我实际上还没有检查过这段代码,但这至少可以帮助您更接近您想要的。这应该足够快,让你的用户不会意识到,如果他们快速浏览它,它并没有完全在退出时启动。但这应该有助于避免重叠


另一种方法是将初始事件设置为null,并在事件完成时让“事件中的鼠标”将“事件中的鼠标”设置为“事件中的鼠标”,但问题是,如果在设置事件之前鼠标熄灭,则无法触发事件。

我已更新了问题,请您看一下好吗?谢谢。@Kassem:你的代码是如何运行的(什么东西没有正常工作?)顺便说一句:你可能还应该检查MouseEnter,如果MouseLeave情节提要仍然在运行,如果是这样的话,停止MouseLeave情节提要我仍然不明白为什么会出现这些问题。我注意到的一件事是,一些事件被多次触发,而它们只应该被调用一次!一个例子是关闭按钮的点击事件(检查新的更新)。@Kassem:events只触发一次,是否会多次附加事件处理程序?您的代码看起来不错,但您应该通过设置断点进行检查
bool mouseOut =false;
bool mouseIn =false;

void OnMouseEnter(Action action, Double targetAnimationHeight)
{
    if(!this.mouseOut)
    {
        this.mouseIn = true;

        if (_mouseEnterStoryBoard == null)
        {
            _mouseEnterStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.From = 10;
            heightAnimation.To = targetAnimationHeight;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseEnterStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseEnterStoryBoard.Children.Add(heightAnimation);
        }
        _mouseEnterStoryBoard.Completed += (s, e) =>
        {
            action.Invoke();
        };
        _mouseEnterStoryBoard.Begin();

        if(this.mouseOut)
        {
            this.OnMouseLeave();
        }

        this.mouseIn = false;
    }
}

void OnMouseLeave()
{
    if(!this.mouseIn)
    {
        this.mouseOut = false;

        if (_mouseLeaveStoryBoard == null)
        {
            _mouseLeaveStoryBoard = new Storyboard();
            DoubleAnimation heightAnimation = new DoubleAnimation();
            heightAnimation.To = 10;
            heightAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(300));
            _mouseLeaveStoryBoard.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
            Storyboard.SetTarget(heightAnimation, this);
            _mouseLeaveStoryBoard.Children.Add(heightAnimation);
        }
        if (_mouseEnterStoryBoard.GetCurrentState() != ClockState.Stopped)
        {
            _mouseEnterStoryBoard.Completed += (s, e) =>
            {
                _mouseLeaveStoryBoard.Begin();
            };
        }
        else
        {
            _mouseLeaveStoryBoard.Begin();
        }
    }
    else
    {
        this.mouseOut = true;
    }
}