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

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

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;
     }
} 

?

原文地址:https://www.cnblogs.com/lonelyxmas/p/10251558.html

时间: 2024-07-31 16:25:03

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

[转]C#鼠标拖动任意控件

C#鼠标拖动任意控件(winform) 分类: c#2011-08-15 22:51 178人阅读 评论(0) 收藏 举报 winformc#userwindowsobjectapi 1 using System.Runtime.InteropServices; 2 //并为控件 添加 MouseDown 事件 3 4 // C#鼠标拖动任意控件 5 6 // 利用Windows的API函数:SendMessage 和 ReleaseCapture 7 const uint WM_SYSCOMM

C#设置一个控件可以鼠标拖动

C#设置一个控件可以鼠标拖动: 新建一个C#项目, 创建一个label控件, 设置label的鼠标按下和抬起事件分别为:label1_MouseDown和label1_MouseUp. 对代码进行如下修改. public partial class Form1 : Form { private Point mouse_offset; public Form1() { InitializeComponent(); } private void label1_MouseUp(object sende

wpf鼠标捕获与控件交互——UIElement.CaptureMouse

应用场景是这样的,我需要拖动一个元素在屏幕上移动,注册了被移动元素的MouseMove事件,但是当鼠标移到被移动元素的外面时,移动失效,且鼠标的手势变成了普通的箭头形状,于是就找到了以下的解决方案. 本例实现了一个鼠标控制控件移动的简单例子,配合鼠标捕获达成预想效果: 1.新建一个wpf应用程序,为了演示效果,xaml简单修改如下:共有两个圆(绿.黄),下面将要实现如何用鼠标拖动他们移动. <Window x:Class="WpfApplication.MainWindow" x

WPF中一个控件绑定另一个控件的属性

原文:WPF中一个控件绑定另一个控件的属性 如同一个Grid中的一个按钮根据另一个按钮的显示与否作出不同的响应: 绑定的时候通过ElementName来指定控件 <Grid Margin="50,130"> <Grid.ColumnDefinitions> <ColumnDefinition/> <ColumnDefinition Width="40"/> </Grid.ColumnDefinitions>

WPF编程之自定义Button控件样式

自.NET Framework 3.0 以后,WPF编程框架可使开发人员开发出更加令人耳目一新的桌面应用程序.它使开发工作更加方便快捷,它将设计人员和编程人员的工作分离开来.至于WPF的背景历史.框架特点.框架结构这里就不再赘述.有兴趣的同袍可在百度搜索关于WPF的相关知识介绍,如WPF. 在微软在WPF框架里提供了一些基础功能各异的控件,例如Button.TextBox.Label.Panel.TextBlock等等.微软将这些组件可视化集成到Visual Studio集成开发工具中了,这在实

【WPF】总结窗口和控件拖拽的实现

前文 本文只对笔者学习掌握的一般的拖动问题的实现方法进行整理和讨论,包括窗口.控件等内容的拖动. 希望本文能对一些寻找此问题的解决方法的人和一些刚入门的人一些帮助.笔者为WPF初学者,能得到各位的批评指正也是荣幸万分.有更好更多的方法,劳烦与我分享,不胜感激. 本文的各种实现方法其他博客中也都有提及,很多文章内容详实,有图有代码,笔者就不重复造轮子了.就写写自己的一些理解吧. 关键词 Window, UserControls, drag, Thumb 参考资料 http://www.cnblog

ExtJs5_继承自定义一个控件

Extjs的开发都可以遵循OOP的原则,其对类的封装也很完善了.自定义一个控件最简单的办法就是继承一个已有的控件.根据上一节的需要,我做了一个Button的子类.首先根据目录结构,在app目录下建立一个ux目录,将自定义控件都放在这个目录下.在ux目录下建立一个文件ButtonTransparent.js. /** * 定义了一个背景透明的Button类,继承于Button */ Ext.define('app.ux.ButtonTransparent', { extend : 'Ext.but

wpf 用cefsharp替代web控件

碰到了一个需求,采用WPF在地图上面放置按钮并可以透明,但是如果采用wpf的webBrowser的话,兼容性不是很好,虽然实现了在其上面放置控件,但是不能透明. 看了几篇博客,有的人说是因为IE的兼容性问题,换了个思路,不用IE的浏览器好不好?这样从网上找到了cefsharp控件,这是谷歌的一个控件,具体内容可以参考博文 http://www.cnblogs.com/TianFang/p/4573324.html  现在介绍Cefsharp的安装方法 首先:打开VS2013----工具-----

转载 [WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary

[WPF][C#]在WPF中内嵌WindowsForm控件-使用WindowsFormsControlLibrary 在[WPF][C#]在WPF中内嵌WindowsForm控件一文中为各位介绍了直接在WPF中使用XAML来嵌入Windows Form控件的作法,不过不是每个人都喜欢写XAML,而且有时候会需要把已经存在的Windows Form应用程序嵌入到WPF中,所以这次就来跟大家介绍怎么使用参考dll档的方式,把dll中的Windows Form加到WPF中. 都说了要使用Windows