2012年6月29日星期五

Silverlight中的Behavior

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/

 


TAG: