Behavior,Trigger,TriggerAction深度解析

使用命令绑定是实现mvvm的重要途径,而Behavior,Trigger更是大大的简化这种方式,相信使用过 Behavior,Trigger的朋友深有体会,而 Trigger得灵活性之强又大大节省了很多的工作量,并且加速了编程效率。那么Behavior,Trigger,TriggerAction是如何实现的,使用过程中又要注意些什么?看我下面的分析。
  Behavior,Trigger,TriggerAction都继承于IAttachedObject接口和DependencyObject,下面是IAttachedObject的源码:

[代码]c#/cpp/oc代码:

    public interface IAttachedObject
    {
        void Attach(DependencyObject dependencyObject);
        void Detach();

        DependencyObject AssociatedObject { get; }
    }
  AssociatedObject是被关联的对象,注意这是DependencyObject类型的,不是所有的对象都可以被关联。Behavior,Trigger,TriggerAction中都会保留有这个对象。
  Attach在被关联时会被调用,dependencyObject是被关联的对象。
  Detach在被解除关联是调用。
  
  在被关联是看看Behavior,Trigger,TriggerAction中内部实现的不同:

[代码]c#/cpp/oc代码:

public void Attach(DependencyObject dependencyObject)
        {
            if (dependencyObject != this.AssociatedObject)
            {
                if (this.AssociatedObject != null)
                {
                    throw new InvalidOperationException(...);
                }
                if ((dependencyObject != null) && !this.AssociatedObjectTypeConstraint.IsAssignableFrom(dependencyObject.GetType()))
                {
                    throw new InvalidOperationException(...);
                }
                this.associatedObject = dependencyObject;
                this.OnAttached();
            }
        }
   以上是TriggerAction的实现。Trigger实现如下:

[代码]c#/cpp/oc代码:

        public void Attach(DependencyObject dependencyObject)
        {
            if (dependencyObject != this.AssociatedObject)
            {
                if (this.AssociatedObject != null)
                {
                    throw new InvalidOperationException(...);
                }
                if ((dependencyObject != null) && !this.AssociatedObjectTypeConstraint.IsAssignableFrom(dependencyObject.GetType()))
                {
                    throw new InvalidOperationException(...);
                }
                this.associatedObject = dependencyObject;
                this.Actions.Attach(dependencyObject);
                this.OnAttached();
            }
        }
   相比TriggerAction多了一行 this.Actions.Attach(dependencyObject)。Actions是TriggerAction的集合,在Trigger被关联的同时会一次关联集合众的TriggerAction。
  Behavior实现如下:

[代码]c#/cpp/oc代码:

public void Attach(DependencyObject dependencyObject)
        {
            if (dependencyObject != this.AssociatedObject)
            {
                if (this.AssociatedObject != null)
                {
                    throw new InvalidOperationException(...);
                }
                if ((dependencyObject != null) && !this.AssociatedType.IsAssignableFrom(dependencyObject.GetType()))
                {
                    throw new InvalidOperationException(...);
                }
                this.associatedObject = dependencyObject;
                this.OnAssociatedObjectChanged();
                this.OnAttached();
            }
        }
   Behavior多了一行AssociatedObjectChanged通知外界关联对象发生了改变。由上面的代码可以看出,3着实现大体相同,对象一但被附加,在被解除关联之前不可以被改变,并且被附加的类型与指定的类型相一致。
  Behavior,Trigger,TriggerAction这三者的区别与关联
   Trigger与TriggerAction是从属的关系,  Trigger 中保留有 TriggerAction 的集合,当 Trigger  被触发时,就会依次调用集合中的TriggerAction中的Invoke函数分别处理。 TriggerAction 中的Invoke是一个纯虚函数,这个函数中实现需要实现自己的逻辑代码。从TriggerBase继承的类可以调用InvokeActions来触发TriggerAction 的执行,以下是InvokeActions的实现:

[代码]c#/cpp/oc代码:

 protected void InvokeActions(object parameter)
        {
            if (this.PreviewInvoke != null)
            {
                PreviewInvokeEventArgs e = new PreviewInvokeEventArgs();
                this.PreviewInvoke(this, e);
                if (e.Cancelling)
                {
                    return;
                }
            }
            foreach (System.Windows.Interactivity.TriggerAction action in this.Actions)
            {
                action.CallInvoke(parameter);
            }
        }
  当Trigger被触发时,会调用PreviewInvoke事件通知外界已被触发。这是一条广播链,当外界设置e.Cancelling=true时,Actions中所有 TriggerAction 都不会执行。wp中所有广播链都是采用的这种模式,当设置 e.Cancelling=true是广播并不会停止,但是会组织后续逻辑的执行。
  Behavior则没有特别的实现,在被关联时刻对被关联对象做任意的处理, Trigger 也一样。 Behavior 与 Trigger  的区别在于Trigger   可以通知到外界做额外的处理。所以 Behavior 与 Trigger 的功能是有重叠的,个人认为 Trigger  完全可以在Behavior  的基础上实现,由于Trigger  中Actions的存在,所以 Trigger   的灵活性和扩展性强于 Behavior  。
   Behavior,Trigger,TriggerAction如何使用我就不额外说明了,不会用的就多搜索,网上的示例很多。
   额外补充:System.Windows.Interactivity中仅有EventTrigger这一种 Trigger ,但是windows phone中提供了额外扩展的Behavior,Trigger和TriggerAction,在Microsoft.Phone.Interop.dll中,从引用中添加即可。
  使用注意事项: Behavior,Trigger,TriggerAction 经常在xmal中使用,并且都附加到了控件上,但是需要注意的是这3着不在可视化树种,所以绑定的时候无法直接使用ElementName这个属性。我有一种解决方案可以解决这个问题,在以后的博客中说明。
   要想最大化发挥Behavior,Trigger,TriggerAction的功效,仅仅使用官方提供的是不够,而自己定制才能将这三着的功能最大化发挥。如何订制就看我以后的博客吧。
  说一下win8中的Behavior,Trigger,TriggerAction,win8官方并没有这样的功能,要使用需要额外下载第三方库,在NuGet管理中搜索Interactivity即可获得,不过库的名称为Windows.Ui.Interactivity.

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章