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.

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