5

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.

enter image description here 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.

Kevin B Burns
  • 1,032
  • 9
  • 24
  • Looks like you're calculating the relative location of the `parentGrid` to it's container. Which would explain the zero point. Try the `UserControl` to it's container instead, ref [this post](http://stackoverflow.com/a/1923775). – bab7lon Apr 19 '17 at 15:06

2 Answers2

1

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;
    }
Tee
  • 414
  • 2
  • 8
  • 19
1

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.

l33t
  • 18,692
  • 16
  • 103
  • 180