如何使 UIElement 的位置变换持久化?
How to make UIElement's location transform persistent?
在寻找在 WPF 中拖动 UIElement 的方法时,我遇到了一些代码并一直在试验它。单击元素时,它会很好地跟随鼠标,但在随后的拖动事件中,元素会自行重置到其原始位置。
xaml 设置:非常简单,只是一个具有最原始名称的命名 Canvas 和元素,在本例中是一个网格,称为 Tile1。
<Grid>
<Canvas x:Name="Canvas" Width="200" Height="300" Background="LightGray">
<Grid x:Name="Tile1">
<Border BorderBrush="Black" BorderThickness="1" Background="White">
<Control Width="25" Height="25"/>
</Border>
</Grid>
</Canvas>
</Grid>
一些代码隐藏:
public TranslateTransform transPoint;
public Point originPoint;
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonDown += Tile1_MouseLeftButtonDown;
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var myLocation = e.GetPosition(Canvas);
originPoint = new Point(myLocation.X, myLocation.Y);
transPoint = new TranslateTransform(originPoint.X, originPoint.Y);
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
var mouseLocation = e.GetPosition(Canvas);
if (e.LeftButton == MouseButtonState.Pressed)
{
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocationOnCanvas = e.GetPosition(Canvas);
var mouseLocationOnTile = e.GetPosition(Tile1);
//attempting to account for offset of mouse on the Tile:
var newX = mouseLocationOnCanvas.X - mouseLocationOnTile.X;
var newY = mouseLocationOnCanvas.Y - mouseLocationOnTile.Y;
Tile1.Margin = new Thickness(newX, newY, 0, 0);
}
在原始示例中(添加了参考 here)甚至没有使用 MouseUpEvent。没有它,我的元素只会在每次 MouseDragEvent 时重置到其原始位置 0,0。有了它,它就会到处乱跳。
我的思路是以某种方式将元素的当前位置设置为 MouseUpEvent 发生的位置。
我一直在摆弄不同的东西,因为这个特殊的东西对我来说是相当新的。例如:Tile1.TransformToAncestor(Canvas).Transform(mouseLocation);
我还发现 VisualOffset 有我需要的信息,所以在重置之前它已经以某种方式存储在对象上,但我还没有找到以任何形式访问它的方法。
Tile1.SetValue(VisualOffset.X = ...);
或 Tile1Grid.GetValue(VisualOffset);
所以基本上,有没有办法让元素在 RenderTransform 之后不重置其位置?
我发现 MouseLeftButtonDown
事件没有用,所以我删除了它:
我注意到移动鼠标时有些延迟可能会很烦人,也许事件需要 运行 异步 MouseMove performance slow using GetPosition。
public TranslateTransform transPoint = new TranslateTransform(0, 0);
public Point originPoint = new Point(0, 0);
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mouseLocation = e.GetPosition(Canvas);
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocation = e.GetPosition(Tile1);
originPoint.X = mouseLocation.X;
originPoint.Y = mouseLocation.Y;
}
RenderTransform 似乎不稳定,但我在使用以下方法移动 UIElement 后将它留在原处:
private void MovableTile_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
tile.CaptureMouse();
}
和
private void MovableTile_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var tile = sender as UIElement;
var mousePosition = e.GetPosition(canvas);
Canvas.SetLeft(tile, mousePosition.X);
Canvas.SetTop(tile, mousePosition.Y);
}
}
然后
private void MovableTile_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
tile.ReleaseMouseCapture();
}
MouseCapture 是这里的关键。 :)
在寻找在 WPF 中拖动 UIElement 的方法时,我遇到了一些代码并一直在试验它。单击元素时,它会很好地跟随鼠标,但在随后的拖动事件中,元素会自行重置到其原始位置。
xaml 设置:非常简单,只是一个具有最原始名称的命名 Canvas 和元素,在本例中是一个网格,称为 Tile1。
<Grid>
<Canvas x:Name="Canvas" Width="200" Height="300" Background="LightGray">
<Grid x:Name="Tile1">
<Border BorderBrush="Black" BorderThickness="1" Background="White">
<Control Width="25" Height="25"/>
</Border>
</Grid>
</Canvas>
</Grid>
一些代码隐藏:
public TranslateTransform transPoint;
public Point originPoint;
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonDown += Tile1_MouseLeftButtonDown;
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
var myLocation = e.GetPosition(Canvas);
originPoint = new Point(myLocation.X, myLocation.Y);
transPoint = new TranslateTransform(originPoint.X, originPoint.Y);
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
var mouseLocation = e.GetPosition(Canvas);
if (e.LeftButton == MouseButtonState.Pressed)
{
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocationOnCanvas = e.GetPosition(Canvas);
var mouseLocationOnTile = e.GetPosition(Tile1);
//attempting to account for offset of mouse on the Tile:
var newX = mouseLocationOnCanvas.X - mouseLocationOnTile.X;
var newY = mouseLocationOnCanvas.Y - mouseLocationOnTile.Y;
Tile1.Margin = new Thickness(newX, newY, 0, 0);
}
在原始示例中(添加了参考 here)甚至没有使用 MouseUpEvent。没有它,我的元素只会在每次 MouseDragEvent 时重置到其原始位置 0,0。有了它,它就会到处乱跳。
我的思路是以某种方式将元素的当前位置设置为 MouseUpEvent 发生的位置。
我一直在摆弄不同的东西,因为这个特殊的东西对我来说是相当新的。例如:Tile1.TransformToAncestor(Canvas).Transform(mouseLocation);
我还发现 VisualOffset 有我需要的信息,所以在重置之前它已经以某种方式存储在对象上,但我还没有找到以任何形式访问它的方法。
Tile1.SetValue(VisualOffset.X = ...);
或 Tile1Grid.GetValue(VisualOffset);
所以基本上,有没有办法让元素在 RenderTransform 之后不重置其位置?
我发现 MouseLeftButtonDown
事件没有用,所以我删除了它:
我注意到移动鼠标时有些延迟可能会很烦人,也许事件需要 运行 异步 MouseMove performance slow using GetPosition。
public TranslateTransform transPoint = new TranslateTransform(0, 0);
public Point originPoint = new Point(0, 0);
public MainWindow()
{
InitializeComponent();
Tile1.MouseLeftButtonUp += Tile1_MouseLeftButtonUp;
Tile1.MouseMove += Tile1_MouseMove;
}
private void Tile1_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var mouseLocation = e.GetPosition(Canvas);
transPoint.X = (mouseLocation.X - originPoint.X);
transPoint.Y = (mouseLocation.Y - originPoint.Y);
Tile1.RenderTransform = transPoint;
}
}
private void Tile1_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
var mouseLocation = e.GetPosition(Tile1);
originPoint.X = mouseLocation.X;
originPoint.Y = mouseLocation.Y;
}
RenderTransform 似乎不稳定,但我在使用以下方法移动 UIElement 后将它留在原处:
private void MovableTile_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
tile.CaptureMouse();
}
和
private void MovableTile_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
var tile = sender as UIElement;
var mousePosition = e.GetPosition(canvas);
Canvas.SetLeft(tile, mousePosition.X);
Canvas.SetTop(tile, mousePosition.Y);
}
}
然后
private void MovableTile_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
tile.ReleaseMouseCapture();
}
MouseCapture 是这里的关键。 :)