WPF 使用鼠标拖动一个控件的实现[2018.7.15]

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/u010469446/article/details/81056430

Q:已经把一个Shape和一个TextBlock组合起来放到了一个Grid中,现在想要实现用鼠标拖动这个Grid到任意位置的功能,如何做?

<Grid Height="50" Width="50">
    <Ellipse Fill="Yellow" Stroke="Blue" Height="50" Width="50" HorizontalAlignment="Left"></Ellipse>
    <TextBlock Text="5" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
</Grid>

A:在stackoverflow上找到解决方法。首先,为这个Grid添加三个鼠标事件

<Grid Height="50" Width="50" MouseLeftButtonDown="grid_MouseLeftButtonDown" MouseLeftButtonUp="
    grid_MouseLeftButtonUp" MouseMove="grid_MouseMove">
    <Ellipse Fill="Yellow" Stroke="Blue" Height="50" Width="50" HorizontalAlignment="Left"></Ellipse>
    <TextBlock Text="5" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
</Grid>

 

在cs文件中为这三个事件添加实现:

private bool isDragging;
private Point clickPosition;

private void grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    isDragging = true;
    var draggableElement = sender as UIElement;
    clickPosition = e.GetPosition(this);
    draggableElement.CaptureMouse();
}

private void grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    isDragging = false;
    var draggableElement = sender as UIElement;
    draggableElement.ReleaseMouseCapture();
}

private void grid_MouseMove(object sender, MouseEventArgs e)
{
    var draggableElement = sender as UIElement;
    if (isDragging && draggableElement != null)
    {
        Point currentPosition = e.GetPosition(this.Parent as UIElement);
        var transform = draggableElement.RenderTransform as TranslateTransform;
        if (transform == null)
        {
            transform = new TranslateTransform();
            draggableElement.RenderTransform = transform;
        }
        transform.X = currentPosition.X - clickPosition.X;
        transform.Y = currentPosition.Y - clickPosition.Y;
     }
} 

 

      每个控件有一个RenderTransform属性,它接收一个对象。TranslateTransform是RenderTransform的一个子类,它的实例可以赋给控件的RenderTransform属性,表示以当前控件为原点进行的平移操作。

    【---2018.7.17添加---】 

     上面这段c#代码有问题。当拖动控件移动后,松开鼠标,如果再次想要拖动该控件,在鼠标刚按下时控件会回到原点。

      出现这个问题是因为在MouseLeftButtonDown事件发生后,立即发生MouseMove事件,currentPosition和clickPosition相等,导致transform的X和Y属性都为0。从而grid的RenderTransform属性指示将控件重新绘制在grid的起始位置。

      对于RenderTransform属性来说,原点是多少?应该是grid控件对象被创建时的坐标。RenderTransform指示的移动都是以这个坐标轴为参考的。

       解决这个问题的方法是,在grid_MouseMove()中,每次移动的时候,要加上上一次拖拽结束时控件的相对坐标。

       首先为这个grid添加一个名字,并使用RenderTransform属性

<Grid Height="50" Width="50" Name="myGrid" MouseLeftButtonDown="grid_MouseLeftButtonDown" MouseLeftButtonUp="
    grid_MouseLeftButtonUp" MouseMove="grid_MouseMove">
    <Ellipse Fill="Yellow" Stroke="Blue" Height="50" Width="50" HorizontalAlignment="Left"></Ellipse>
    <TextBlock Text="5" TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>
    <Grid.RenderTransform>
        <TranslateTransform x:Name="tt" />
    </RenderTransform>
</Grid>

    然后,将cs代码中的clickPosition取消,换一个名字,比如叫startPosition,用来记录该控件在任一时刻离自己的原点的相对坐标。在grid_MouseLeftButtonDown方法中,不记录鼠标点击的位置坐标,而是记录鼠标被按下时这个位置离控件原点的距离,即刚刚定义的startPosition。

      在grid_MouseMove方法中,由于grid的RenderTransform早有定义,所以不用进行是否null的判断。之后transform变量的值,应该为当前坐标currentPosition与参考点startPosition之差。

private bool isDragging;
private Point startPosition;

private void grid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    isDragging = true;
    var draggableElement = sender as UIElement;
    var clickPosition = e.GetPosition(this);

    var transform = draggableElement.RenderTranform as TranslateTransform;
    startPosition.X = clickPosition.X - transform.X;    //注意减号
    startPosition.Y = clickPosition.Y - transform.Y;

    draggableElement.CaptureMouse();
}

private void grid_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
    isDragging = false;
    var draggableElement = sender as UIElement;
    draggableElement.ReleaseMouseCapture();
}

private void grid_MouseMove(object sender, MouseEventArgs e)
{
    var draggableElement = sender as UIElement;
    if (isDragging && draggableElement != null)
    {
        Point currentPosition = e.GetPosition(this.Parent as UIElement);
        var transform = draggableElement.RenderTransform as TranslateTransform;

        transform.X = currentPosition.X - startPosition.X;
        transform.Y = currentPosition.Y - startPosition.Y;
     }
} 

 

展开阅读全文

没有更多推荐了,返回首页