Silverlight的鼠标事件:的MouseEnter和鼠标离开冲突 [英] Silverlight Mouse Events: MouseEnter and MouseLeave conflicts

查看:171
本文介绍了Silverlight的鼠标事件:的MouseEnter和鼠标离开冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有按钮的集合的网格。对于这些按钮中的每一个,我要处理的MouseEnter和鼠标离开事件,以动画按钮的高度(以及做一些其他的有趣的东西)。直到我开始了我的移动鼠标太快和关闭,最终导致事件发生在之前,其他完成按钮这一切运作良好。什么是确保该活动等待海誓山盟被触发之前的最佳方式?

I have a collection of buttons in a grid. For each one of these buttons, I want to handle the MouseEnter and MouseLeave events to animate the height of the button (and do some other interesting stuff). It all works good until I start moving my mouse too fast over and off the buttons which eventually cause the events to take place at before the other is complete. What's the best way of making sure the events wait for eachother before being triggered?

更新:

由X0R的意见去,我重构我的code到从继承按钮并拥有所需的方法来执行动画的内部类。不幸的是,这并没有真正解决问题,因为的 - 我认为 - 的我处理的第一个动画的已完成事件两个不同的地方。 (纠正我,如果我错了)。这里是我的code:

Going by x0r's advice, I refactored my code into an internal class which inherits from Button and has the required methods to perform the animations. Unfortunately, this did not really solve the problem because - I think - I'm handling the Completed event of the first animation in two separate places. (correct me if I'm wrong). Here's my code:

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:

有些事件越来越多次触发。这方面的一个例子是点击我规则的关闭按钮事件对象...

Some events are getting triggered multiple times. An example of that is the Click event on the close button of my Rule object...

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

和下面是动作&LT;的Int32&GT; 我传递给规则对象作为 CloseAction

And below is the Action<Int32> I'm passing to the Rule object as the CloseAction:

    private void RemoveRule(Int32 ruleIndex)
    {
        Rule ruleToRemove = Rules.FirstOrDefault(x => x.Index.Equals(ruleIndex));
        Storyboard sb = new Storyboard();
        DoubleAnimation animation = new DoubleAnimation();
        sb.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Opacity"));
        animation.Duration = TimeSpan.FromMilliseconds(300);
        animation.From = 1;
        animation.To = 0;
        sb.Children.Add(animation);
        Storyboard.SetTarget(animation, ruleToRemove);
        sb.Completed += (s, e) =>
        {
            if (Rules.FirstOrDefault(x => x.Index.Equals(ruleIndex)) != null)
            {
                this.Rules.RemoveAt(ruleIndex);
            }
        };
        sb.Begin();
    }

更新3:

为了避免太早运行动画,我想我可能会推迟的MouseEnter 事件,因此,如果用户只是滚动在该项目上得太快,这不是' ŧ揭开序幕。不过,我现在有一个问题:假设在该项目的用户鼠标,然后鼠标移出。如果我使用 Storyboard.BeginTime 属性,这将打击该行为没有安全防范,因为eventhough动画被延迟,它仍然会最终开始... ...那么,有没有一种方法,我可以prevent这种情况的发生?

In order to avoid the animations running too early, I thought I could delay the MouseEnter event, so if the user just scrolls over the item too fast, it doesn't kick off. But I have a problem now: Say the user mouses over the item and then mouses out. If I use the Storyboard.BeginTime property, that won't safe guard against that behavior because eventhough the animation gets delayed, it's still going to start eventually... So is there a way I could prevent that from happening?

有什么建议?

推荐答案

请检查您的鼠标离开事件处理程序,如果第一个故事板仍然在运行,如果是这样的话附上

check in your mouseleave eventhandler if the first storyboard is still running and if that is the case attach the starting of the second storyboard to the Completed event of the first storybaord:

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

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

这篇关于Silverlight的鼠标事件:的MouseEnter和鼠标离开冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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