2016-03-12 74 views
0

我正在開發一個應用程序,我必須在畫布上拖動用戶控件。 此用戶控制可以拖動到正常位置或以90,180,270度的角度旋轉。 當用戶控件以90度或270度的角度拖動時出現問題,因爲用戶控件在鼠標釋放時轉移到了放置點。 我試過用控制的方法TransformToVisual,但它不能正常工作。 有沒有人有任何建議? 如果你需要一些代碼或文件問我。 謝謝。如何在畫布佈局中拖放和旋轉用戶控件

編輯:

這是我背後的代碼ProdottoCtrl:

using System; 
using System.Windows; 
using System.Windows.Controls; 
using System.Windows.Input; 
using System.Windows.Shapes; 

namespace Libreria_Controlli 
{ 
    /// <summary> 
    /// Logica di interazione per ProdottoCtrl.xaml 
    /// </summary> 
    public partial class ProdottoCtrl : ProdottoCtrlBase 
    { 
     Rect _rectCanvasDrop1; 
     Rect _rectCanvasDrop2; 

     bool _isFuoriConfineDrop1; 
     bool _isFuoriConfineDrop2; 
     bool _isContatto = false; 

     public ProdottoCtrl() 
     { 
      InitializeComponent(); 
     } 

     #region Proprietà User Control 

     #region CanvasDrag 
     public Canvas CanvasDrag 
     { 
      get { return (Canvas)GetValue(CanvasDragProperty); } 
      set { SetValue(CanvasDragProperty, value); } 
     } 

     // Using a DependencyProperty as the backing store for CanvasDrag. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CanvasDragProperty = 
      DependencyProperty.Register("CanvasDrag", typeof(Canvas), typeof(ProdottoCtrl)); 
     #endregion 

     #region CanvasDrop1 

     public CanvasDropCtrl CanvasDrop1 
     { 
      get { return (CanvasDropCtrl)GetValue(CanvasDrop1Property); } 
      set { SetValue(CanvasDrop1Property, value); } 
     } 

     // Using a DependencyProperty as the backing store for CanvasDrop1. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CanvasDrop1Property = 
      DependencyProperty.Register("CanvasDrop1", typeof(CanvasDropCtrl), typeof(ProdottoCtrl)); 

     #endregion 

     #region CanvasDrop2 
     public CanvasDropCtrl CanvasDrop2 
     { 
      get { return (CanvasDropCtrl)GetValue(CanvasDrop2Property); } 
      set { SetValue(CanvasDrop2Property, value); } 
     } 

     // Using a DependencyProperty as the backing store for CanvasDrop2. This enables animation, styling, binding, etc... 
     public static readonly DependencyProperty CanvasDrop2Property = 
      DependencyProperty.Register("CanvasDrop2", typeof(CanvasDropCtrl), typeof(ProdottoCtrl)); 
     #endregion 

     #endregion 

     #region Drag handlers 
     private void RettangoloProdotto_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) 
     { 
      _posizioneMouseIniziale= e.GetPosition(TopWindow); 

      // DA MUOVERE 
      _rectCanvasDrop1 = CanvasDrop1.Canvas.TransformToVisual(TopWindow).TransformBounds(new Rect(0, 0, CanvasDrop1.ActualWidth, CanvasDrop1.ActualHeight)); 
      _rectCanvasDrop2 = CanvasDrop2.Canvas.TransformToVisual(TopWindow).TransformBounds(new Rect(0, 0, CanvasDrop2.ActualWidth, CanvasDrop2.ActualHeight)); 

      _isDrag = true; 
      e.Handled = true; 
     } 

     private void RettangoloProdotto_MouseMove(object sender, MouseEventArgs e) 
     { 
      if(_isDrag) 
      { 
       if(IsMinimaDistanzaDrag(e.GetPosition(TopWindow))) 
       { 
        if(_rettangoloOutline == null) 
        { 

         _rettangoloOutline = new Rectangle(); 
         _rettangoloOutline.Width = RettangoloProdotto.Width; 
         _rettangoloOutline.Height = RettangoloProdotto.Height; 
         _rettangoloOutline.Fill = RettangoloProdotto.Fill; 
         _rettangoloOutline.RenderTransform = GridMain.RenderTransform; 
         _rettangoloOutline.Opacity = 0.8; 


         CanvasDrag.Children.Add(_rettangoloOutline); 

         TopWindow.MouseLeftButtonUp += TopWindow_MouseLeftButtonUp; 
         TopWindow.MouseMove += TopWindow_MouseMove; 
        } 
       } 
      } 
     } 

