我正在开发一个应用程序,我必须在画布上拖动用户控件。
该用户控件可以在正常位置拖动或以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 :(得分:0)
只需将RotateTransform的centerX和centerY值设置为旋转元素的半宽和半高。这样,您可以将对象相对于其父级中的位置拖动,就像在未旋转时一样。
示例:
class SubView: UIImageView {
var mySubView: UIImageView
required init?(coder aDecoder: NSCoder) {
mySubView = UIImageView()
mySubView.backgroundColor = UIColor.cyan
super.init(coder: aDecoder)
self.addSubview(mySubView)
mySubView.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true
mySubView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
mySubView.widthAnchor.constraint(equalTo: widthAnchor).isActive = true
mySubView.heightAnchor.constraint(equalTo: heightAnchor).isActive = true
}
}
在MouseMove-Handler中,您无需调整运动:
if(rotateTransform != null)
{ RotateTransform t = RotateTransform(rotateTransform.Angle + <rotationValue>, Width/2, Height/2);
RenderTransform = t;
}
希望这有帮助!
干杯,
亚历