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