     private void TopWindow_MouseMove(object sender, MouseEventArgs e) 
     { 
      if (!_isDrag || _rettangoloOutline == null) 
       return; 

      #region Offset rotazione    
      if (Rotazione == 0) 
      { 
       delta.X = e.GetPosition(CanvasDrag).X - _rectOutline.Width/2; 
       delta.Y = e.GetPosition(CanvasDrag).Y - _rectOutline.Height/2; 
      } 
      else if (Rotazione == 90) 
      { 
       delta.X = e.GetPosition(CanvasDrag).X + _rectOutline.Width/2; 
       delta.Y = e.GetPosition(CanvasDrag).Y - _rectOutline.Height/2; 
      } 
      else if (Rotazione == 180) 
      { 
       delta.X = e.GetPosition(CanvasDrag).X + _rectOutline.Width/2; 
       delta.Y = e.GetPosition(CanvasDrag).Y + _rectOutline.Height/2; 
      } 
      else if (Rotazione == 270) 
      { 
       delta.X = e.GetPosition(CanvasDrag).X - _rectOutline.Width/2; 
       delta.Y = e.GetPosition(CanvasDrag).Y + _rectOutline.Height/2; 
      } 
      #endregion 

      Canvas.SetLeft(_rettangoloOutline, delta.X); 
      Canvas.SetTop(_rettangoloOutline, delta.Y); 

      _rectOutline = _rettangoloOutline.TransformToVisual(TopWindow).TransformBounds(new Rect(0, 0, _rettangoloOutline.Width, _rettangoloOutline.Height)); 

      _isFuoriConfineDrop1 = IsFuoriConfine(_rectCanvasDrop1); 
      _isFuoriConfineDrop2 = IsFuoriConfine(_rectCanvasDrop2); 
      _isContatto = IsContatto(); // VErificare velocità con molti pacchi 

      if (_isFuoriConfineDrop1) 
       Mouse.OverrideCursor = Cursors.No; 
      else 
       Mouse.OverrideCursor = null; 
     } 

     private void TopWindow_MouseLeftButtonUp(object sender, MouseButtonEventArgs e) 
     { 
      Mouse.OverrideCursor = null; 
      e.Handled = true; 

      if (!_isDrag) 
       return;   

      TopWindow.MouseLeftButtonUp -= TopWindow_MouseLeftButtonUp; 
      TopWindow.MouseMove -= TopWindow_MouseMove; 

      // Il prodotto è fuori dai confini, avverto l'utente 
      if (_isFuoriConfineDrop1 && _isFuoriConfineDrop2) 
      { 
       // Avverto l'utente con un avviso visuale (messageBox o meglio segnali sullo 
       // User control 
      } 
      else if(!_isFuoriConfineDrop1) // Sono nel primo CanvasDrop 
      { 
       if(_isContatto) 
       { 
        // Avverto utente del contatto 

       } 
       else 
       { 

        Point p = _rettangoloOutline.TranslatePoint(new Point(0, 0), CanvasDrop1.Canvas); 

        ProdottoDropCtrl prodottoDrop = CreaProdottoDrop(); 
        CanvasDrop1.Canvas.Children.Add(prodottoDrop); 

        Point pointSnap = SnapToGrid(new Point(p.X, p.Y)); 
        Canvas.SetLeft(prodottoDrop, pointSnap.X); 
        Canvas.SetTop(prodottoDrop, pointSnap.Y); 
       } 
      } 


      if (_rettangoloOutline != null) 
      { 
       CanvasDrag.Children.Remove(_rettangoloOutline); 
       _rettangoloOutline = null; 
      } 
      _isDrag = false; 

      Console.WriteLine("pallet1_Interno {0} - pallet2_Interno {1} - Contatto {2}", !_isFuoriConfineDrop1, !_isFuoriConfineDrop2, _isContatto);    

     } 
     #endregion 

     private bool IsContatto() 
     { 
      CanvasDropCtrl canvasDrop = null; 

      if (_isFuoriConfineDrop1 && _isFuoriConfineDrop2) 
       return false; 

      // Sono nel primo pallet 
      if (_isFuoriConfineDrop2) 
       canvasDrop = CanvasDrop1; 
      else // Sono nel secondo pallet 
       canvasDrop = CanvasDrop2; 

      foreach(var prodotto in canvasDrop.Canvas.Children) 
      { 
       ProdottoCtrlBase prodottoDrop = prodotto as ProdottoCtrlBase; 

       if (this.Equals(prodottoDrop) || prodottoDrop == null) 
        continue; 

       Rect rectProdottoDrop = prodottoDrop.TransformToVisual(TopWindow).TransformBounds(new Rect(0, 0, prodottoDrop.Lunghezza, prodottoDrop.Profondita)); 

       // Contatto - UPDATE: contatto in un solo punto ??? 
       if (rectProdottoDrop.IntersectsWith(_rectOutline)) 
        return true; 
      } 

      return false; 
     } 

