2016-06-30 27 views
5

Ho un controllo utente che sto trascinando all'interno di una griglia. Lo Z-Index è impostato piuttosto in alto in modo da poterlo mantenere sopra gli altri bambini. Trascinando il controllo funziona perfettamente, ma se un utente vuole spostare il controllo al di fuori della griglia lo consentirà.Trascina il controllo utente, ma tienilo entro i limiti del suo genitore in WPF

enter image description here Come faccio a tenerlo di lasciare i limiti del controllo griglia genitore, ecco quello che ho adesso:

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

Il "relativeLocation" è sempre 0x0, di modo che è non funziona. Qualsiasi idea sarebbe molto apprezzata.

* Nota: so che se ho modificato il mio UserControl in una finestra, questo avrebbe attenuato tutti i problemi che sto riscontrando. Ma ad essere onesti, sembra fantastico in questo modo e davvero non voglio ingombrare la finestra. Questo sistema si apre come una dashboard che consuma l'intera finestra dell'utente (è aperta in una finestra separata). Quindi quando apri una finestra qui, la sua non scorre correttamente.

+0

Sembra che si stia calcolando la posizione relativa di 'parentGrid' nel suo contenitore. Quale spiegherebbe il punto zero. Prova invece "UserControl" al suo contenitore, ref [questo post] (http://stackoverflow.com/a/1923775). – bab7lon

risposta

1

Non penso che sia necessaria la relativa posizione. La matematica può essere un po 'fastidiosa per avere ragione, però. Prova questo approccio, ha funzionato bene quando ho provato:

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

questo è un inizio:

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

Ora avete le coordinate dello schermo della griglia genitore. La chiamata a Transform() è importante in quanto convertirà i pixel in pixel indipendenti dal dispositivo WPF, facendo corrispondere l'impostazione DPI del sistema.