基于C# wpf 实现Grid内控件拖动详情

 更新时间:2021年11月20日 12:59:55   作者:Alfred-N  
这篇文章主要介绍了基于C# wpf 实现Grid内控件拖动,有一些业务场景中我们需要拖动控件,在Grid中就可以实现控件拖动,通过设置Margin属性即可,下面文章我们来看看具体的实现内容

前言:

有一些业务场景中我们需要拖动控件,在Grid中就可以实现控件拖动,通过设置Margin属性即可,根据鼠标的移动,设置相应的MarginLeft、Top,当然有时也不是直接设置的,需要根据HorizontalAlignmentVerticalAlignment值有不同的计算方法。

一、如何实现?

1.注册鼠标事件

拖动的控件需要注册3个鼠标事件分别是,鼠标按下、鼠标移动、鼠标弹起。

以Button为例:

<Button   PreviewMouseDown="Button_MouseDown" 
          PreviewMouseMove="Button_MouseMove" 
          PreviewMouseUp="Button_MouseUp"> </Button>

2.记录位置

在鼠标按下事件中记录位置。

//鼠标是否按下
bool _isMouseDown = false;
//鼠标按下的位置
Point _mouseDownPosition;
//鼠标按下控件的Margin
Thickness _mouseDownMargin;
//鼠标按下事件
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
 
    var c = sender as Control;
    _isMouseDown = true;
    _mouseDownPosition = e.GetPosition(this);
    _mouseDownMargin = c.Margin;
}

3.跟随鼠标移动

鼠标按下后移动鼠标,控件需要跟随鼠标移动。根据HorizontalAlignmentVerticalAlignment值不同,计算Margin的方式也不同。

private void Button_MouseMove(object sender, MouseEventArgs e)
{
 
    if (_isMouseDown)
    {
 
        var c = sender as Control;
        var pos = e.GetPosition(this);
        var dp = pos - _mouseDownPosition;
        double left, top, right, bottom;
        if (c.HorizontalAlignment == HorizontalAlignment.Stretch|| c.HorizontalAlignment == HorizontalAlignment.Center)
        //中央移动距离是双倍
        {
 
            left= _mouseDownMargin.Left+ dp.X * 2;
            right = _mouseDownMargin.Right;
        }
        else if(c.HorizontalAlignment== HorizontalAlignment.Left)
        //左边是正常距离
        {
 
            left = _mouseDownMargin.Left + dp.X ;
            right = _mouseDownMargin.Right;
        }
        else
        //右边是右边距距离
        {
 
            left = _mouseDownMargin.Left;
            right = _mouseDownMargin.Right - dp.X;
        }
        if (c.VerticalAlignment == VerticalAlignment.Stretch || c.VerticalAlignment == VerticalAlignment.Center)
        //中央移动距离是双倍
        {
 
            top = _mouseDownMargin.Top+ dp.Y* 2;
            bottom = _mouseDownMargin.Bottom;
        }
        else if (c.VerticalAlignment == VerticalAlignment.Top)
        //顶部是正常距离
        {
 
            top = _mouseDownMargin.Top + dp.Y ;
            bottom = _mouseDownMargin.Bottom;
        }
        else
        //底部是底边距距离
        {
 
            top = _mouseDownMargin.Top ;
            bottom = _mouseDownMargin.Bottom- dp.Y;
        }
        c.Margin = new Thickness(left, top, right, bottom);
    }
}

4.恢复标识

鼠标弹起后需要恢复标识,让控件不再跟随鼠标移动。

private void Button_MouseUp(object sender, MouseButtonEventArgs e)
{
 
    if (_isMouseDown)
    {
 
        _isMouseDown = false;
        //移动了的控件不响应点击事件(此处根据具体需求)
        e.Handled = true;
    }
}

二、示例

示例代码:

<Window x:Class="WpfControlMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfControlMove"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640">
    <Grid>
        <Button Width="120" Height="50" Content="移动"   PreviewMouseDown="Button_MouseDown" PreviewMouseMove="Button_MouseMove" PreviewMouseUp="Button_MouseUp"> </Button>
    </Grid>
</Window>


效果预览:

总结:

本文说明了Grid中控件拖动的方法。方法采用了记录鼠标位置以及控件位置的方法来确保准确的相对位置。如果是采用只记录鼠标位置,计算时通过控件内部坐标差值累加,这样会产生累计误差,除非取整运算,但取整与dpi有可能产生不兼容。总的来说,本方法采用准确的位置计算方式,而且还根据不同停靠采用相应的计算方法,适用性较好。

到此这篇关于基于C# wpf 实现Grid内控件拖动详情的文章就介绍到这了,更多相关C# wpf 实现Grid内控件拖动内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 关于C#调用C++dll传指针释放内存问题

    关于C#调用C++dll传指针释放内存问题

    这篇文章主要介绍了关于C#调用C++dll传指针释放内存问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-12-12
  • 详解c# SpinWait

    详解c# SpinWait

    这篇文章主要介绍了c# SpinWait的相关资料,帮助大家更好的理解和学习c# 编程,感兴趣的朋友可以了解下
    2020-10-10
  • C#如何更改Word的语言设置

    C#如何更改Word的语言设置

    这篇文章主要为大家详细介绍了C#如何更改Word的语言设置,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • Silverlight将图片转换为byte的实现代码

    Silverlight将图片转换为byte的实现代码

    这篇文章主要介绍了Silverlight将图片转换为byte的实现代码,需要的朋友可以参考下
    2015-11-11
  • winform模拟鼠标按键的具体实现

    winform模拟鼠标按键的具体实现

    这篇文章介绍了winform模拟鼠标按键的具体实现,有需要的朋友可以参考一下
    2013-10-10
  • C#中面向对象编程机制之多态学习笔记

    C#中面向对象编程机制之多态学习笔记

    这篇文章主要介绍了C#中面向对象编程机制之多态学习笔记,本文总结了个人对多态的理解以及接口多态、继承多态等内容,并给出了代码示例,需要的朋友可以参考下
    2015-01-01
  • C# 面向对象的基本原则

    C# 面向对象的基本原则

    什么是面向对象的基本原则?设计原则是基本的工具,应用这些规则可以使你的代码更加灵活、更容易维护,更容易扩展。
    2009-11-11
  • C#使用ZBar实现识别条形码

    C#使用ZBar实现识别条形码

    目前主流的识别库主要有ZXing.NET和ZBar,本文主要介绍的是如何使用ZBar库实现识别条形码功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下
    2023-07-07
  • C#实现异步发送邮件的方法

    C#实现异步发送邮件的方法

    这篇文章主要介绍了C#实现异步发送邮件的方法,涉及C#异步操作与邮件发送的技巧,非常具有实用价值,需要的朋友可以参考下
    2015-04-04
  • C# 16 进制字符串转 int的方法

    C# 16 进制字符串转 int的方法

    这篇文章主要介绍了C# 16 进制字符串转 int的方法,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2018-04-04

最新评论