简体   繁体   中英

Drag User Control, but keep it inside the bounds of its parent in WPF

I have a user control that I am dragging inside of a grid. The Z-Index is set pretty high so that I can keep it above the other children. Dragging the control works perfectly, but if a user wants to move the control outside of the grid it will allow it.

在此输入图像描述 How do I keep it from leaving the bounds of the parent Grid control, here is what I have now:

   private System.Windows.Point _anchorPoint;
    private System.Windows.Point _currentPoint;
    private bool _isInDrag;

   private void UserControl_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        var element = sender as FrameworkElement;
        _anchorPoint = e.GetPosition(null);
        if (element != null) element.CaptureMouse();
        _isInDrag = true;
        e.Handled = true;
    }

    private void UserControl_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        if (!_isInDrag) return;
        var element = sender as FrameworkElement;
        if (element != null) element.ReleaseMouseCapture();
        _isInDrag = false;
        e.Handled = true;
    }

   private void UserControl_MouseMove(object sender, MouseEventArgs e)
        {
            if (!_isInDrag) return;
            _currentPoint = e.GetPosition(null);

            UIElement container = VisualTreeHelper.GetParent(_parentGrid) as UIElement;
            System.Windows.Point relativeLocation = _parentGrid.TranslatePoint(new System.Windows.Point(0, 0), container);

            if (_currentPoint.X > relativeLocation.X) return;
            if(_currentPoint.Y >= relativeLocation.Y)return;

            _transform.X += _currentPoint.X - _anchorPoint.X;
            _transform.Y += (_currentPoint.Y - _anchorPoint.Y);
            RenderTransform = _transform;
            _anchorPoint = _currentPoint;
        }

The "relativeLocation" is always 0x0, so thats not working. Any ideas would greatly be appreciated.

*Note : I know if I changed my UserControl to a Window it would mitigate all of the issues that I am having. But to be honest, it looks great this way and I really don't want to clutter the window up. This system opens up as a dashboard that consumes the user's' entire window ( is opened on a separate window). So when you open a window here, its doesn't flow right.

I don't think you need the relativeLocation. The math can be a bit annoying to get right, though. Try this approach, it worked well when I tested it:

    private void UserControl_MouseMove(object sender, MouseEventArgs e)
    {
        if (!_isInDrag) return;
        _currentPoint = e.GetPosition(null);

        //This is the change to the position that we want to apply
        Point delta = new Point();
        delta.X = _currentPoint.X - _anchorPoint.X;
        delta.Y = _currentPoint.Y - _anchorPoint.Y;

        //Calculate user control edges
        var leftEdge   = Margin.Left + _transform.X + delta.X;
        var topEdge    = Margin.Top + _transform.Y + delta.Y;
        var rightEdge  = Width + Margin.Left + _transform.X + delta.X;
        var bottomEdge = Height + Margin.Top + _transform.Y + delta.Y;

        //Set the delta to 0 if it goes over _parentGrid edges
        if (leftEdge < 0) delta.X = 0;
        if (topEdge  < 0) delta.Y = 0;

        if (rightEdge  > _parentGrid.Width)  delta.X = 0;
        if (bottomEdge > _parentGrid.Height) delta.Y = 0;

        //Apply the delta to the user control
        _transform.X += delta.X;
        _transform.Y += delta.Y;
        RenderTransform = _transform;
        _anchorPoint = _currentPoint;
    }

This is a start:

Point position = _parentGrid.PointToScreen(new Point(0, 0));
PresentationSource source = PresentationSource.FromVisual(_parentGrid);
position = source.CompositionTarget.TransformFromDevice.Transform(position);

Now you have the screen coordinates of the parent grid. The call to Transform() is important as it will convert pixels to WPF device independent pixels, matching the system DPI setting.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM