上一篇,我们实现了基本拖拽操作,今天,我们来实现,拖拽过程中鼠标跟随效果,这里我们要用到WPF新对象Adorner(装饰器)用来显示拖拽内容,如我们今天拖拽的矩形。首先,我们新建一个DragAdorner类,继承Adorner用来显示拖拽内容,代码如下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
public
class
DragAdorner : Adorner
{
#region 变量
protected
UIElement _child;
protected
VisualBrush _brush;
protected
UIElement _owner;
protected
double
XCenter;
protected
double
YCenter;
private
double
_leftOffset;
private
double
_topOffset;
public
double
Scale = 1.0;
#endregion
#region 构造函数
public
DragAdorner(UIElement owner) :
base
(owner) { }
public
DragAdorner(UIElement owner, UIElement adornElement,
double
opacity)
:
base
(owner)
{
this
._owner = owner;
VisualBrush _brush =
new
VisualBrush(adornElement);
_brush.Opacity = opacity;
Rectangle r =
new
Rectangle();
r.RadiusX = 3;
r.RadiusY = 3;
r.Width = adornElement.DesiredSize.Width;
r.Height = adornElement.DesiredSize.Height;
XCenter = adornElement.DesiredSize.Width / 2;
YCenter = adornElement.DesiredSize.Height / 2;
r.Fill = _brush;
this
._child = r;
}
#endregion
#region 属性
public
double
LeftOffset
{
get
{
return
this
._leftOffset; }
set
{
this
._leftOffset = value - XCenter;
this
.UpdatePosition();
}
}
public
double
TopOffset
{
get
{
return
this
._topOffset; }
set
{
this
._topOffset = value - YCenter;
this
.UpdatePosition();
}
}
protected
override
int
VisualChildrenCount
{
get
{
return
1;
}
}
#endregion
#region 方法
private
void
UpdatePosition()
{
AdornerLayer adorner = (AdornerLayer)
this
.Parent;
if
(adorner !=
null
)
{
adorner.Update(
this
.AdornedElement);
}
}
protected
override
Visual GetVisualChild(
int
index)
{
return
_child;
}
protected
override
Size MeasureOverride(Size finalSize)
{
this
._child.Measure(finalSize);
return
this
._child.DesiredSize;
}
protected
override
Size ArrangeOverride(Size finalSize)
{
this
._child.Arrange(
new
Rect(_child.DesiredSize));
return
finalSize;
}
public
override
GeneralTransform GetDesiredTransform(GeneralTransform transform)
{
GeneralTransformGroup result =
new
GeneralTransformGroup();
result.Children.Add(
base
.GetDesiredTransform(transform));
result.Children.Add(
new
TranslateTransform(
this
._leftOffset,
this
._topOffset));
return
result;
}
#endregion
}
|
我们声明几个对象,并且修改上篇代码中矩形的PreviewMouseMove事件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
|
/// <summary>
/// 拖动的区域
/// </summary>
private
FrameworkElement _dragScope;
/// <summary>
/// 用于显示鼠标跟随效果的装饰器
/// </summary>
private
DragAdorner _adorner;
/// <summary>
/// 用于呈现DragAdorner的图画
/// </summary>
private
AdornerLayer _layer;
void
rectangle1_PreviewMouseMove(
object
sender, MouseEventArgs e)
{
if
(e.LeftButton == MouseButtonState.Pressed)
{
this
.StartDrag(e);
}
}
private
void
StartDrag(MouseEventArgs e)
{
this
._dragScope = Application.Current.MainWindow.Content
as
FrameworkElement;
this
._dragScope.AllowDrop =
true
;
DragEventHandler draghandler =
new
DragEventHandler(DragScope_PreviewDragOver);
this
._dragScope.PreviewDragOver += draghandler;
this
._adorner =
new
DragAdorner(
this
._dragScope, (UIElement)
this
.rectangle1, 0.5);
this
._layer = AdornerLayer.GetAdornerLayer(
this
._dragScope
as
Visual);
this
._layer.Add(
this
._adorner);
DataObject data =
new
DataObject(
typeof
(Rectangle),
this
.rectangle1);
DragDrop.DoDragDrop(
this
.rectangle1, data, DragDropEffects.Move);
AdornerLayer.GetAdornerLayer(
this
._dragScope).Remove(
this
._adorner);
this
._adorner =
null
;
this
._dragScope.PreviewDragOver -= draghandler;
}
void
DragScope_PreviewDragOver(
object
sender, DragEventArgs args)
{
if
(
this
._adorner !=
null
)
{
this
._adorner.LeftOffset = args.GetPosition(
this
._dragScope).X;
this
._adorner.TopOffset = args.GetPosition(
this
._dragScope).Y;
}
|
这样,就实现了,拖拽过程中显示跟随效果。关键代码就在StartDrag(MouseEventArgs)方法中,开始拖放的时候创建显示拖拽的对象,移动过程中更改装饰坐标,鼠标释放的时候移除装饰对象。看懂了之后,会发现WPF的拖拽并不复杂,但是,如何实现不同窗体之间的拖拽呢?后面我们会做介绍。