silverlight智能表单实现代码
控件从工具箱到画板的拖动让我想到了tookit中dragdroptarget控件,工具箱好说用listbox或者treeview,画板就不知道怎么搞了,于是决定自己做dragdrop。
左侧的是一个listbox,右侧红色的是canvas。创建一个类库dragdroplibrary(这个名不知道好不好听)。
点击左侧的listbox,然后移动鼠标到右侧红色部分,松开鼠标控件就放到松开的位置,思路就这么简单。
listbox的xaml:(controls = new string[3] { "textbox", "button", "textblock" };这个是给listbox的数据,测试。。。)
item就一个textblock,我们要注册mouseleftbuttondown事件。
在dragdroplibrary中添加一个类:
show sourceview sourceprint?01 using system.windows;
02 using system.windows.controls;
03 using system.windows.input;
04 using system.windows.media;
05 using system.windows.media.imaging;
06
07 namespace dragdroplibrary
08 {
09 public static class dragdropmanage
10 {
11 private static panel _root, _board;
12 //drop
13 public delegate void drop(dragdropeventargs target);
14 private static drop _ondrag;
15 private static dragdropeventargs eveargs;
16
17 //鼠标拖动时跟随效果
18 private static image _mouseeffert;
19
20 ///
21 /// 拖动之前调用
22 ///
23 /// 根panel(children中包含工具箱和画板)
24 /// 画板
25 public static void register(panel root, panel board)
26 {
27 _root = root;
28 _board = board;
29 if (_root is grid)
30 {
31 grid.setcolumnspan(_mouseeffert, (_root as grid).columndefinitions.count+1);
32 grid.setrowspan(_mouseeffert, (_root as grid).rowdefinitions.count+1);
33 }
34 }
35
36 static dragdropmanage()
37 {
38 _mouseeffert = new image();
39 }
40
41 public static void begindrag(object sender, mousebuttoneventargs e, drop drop)
42 {
43 frameworkelement target = sender as frameworkelement;
44 writeablebitmap bitmap = new writeablebitmap(target, new translatetransform());
45 _mouseeffert.source =bitmap;
46 _mouseeffert.height = bitmap.pixelheight;
47 _mouseeffert.width = bitmap.pixelwidth;
48 _root.children.add(_mouseeffert);
49 point position = e.getposition(_root);
50 _mouseeffert.margin = new thickness(position.x, position.y, 0, 0);
51
52 _mouseeffert.horizontalalignment = horizontalalignment.left;
53 _mouseeffert.verticalalignment = verticalalignment.top;
54 _mouseeffert.capturemouse();
55 eveargs = new dragdropeventargs(target);
56
57 _ondrag = drop;
58 _root.mousemove += onrootmousemove;
59 _root.mouseleftbuttonup += onrootmouseleftbuttonup;
60 }
61
62 private static void clear()
63 {
64 _root.mousemove -= onrootmousemove;
65 _root.mouseleftbuttonup -= onrootmouseleftbuttonup;
66 _root.children.remove(_mouseeffert);
67 _ondrag = null;
68 eveargs = null;
69 }
70
71 private static void onrootmouseleftbuttonup(object sender, mousebuttoneventargs e)
72 {
73 eveargs.position = e.getposition(_board);
74 _ondrag(eveargs);
75 clear();
76 }
77
78 private static void onrootmousemove(object sender, mouseeventargs e)
79 {
80 point position = e.getposition(_root);
81 _mouseeffert.margin = new thickness(position.x, position.y, 0, 0);
82
83 point currentposition = e.getposition(_board);
84 if (currentposition.x > 0 && currentposition.x < _board.actualwidth
85 && currentposition.y > 0 && currentposition.y < _board.actualheight)
86 {
87 eveargs.accept = true;
88 }
89 else
90 {
91 eveargs.accept = false;
92 }
93 }
94 }
95 }
show sourceview sourceprint?01 using system;02 using system.windows;
03
04 namespace dragdroplibrary
05 {
06 public class dragdropeventargs : eventargs
07 {
08 public bool accept { get; set; }
09
10 public point position { get; internal set; }
11
12 public frameworkelement target { get; private set; }
13
14 public dragdropeventargs(frameworkelement target)
15 {
16 target = target;
17 position = new point(0, 0);
18 }
19 }
20 }
dragdropmanage我做成了静态类,我的电脑只有一个鼠标,而且我也没有多点触控的装备,不知道多点触控能不能同时托两个或者更多控件。
在最最最开始,我们需要初始化dragdroplibrary.dragdropmanage.register(layoutroot, boardcanvas);
layoutroot这个都知道,就是程序的根容器,boardcanvas就是上面说的红色的canvas。
textblock鼠标点击事件,这时我们就开始拖动了。drop1是一个方法,用来当我们松开鼠标时的回调方法。
private void onlistboxitemmouseleftbuttondown(object sender, mousebuttoneventargs e)
{
dragdroplibrary.dragdropmanage.begindrag(sender, e, drop1);
}
show sourceview sourceprint?01 public void drag1(dragdroplibrary.dragdropeventargs target)
02 {
03 if (target.accept)
04 {
05 string name = (target.target as textblock).text;
06 frameworkelement element = null;
07
08 type type = gettypefromstring(name);
09 if (type != null)
10 {
11 element = activator.createinstance(type) as frameworkelement;
12
13 if (target.position != null)
14 {
15 canvas.setleft(element, target.position.x);
16 canvas.settop(element, target.position.y);
17 }
18
19 element.;
20 element.;
21
22 boardcanvas.children.add(element);
23 }
24 }
25 }
26 private type gettypefromstring(string typename)
27 {
28 type type = null;
29 typename = "system.windows.controls." + typename;
30 assembly assembly = assembly.load("system.windows, version=2.0.5.0, culture=neutral, publickeytoken=7cec85d7bea7798e");
31
32 type = assembly.gettype(typename);
33 return type;
34 }
在drop1中target是listbox中的textblock所以直接转了。
几点说明:
1.dragdropeventargs中accept是用来说明,松开鼠标时,当前鼠标的位置是不是落在canvas中。position指示当前位置
2.dragdropeventargs中target是鼠标点击时的控件。
3.生成控件我是根据名称和程序集,这两个东西获取的,一开始我设想的就是把所有的控件存到xml文件中,包括他的中文名,全名,以及程序集,这样listbox中的控件就可以反射出来了。
4.拖动时要在根容器中注册mousemove事件以及mousedown。
5.打了个漫长的电话就不知道该说些什么了,今天周五,各位大侠玩的开心。