C# 如何在画布布局中拖动和旋转用户控件

C# 如何在画布布局中拖动和旋转用户控件,c#,wpf,canvas,rotation,drag,C#,Wpf,Canvas,Rotation,Drag,我正在开发一个应用程序,我必须在画布上拖动一个用户控件。 此用户控件可以在正常位置拖动或以90度、180度、270度的角度旋转。 当以90度或270度的角度拖动用户控件时,我遇到了一个问题,因为在释放鼠标时,用户控件会移动到放置点。 我尝试了TransformToVisual控制方法,但效果不好。 有人有什么建议吗? 如果您需要一些代码或文件,请询问我。 谢谢 编辑: 这是我的ProdottoCtrl代码隐藏: using System; using System.Windows; using

我正在开发一个应用程序,我必须在画布上拖动一个用户控件。 此用户控件可以在正常位置拖动或以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;

        }
    }
}
使用系统;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Input;
使用System.Windows.Shapes;
名称空间库
{
/// 
///每个ProdottoCtrl.xaml的内部逻辑
/// 
公共部分类ProdottoCtrl:prodottoctrbase
{
直肠-直肠扩张1;
直肠血管扩张2;
bool_Isfuori 1;
bool_isfuori2;
bool _isContatto=false;
公共产品目录
{
初始化组件();
}
#用户控制的区域属性
#区域拉票
公共画布拉票
{
获取{return(Canvas)GetValue(CanvasDragProperty);}
set{SetValue(CanvasDragProperty,value);}
}
//使用DependencyProperty作为画布拖动的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性CanvasDragProperty=
DependencyProperty.Register(“CanvasDrag”、typeof(Canvas)、typeof(prodottotctrl));
#端区
#地区拉票1
公众拉票Ctrl拉票1
{
获取{return(CanvasDropCtrl)GetValue(CanvasDrop1Property);}
set{SetValue(canvasdroperty,value);}
}
//使用DependencyProperty作为画布1的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性CanvasDrop1属性=
DependencyProperty.Register(“CanvasDrop1”、typeof(CanvasDropCtrl)、typeof(ProdotOctRL));
#端区
#地区拉票2
公众拉票Ctrl拉票2
{
获取{return(CanvasDropCtrl)GetValue(CanvasDrop2Property);}
设置{SetValue(CanvasDrop2Property,value);}
}
//使用DependencyProperty作为画布2的后台存储。这将启用动画、样式、绑定等。。。
公共静态只读从属属性CanvasDrop2属性=
DependencyProperty.Register(“CanvasDrop2”、typeof(CanvasDropCtrl)、typeof(ProdotOctRL));
#端区
#端区
#区域拖动处理程序
私有void RettangoloProdotto_MouseLeftButtonDown(对象发送器,MouseButtonEventArgs e)
{
_posizioneMouseIniziale=e.GetPosition(TopWindow);
//达穆奥弗
_rectCanvasDrop1=CanvasDrop1.Canvas.TransformToVisual(TopWindow.TransformBounds)(新的Rect(0,0,CanvasDrop1.ActualWidth,CanvasDrop1.ActualHeight));
_rectCanvasDrop2=CanvasDrop2.Canvas.TransformToVisual(TopWindow.TransformBounds)(新的Rect(0,0,CanvasDrop2.ActualWidth,CanvasDrop2.ActualHeight));
_isDrag=true;
e、 已处理=正确;
}
私有void RettangoloProdotto_MouseMove(对象发送方,MouseEventArgs e)
{
如果(_isDrag)
{
如果(IsMinimaDistanzaDrag(例如GetPosition(TopWindow)))
{
如果(_rettangoloOutline==null)
{
_rettangoloOutline=新矩形();
_rettangoloOutline.Width=RettangoloProdotto.Width;
_rettangoloOutline.Height=RettangoloProdotto.Height;
_rettangoloOutline.Fill=RettangoloProdotto.Fill;
_rettangoloOutline.RenderTransform=GridMain.RenderTransform;
_不透明度=0.8;
CanvasDrag.Children.Add(_rettangoloOutline);
TopWindow.MouseLeftButtonUp+=TopWindow\u MouseLeftButtonUp;
TopWindow.MouseMove+=TopWindow\u MouseMove;
}
}
}
}
私有void TopWindow\u MouseMove(对象发送方,MouseEventArgs e)
{
如果(!_isDrag | | u rettangoloOutline==null)
返回;
#区域偏移罗他嗪
如果(罗他嗪==0)
{
delta.X=e.GetPosition(CanvasDrag).X-_-rectOutline.Width/2;
delta.Y=e.GetPosition(CanvasDrag).Y-_-rectOutline.Height/2;
}
否则如果(罗他嗪==90)
{
delta.X=e.GetPosition(CanvasDrag).X+\u rectOutline.Width/2;
delta.Y=e.GetPosition(CanvasDrag).Y-_-rectOutline.Height/2;
}
否则如果(罗他嗪==180)
{
delta.X=e.GetPosition(CanvasDrag).X+\u rectOutline.Width/2;
delta.Y=e.GetPosition(CanvasDrag).Y+\u rectoutoutline.Height/2;
}
否则如果(罗他嗪==270)
{
delta.X=e.GetPosition(CanvasDrag).X-_-rectOutline.Width/2;
delta.Y=e.GetPosition(CanvasDrag).Y+\u rectoutoutline.Height/2;
} 
#端区
Canvas.SetLeft(_rettangoloOutline,delta.X);
画布.SetTop(_rettangoloOutline,delta.Y);
_rectOutline=\u rettangoloOutline.TransformToVisual(TopWindow).TransformBounds(新的Rect(0,0,\u rettangoloOutline.Width,\u rettangoloOutline.Height));
_IsfuOriConstructionDrop1=IsfuOriConstruction(_rectanvasDrop1);
_IsfuOriRestrictDrop2=IsFuoriCon
<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>
if(rotateTransform != null)
  { RotateTransform t = RotateTransform(rotateTransform.Angle + <rotationValue>, Width/2, Height/2);
    RenderTransform = t;
  }
    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;

     }