【问题标题】:How to make UIElement's location transform persistent?如何使 UIElement 的位置变换持久化?
【发布时间】:2020-05-14 17:12:40
【问题描述】:

在寻找在 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 之后不重置其位置?

【问题讨论】:

  • 我的回答能解决您的问题吗?如果没有,请告诉我是否可以通过改进它来提供帮助。

标签: c# wpf location rendertransform


【解决方案1】:

我没有发现 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;
        }

【讨论】:

  • 不幸的是,瓷砖仍然不停地跳来跳去。我很惊讶它确实在没有使用 MouseLeftButtonDown 的情况下移动,但根据我的经验,省略它时它的响应速度较慢。
【解决方案2】:

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 是这里的关键。 :)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-11-02
    • 2019-12-17
    • 2011-11-20
    • 2010-09-29
    • 2019-12-27
    • 2023-02-23
    • 2020-10-17
    • 2018-12-20
    相关资源
    最近更新 更多