【问题标题】:Drag User Control, but keep it inside the bounds of its parent in WPF拖动用户控件,但将其保持在 WPF 中其父级的范围内
【发布时间】:2016-06-30 20:38:56
【问题描述】:

我有一个在网格内拖动的用户控件。 Z-Index 设置得相当高,这样我就可以将它保持在其他孩子之上。拖动控件效果很好,但是如果用户想要将控件移到网格之外,它会允许这样做。

如何防止它离开父 Grid 控件的边界,这就是我现在所拥有的:

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

“relativeLocation”总是 0x0,所以这不起作用。任何想法将不胜感激。

*注意:我知道如果我将 UserControl 更改为 Window,它会缓解我遇到的所有问题。但老实说,这样看起来很棒,我真的不想把窗户弄得乱七八糟。该系统作为仪表板打开,使用用户的整个窗口(在单独的窗口中打开)。所以当你在这里打开一个窗口时,它不会正确流动。

【问题讨论】:

  • 看起来您正在计算 parentGrid 与其容器的相对位置。这可以解释零点。尝试使用UserControl 代替它的容器,参考this post

标签: c# wpf


【解决方案1】:

我认为您不需要 relativeLocation。不过,数学可能有点烦人。试试这个方法,我测试的时候效果很好:

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

【讨论】:

    【解决方案2】:

    这是一个开始:

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

    现在您有了父网格的屏幕坐标。对Transform() 的调用很重要,因为它将像素转换为独立于 WPF 设备的像素,与系统 DPI 设置相匹配。

    【讨论】:

      猜你喜欢
      • 2011-07-22
      • 1970-01-01
      • 1970-01-01
      • 2012-07-31
      • 1970-01-01
      • 2011-08-06
      • 1970-01-01
      • 2010-09-23
      相关资源
      最近更新 更多