     private ProdottoDropCtrl CreaProdottoDrop() 
     { 
      ProdottoDropCtrl prodottoDrop = new ProdottoDropCtrl(); 
      prodottoDrop.Altezza = Altezza; 
      prodottoDrop.Lunghezza = Lunghezza; 
      prodottoDrop.Profondita = Profondita; 
      prodottoDrop.Rotazione = Rotazione; 
      prodottoDrop.GridSize = GridSize; 

      prodottoDrop.TopWindow = TopWindow; 
      if (!_isFuoriConfineDrop1) 
      { 
       prodottoDrop.CanvasDrop = CanvasDrop1; 
       prodottoDrop.NumeroProdotto = NumeroProdottiCanvas(CanvasDrop1) + 1; 
      } 
      else 
      { 
       prodottoDrop.CanvasDrop = CanvasDrop2; 
       prodottoDrop.NumeroProdotto = NumeroProdottiCanvas(CanvasDrop2) + 1; 
      }    

      return prodottoDrop; 
     } 

     private int NumeroProdottiCanvas(CanvasDropCtrl canvasDrop) 
     { 
      int numeroProdotti = 0; 

      foreach (var item in canvasDrop.Canvas.Children) 
      { 
       if (item is ProdottoDropCtrl) 
        numeroProdotti++; 
      } 

      return numeroProdotti; 

     } 
    } 
} 

ProdottoCtrl.xaml:

<local:ProdottoCtrlBase x:Class="Libreria_Controlli.ProdottoCtrl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Libreria_Controlli" 
      mc:Ignorable="d" 
      x:Name="UsrCtrl" 
      Height="{Binding ElementName=UsrCtrl, Path=Profondita}" 
      Width="{Binding ElementName=UsrCtrl, Path=Lunghezza}" 
      Focusable="True" > 

    <Grid Name="GridMain" RenderTransformOrigin="0.5,0.5" 
      Height="{Binding ElementName=UsrCtrl, Path=Profondita}" 
      Width="{Binding ElementName=UsrCtrl, Path=Lunghezza}"> 

     <Grid.RenderTransform> 
      <RotateTransform Angle="{Binding ElementName=UsrCtrl, Path=Rotazione}" /> 
     </Grid.RenderTransform> 

     <Grid.RowDefinitions> 
      <RowDefinition Height="10" /> 
      <RowDefinition /> 
     </Grid.RowDefinitions> 

     <Rectangle Grid.Row="0" Name="RettangoloEtichetta" Margin="5,0" Width="50" Height="5" Fill="White" Panel.ZIndex="100" VerticalAlignment="Bottom"/> 

     <Rectangle Name="RettangoloProdotto" 
        Height="{Binding ElementName=UsrCtrl, Path=Profondita}" 
        Width="{Binding ElementName=UsrCtrl, Path=Lunghezza}" 
        Fill="Coral" 
        Grid.RowSpan="2" 

        MouseLeftButtonDown="RettangoloProdotto_MouseLeftButtonDown" 
        MouseMove="RettangoloProdotto_MouseMove"/> 

    </Grid> 

</local:ProdottoCtrlBase> 
+0

你能provde代碼:旋轉,移動用戶控件類 – MaLiN2223

+0

沒有人有一個想法? – skytron87

回答

0

只是半套的RotateTransform的的centerX和centerY值旋轉要素寬度和半高。通過這種方式,您可以將對象相對於其父項中的位置相對拖動,就像在未旋轉時一樣。

例子:

if(rotateTransform != null) 
    { RotateTransform t = RotateTransform(rotateTransform.Angle + <rotationValue>, Width/2, Height/2); 
    RenderTransform = t; 
    } 

在你的MouseMove處理程序就不需要適應運動:

private void handleMouseMoveEvent(object sender, MouseEventArgs args) 
    { 

     if (args.LeftButton == MouseButtonState.Pressed) 
     { 
      Point parentPosition = Mouse.GetPosition(parentCanvas); 

      Canvas.SetLeft(this, (parentPosition.X - Width/2)); 
      Canvas.SetTop(this, (parentPosition.Y - Height/2));     
     } 

     args.Handled = true; 

    } 

希望這有助於!

乾杯,

亞歷