剛開始從網上找了一個只可以完成拖動,而且控件必須設置為水平為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);
}
}
}
