wpf在窗口的控件拖动、点击窗口中控件显示在最上面以及控件拖动不超过窗口边界
刚开始从网上找了一个只可以完成拖动,而且控件必须设置为水平为left、垂直为top才能正常移动,因此很不方便,所以就在此基础上修改了一下代码,然后不管设置任何水平和垂直都可以完成拖动,后来又有了新的需求,拖动时会超过边界,刚开始弄了半天实现了没有设置水平和垂直的控件,设置了水平和垂直只能在设置了的方向才能移动,弄了一周在窗口不改变大小的情况可以正常实现了,但是一放大窗口又不行了,就在之前的代码上改,结果发现一句代码就实现了,之前写的代码都是无用功的,走了弯路,因此写下这篇博客,希望后面的小伙伴不要走同样的弯路。主要代码如下。
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace WpfComboBox.Entity
{
public class InitDrag
{
private int totalZIndex = 100;
private IEnumerable<UIElement> DragElements { get; set; }
private FrameworkElement WindowElement;
public void Drag(IEnumerable<UIElement> dragElements, FrameworkElement windowElement)
{
WindowElement = windowElement;
DragElements = dragElements;
//WPF设计上的问题,Button.Clicked事件Supress掉了Mouse.MouseLeftButtonDown附加事件等.
//不加这个Button、TextBox等无法拖动
foreach (UIElement uiEle in DragElements)
{
uiEle.AddHandler(Button.MouseLeftButtonDownEvent, new MouseButtonEventHandler(Element_MouseLeftButtonDown), true);
uiEle.AddHandler(Button.MouseMoveEvent, new MouseEventHandler(Element_MouseMove), true);
uiEle.AddHandler(Button.MouseLeftButtonUpEvent, new MouseButtonEventHandler(Element_MouseLeftButtonUp), true);
}
}
bool isDragDropInEffect = false;
Point pos = new Point();
void Element_MouseMove(object sender, MouseEventArgs e)
{
if (isDragDropInEffect)
{
FrameworkElement currEle = sender as FrameworkElement;
double xPos = e.GetPosition(null).X - pos.X + currEle.Margin.Left;
double yPos = e.GetPosition(null).Y - pos.Y + currEle.Margin.Top;
double rPos = pos.X - e.GetPosition(null).X + currEle.Margin.Right;
double bPos = pos.Y - e.GetPosition(null).Y + currEle.Margin.Bottom;
if (xPos >= 0 && rPos >= 0 && yPos >= 0 && bPos >= 0)
{
currEle.Margin = new Thickness(xPos, yPos, rPos, bPos);
}
pos = e.GetPosition(null);
}
}
void Element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
FrameworkElement fEle = sender as FrameworkElement;
totalZIndex++;
Canvas.SetZIndex(fEle, totalZIndex);
isDragDropInEffect = true;
pos = e.GetPosition(null);
fEle.CaptureMouse();
fEle.Cursor = Cursors.Hand;
SetMargin(fEle);
}
/// <summary>
/// 设置上下左右边距
/// </summary>
/// <param name="fEle"></param>
private void SetMargin(FrameworkElement fEle)
{
//取得控件在窗口中的坐标
Window wind = Window.GetWindow(fEle);
Point point = fEle.TransformToAncestor(wind).Transform(new Point(0, 0));
//得到窗体的标题高度和窗口外边宽度
var verticalBorderWidth = SystemParameters.ResizeFrameVerticalBorderWidth;
var titleHeight = SystemParameters.WindowCaptionHeight + SystemParameters.ResizeFrameHorizontalBorderHeight;
double x = point.X;
double y = point.Y;
double right = WindowElement.ActualWidth - fEle.ActualWidth - x - 4 * verticalBorderWidth;
double bottom = WindowElement.ActualHeight - fEle.ActualHeight - y - titleHeight - 3 * verticalBorderWidth;
fEle.Margin = new Thickness(x, y, right, bottom);
}
void Element_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (isDragDropInEffect)
{
FrameworkElement ele = sender as FrameworkElement;
isDragDropInEffect = false;
ele.ReleaseMouseCapture();
}
}
}
}
在wpf窗体中使用的代码:
namespace WpfComboBox
{
/// <summary>
/// Window3.xaml 的交互逻辑
/// </summary>
public partial class Window3 : Window
{
public Window3()
{
InitializeComponent();
InitDrag initDrag=new InitDrag();
var DragElements = new List<UIElement>() { button1, button2, Grid, label1, Grid1,button };
initDrag.Drag(DragElements, Window);
}
}
}