Silverlight中的Behavior
上次写了关于Trigger和Action的文章(Silverlight中的Action和Trigger),这次写一个Behavior的。Behavior的目的在于封装部分UI功能,那样就可以直接应用于元素而不用写任何代码。Behavior是一组相关操作的组合,它包含了Trigger和Action的工作。简单的说就是Trigger和Action的合体。
听说过Behavior的人一说到Behavior很容易想到拖动效果,这里我就做一个简单的在Canvas里的拖动行为。创建自定义Behavior需要从Behavior<DependencyObject>继承,并覆盖OnAttached和OnDetaching方法(和Trigger差不多)。还是用代码说话方便。
新建一个Behavior如下:
1: public class Behavior1 : Behavior<Shape>
2: {
3: private Canvas _canvas;
4: private bool _isDraging;
5: private Point _originalMousePosition;
6:
7: public Behavior1()
8: {
9: _isDraging = false;
10: }
11:
12: protected override void OnAttached()
13: {
14: base.OnAttached();
15: this.AssociatedObject.MouseLeftButtonDown += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
16: this.AssociatedObject.MouseMove += new MouseEventHandler(AssociatedObject_MouseMove);
17: this.AssociatedObject.MouseLeftButtonUp += new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
18: }
19:
20: protected override void OnDetaching()
21: {
22: base.OnDetaching();
23: this.AssociatedObject.MouseLeftButtonDown -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonDown);
24: this.AssociatedObject.MouseMove -= new MouseEventHandler(AssociatedObject_MouseMove);
25: this.AssociatedObject.MouseLeftButtonUp -= new MouseButtonEventHandler(AssociatedObject_MouseLeftButtonUp);
26: }
27:
28: private void AssociatedObject_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
29: {
30: _canvas = (Canvas)VisualTreeHelper.GetParent(this.AssociatedObject);
31: _originalMousePosition = e.GetPosition(_canvas);
32: _isDraging = true;
33: this.AssociatedObject.CaptureMouse();
34: }
35:
36: private void AssociatedObject_MouseMove(object sender, MouseEventArgs e)
37: {
38: if (_isDraging)
39: {
40: //get the current mouse position
41: Point currentMousePosition = e.GetPosition(_canvas);
42: //calculate the current position of the shape
43: this.AssociatedObject.SetValue(Canvas.LeftProperty, ((double)this.AssociatedObject.GetValue(Canvas.LeftProperty)) + (currentMousePosition.X - _originalMousePosition.X));
44: this.AssociatedObject.SetValue(Canvas.TopProperty, ((double)this.AssociatedObject.GetValue(Canvas.TopProperty)) + (currentMousePosition.Y - _originalMousePosition.Y));
45: //update original mouse position
46: _originalMousePosition = currentMousePosition;
47: }
48: }
49:
50: private void AssociatedObject_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
51: {
52: _isDraging = false;
53: this.AssociatedObject.ReleaseMouseCapture();
54: }
55: }
OnAttached里面注册MouseLeftButtonDown,MouseMove,MouseLeftButtonUp三个事件,OnDetaching里面取消注册。MouseLeftButtonDown事件获取Canvas和原始坐标,并设置开始拖动的标志;MouseMove事件不停的计算当前坐标与原始坐标的差值,并更新到Shape的坐标,从而实现移动(坐标的计算方法这里不多说);MouseLeftButtonUp结束拖动。这三个事件处理方法实际上可以看成三个Action,而Behavior本身可以看成一个Trigger。
下面该使用这个Behavior了。
因为是在Canvas上的拖动,所以要有一个Canvas,然后在上面放一个矩形和一个椭圆:
1: <Canvas x:Name="LayoutRoot" Background="White">
2: <Rectangle Fill="#FFF4F4F5" Height="76" Canvas.Left="82" Stroke="Black" Canvas.Top="78" Width="81">
3: <i:Interaction.Behaviors>
4: <local:Behavior1/>
5: </i:Interaction.Behaviors>
6: </Rectangle>
7: <Ellipse Fill="#FFF4F4F5" Height="76" Canvas.Left="221" Stroke="Black" Canvas.Top="154" Width="79">
8: <i:Interaction.Behaviors>
9: <local:Behavior1/>
10: </i:Interaction.Behaviors>
11: </Ellipse>
12: </Canvas>
给它们分别应用上同一个Behavior,然后运行。结果很明显,两个Shape都能拖动了。
Behavior是个好东西,好处就不用说了,显而易见。其实在Blend(做Silverlight界面的)中已经预定义了不少Behaviors,在Microsoft Expression Gallery也可以获得他人的或共享自己的Behavior。
附上上面的源代码
参考资料:
http://hi.baidu.com/biongiser/item/6c3509355f9b49f32784f40b
http://kb.cnblogs.com/a/2253240/