" Microsoft Blend"类似连续拖动

时间:2016-11-02 06:09:24

标签: wpf drag blend

Microsoft Blend允许通过连续拖动更改Left,Top等属性的数值。用户在属性值框中单击,保持按钮向下并向左或向右拖动以减小/增加值。简单。

关于它的特殊之处在于,如果光标到达屏幕的左端或右端并且用户仍想要拖动更多,则可以继续拖动,光标将从屏幕的另一端重新开始。

我尝试使用Thumb控件在我的一个WPF应用程序中执行此操作。使用DragDetla事件,如果我发现Thumb已到达屏幕边缘,我会将其位置设置为远端。但这会使e.HorizontalChange的值与整个屏幕的宽度一样大。如何在不影响水平变化值的情况下更改拇指在拖动期间的位置

1 个答案:

答案 0 :(得分:0)

我已经在WPF控件中通过使用文本框并订阅以下事件来实现了这一点:

拖动直到达到屏幕限制要求鼠标捕获或调用任何UIElement上可用的CaptureMouse方法。另一方面,您需要在需要调用ReleaseMouseCapture方法的某个时候释放鼠标。解决方案可能是这样的:

声明枚举以建模拖动方向

internal enum MouseDirections
{
    None,
    LeftRight,
    UpDown
}

声明一个类以保留鼠标起源(第一个位置)和当前位置的痕迹:

internal class MouseIncrementor
{
    private MouseDirections _enumMouseDirection = MouseDirections.None;
    private Point _objPoint;

    private readonly Point _initialPoint;

    public MouseIncrementor(Point objPoint, MouseDirections enumMouseDirection)
    {
        _objPoint = objPoint;
        _initialPoint = _objPoint;
        _enumMouseDirection = enumMouseDirection;
    }

    public MouseDirections MouseDirection
    {
        get
        {
            return _enumMouseDirection;
        }

        protected set
        {
            _enumMouseDirection = value;
        }
    }

    public Point InitialPoint
    {
        get
        {
            return _initialPoint;
        }
    }

    public Point Point
    {
        get
        {
            return _objPoint;
        }

        set
        {
            _objPoint = value;
        }
    }

    internal MouseDirections SetMouseDirection(Point pos)
    {
        double deltaX = this.Point.X - pos.X;
        double deltaY = this.Point.Y - pos.Y;

        if (Math.Abs(deltaX) > Math.Abs(deltaY))
            MouseDirection = MouseDirections.LeftRight;
        else
        {
            if (Math.Abs(deltaX) < Math.Abs(deltaY))
                MouseDirection = MouseDirections.UpDown;
        }

        return MouseDirection;
    }
}

我有一个自定义控件,其中包含一个名为_PART_TextBox的TextBox:                 文字框_PART_TextBox;

...以及MouseIncrementor的字段:                 MouseIncrementor _objMouseIncr;

...这些连接方式如下:

            _PART_TextBox.MouseEnter += _PART_TextBox_MouseEnter;
            _PART_TextBox.GotKeyboardFocus += _PART_TextBox_GotKeyboardFocus;
            _PART_TextBox.LostKeyboardFocus += _PART_TextBox_LostKeyboardFocus;
            _PART_TextBox.MouseMove += _PART_TextBox_MouseMove;
            _PART_TextBox.MouseUp += _PART_TextBox_MouseUp;
            _PART_TextBox.PreviewMouseDown += _PART_TextBox_PreviewMouseDown;
            _PART_TextBox.LostMouseCapture += _PART_TextBox_LostMouseCapture;

和一些事件处理程序才能使它起作用:

    private void _PART_TextBox_LostMouseCapture(object sender, MouseEventArgs e)
    {
        _objMouseIncr = null;
    }

    private void _PART_TextBox_MouseUp(object sender, MouseButtonEventArgs e)
    {
        if (_objMouseIncr != null)
        {
            var mouseUpPosition = GetPositionFromThis(e);
            if (_objMouseIncr.InitialPoint.Equals(mouseUpPosition))
            {
                _PART_TextBox.Focus();
            }
        }

        _PART_TextBox.ReleaseMouseCapture();
        _objMouseIncr = null;
    }

    private void _PART_TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        if (IsKeyboardFocusWithin == false)
        {
            _objMouseIncr = new MouseIncrementor(this.GetPositionFromThis(e), MouseDirections.None);
            e.Handled = true;
        }
    }

    private void _PART_TextBox_MouseMove(object sender, MouseEventArgs e)
    {
        // nothing to do here
        if (_objMouseIncr == null)
            return;

        if (e.LeftButton != MouseButtonState.Pressed)
            return;

        if (CanIncreaseCommand() == false && CanDecreaseCommand() == false)
        {
            // since we can't parse the value, we are out of here, i.e. user put text in our number box
            _objMouseIncr = null;
            return;
        }

        var pos = GetPositionFromThis(e);
        double deltaX = _objMouseIncr.Point.X - pos.X;
        double deltaY = _objMouseIncr.Point.Y - pos.Y;

        if (_objMouseIncr.MouseDirection == MouseDirections.None)
        {
            // this is our first time here, so we need to record if we are tracking x or y movements
            if (_objMouseIncr.SetMouseDirection(pos) != MouseDirections.None)
                _PART_TextBox.CaptureMouse();
        }

        if (_objMouseIncr.MouseDirection == MouseDirections.LeftRight)
        {
            if (deltaX > 0)
                OnDecrement(LargeStepSize);
            else
            {
                if (deltaX < 0)
                    OnIncrement(LargeStepSize);
            }
        }
        else
        {
            if (_objMouseIncr.MouseDirection == MouseDirections.UpDown)
            {
                if (deltaY > 0)
                {
                    if (CanIncreaseCommand() == true)
                        OnIncrease();
                }
                else
                {
                    if (deltaY < 0)
                    {
                        if (CanDecreaseCommand() == true)
                            OnDecrease();
                    }
                }
            }
        }

        _objMouseIncr.Point = GetPositionFromThis(e);
    }

    private Point GetPositionFromThis(MouseEventArgs e)
    {
        return this.PointToScreen(e.GetPosition(this));
    }

    private void _PART_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        _objMouseIncr = null;
        (sender as TextBox).Cursor = Cursors.ScrollAll;
    }

    private void _PART_TextBox_MouseEnter(object sender, MouseEventArgs e)
    {
        if (IsMouseDragEnabled == false)
            return;

        if (IsKeyboardFocusWithin)
            (sender as TextBox).Cursor = Cursors.IBeam;
        else
            (sender as TextBox).Cursor = Cursors.ScrollAll;
    }

    private void _PART_TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
    {
        _objMouseIncr = null;
        (sender as TextBox).Cursor = Cursors.IBeam;
    }

完整的项目位于:https://github.com/Dirkster99/NumericUpDownLib 请让我知道我是否缺少某些东西或还有其他问题。