UWP开发—自定义Behavior的使用 转

转http://www.tuicool.com/articles/z6Fraqa

UWP开发—自定义Behavior的使用

这是我第三次探索Behavior,依然记得2年前第一次和Behavior打交道。

郑州,2013年初……

当时刚毕业不久,满腔热血的投入到WindowsPhone App 开发,一个毛头小子对什么都充满了好奇,对WindowsPhone的开发工具自然而然的也一一进行探索,其中Blend肯定是少不了去接触的。然而一次无意的探索让我第一次接触到Behavior。

当时对Behavior的概念几乎没有,百度一番过后得知是拖放到控件上就能产生一定的行为效果,于是就把Blend中提供的所有Behavior挨个拖放到控件中看看到底是起什么作用。具体的细节现在都忘记了,只记住了一个特别的Behavior,叫什么也忘记了,记得它的作用是能让控件支持随意拖动的行为,也就是可以用手指将一个小球( Ellipse 控件)随意放置到屏幕任何位置。那时的我兴奋的好像自己实现了什么多牛逼的功能似的,其实然并卵而已,兴奋了几天后也就忘记了Behavior的存在。这就是我第一次和Behavior打交道,懵懂而又青涩……

第二次和Behavior打交道是因为MVVM框架,使用Blend 提供的Behavior能够很方便的使UI与VM逻辑结合起来,使得代码很清爽干净,但也仅仅局限于使用Blend中提供的Behavior,具体的Blend 中内置的Behavior使用方法请移步:Behavior的使用详解

最近在开发中,接触到了自定义Behavior,百度谷歌一番,无不发现每个开发者对Behavior的赞美。那么Behavior到底是什么?真的那么神奇?

简单点说就是,Behavior可以让某些功能行为附加到一个控件上,也就是说Behavior可以定义一组行为来循环使用或者提供给其他人使用。

那么自定义Behavior在UWP中到底怎么使用?下面我们就来利用自定义Behavior实现一个行为(Blend中自带的Behavior在这里不讨论)。

例子:自定义一个Behavior,实现元素鼠标经过时变大、离开时变小。

首先添加Behaviors SDK引用(忽略兼容性提示),实现自定义Behavior必须继承Behaviors SDK 中的DependencyObject 类并实现IBehavior接口。

新建一个类,暂时起名叫做BtnGetFocusBehavior.cs ,继承DependencyObject 类并实现IBehavior接口

public sealed class BtnGetFocusBehavior : DependencyObject, IBehavior
{
  public void Attach(DependencyObject associatedObject)
  {
    throw new NotImplementedException();
  }
  public void Detach()
  {
    throw new NotImplementedException();
  }
  public DependencyObject AssociatedObject { get; }
}

代码中Attach方法就是当该Behavior被关联到某一元素时要执行的代码,参数为元素对象的引用

Detach方法是党Behavior与关联的元素分离时要执行的代码

AssociatedObject是获取与Behavior关联起来的元素对象

接下来我们需要在Attach方法中实现被关联元素所拥有的行为,代码很简单就不解释了

public sealed class BtnGetFocusBehavior : DependencyObject, IBehavior
{
  private DependencyObject _associatedObject;
  private readonly Storyboard _focuStoryboard = new Storyboard();
  private const double AnimFrom = 1;
  private const double AnimTo = 1.5;
  private readonly DoubleAnimation _scaleXAnim = new DoubleAnimation();
  private readonly DoubleAnimation _scaleYAnim = new DoubleAnimation();
  public void Attach(DependencyObject associatedObject)
  {
    //获取关联的对象
    _associatedObject = associatedObject;
    if (associatedObject == null) return;
    var obj = _associatedObject as FrameworkElement;
    if (obj == null) return;
    var ct = new CompositeTransform();
    //添加CompositeTransform缩放支持
    obj.RenderTransform = ct;
    //设置动画关联对象
    Storyboard.SetTarget(_scaleXAnim, obj.RenderTransform);
    Storyboard.SetTargetProperty(_scaleXAnim, nameof(CompositeTransform.ScaleX));
    //设置动画关联对象
    Storyboard.SetTarget(_scaleYAnim, obj.RenderTransform);
    Storyboard.SetTargetProperty(_scaleYAnim, nameof(CompositeTransform.ScaleY));
    //将动画添加到故事版
    _focuStoryboard.Children.Add(_scaleYAnim);
    _focuStoryboard.Children.Add(_scaleXAnim);
    //关联事件
    obj.PointerEntered += Obj_PointerEntered;
    obj.PointerExited += Obj_PointerExited;
  }
  private void Obj_PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
  {
    StartScaleStoryboard(AnimTo, AnimFrom);
  }
  private void Obj_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
  {
    StartScaleStoryboard(AnimFrom, AnimTo);
  }
  private void StartScaleStoryboard(double from, double to)
  {
    _scaleYAnim.From = _scaleXAnim.From = from;
    _scaleYAnim.To = _scaleXAnim.To = to;
    _scaleYAnim.EasingFunction = _scaleXAnim.EasingFunction = new ExponentialEase { Exponent = 4 };
    _scaleYAnim.Duration = _scaleXAnim.Duration = new Duration(TimeSpan.FromSeconds(0.3));
    _focuStoryboard.Begin();
  }
  public void Detach()
  {
    var obj = _associatedObject as FrameworkElement;
    if (obj==null) return;
    //解除事件
    obj.PointerEntered -= Obj_PointerEntered;
    obj.PointerExited -= Obj_PointerExited;
  }
  public DependencyObject AssociatedObject => _associatedObject;
}

实现了自定义Behavior后,来看看在UI上怎么使用。

首先引用 Microsoft.Xaml.Interactivity 命名空间,我们需要把我们的Behavior放入到Interaction.Behaviors 里面,这样才能使Behavior关联到我们的元素中,如下:

xmlns:Interactivity="using:Microsoft.Xaml.Interactivity"

   <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
       
        <Ellipse  Width="100" Height="100" Fill="#FF1E5FBD" RenderTransformOrigin="0.5,0.5" >
            <Interactivity:Interaction.Behaviors>
                <beh:BtnGetFocusBehavior />
            </Interactivity:Interaction.Behaviors>
        </Ellipse>
    </Grid>

其实还有个更方便的使用我们自定义的Behavior的方法

我们打开Blend – "资产"面板 – "Behaviors行为",看看里面有什么?

对,有我们刚自定义的 BtnGetFocusBehavior ,在Blend中我们可以直接拖拽该Behavior 到页面的任意元素上,界面代码Blend会自动帮我们实现,是不是很方便?

Ok,Demo很简单,但意义重大,起个抛砖引玉功能,更优秀的Behavior还需要大家花花心思好好设计一番。

来看下运行效果:

 
posted @ 2015-12-09 15:16  tennychen  阅读(157)  评论(0)    收藏  举报