欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

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

程序员文章站 2022-03-03 08:39:59
目录一、如何实现?1.注册鼠标事件2.记录位置3.跟随鼠标移动4.恢复标识二、示例前言:有一些业务场景中我们需要拖动控件,在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>


效果预览:

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

总结:

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

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