Saturday, June 02, 2012

MVVMLight源碼分析之EventToCommand

  
1.1MVVM下的寫法
<i:Interaction.Triggers>
    <i:EventTrigger  EventName ="被包含的frameworklement的事件比如textchanged">         <cmd:EventToCommand  Command =" {Binding SimpleCommand(你的command)}"/>     </i:EventTrigger> </i:Interaction.Triggers> private  class  TestViewModel2 : ViewModelBase 
{          public  ICommand SimpleCommand { get ; set ; }           public  bool  CommandExecuted {  get set ; }           public  TestViewModel2() {                 SimpleCommand                  SimpleCommand  =  new  RelayCommand(()  => { CommandExecuted  =  true ; // 你的要處理的邏輯 });             }         }          // 測試不帶參數的調用         public  void  TestInvokeWithoutParameter() {             var trigger              var trigger  =  new  EventToCommand(); //             var rectangle  =  new  Rectangle();             ((IAttachedObject)trigger).Attach(rectangle);             ((IAttachedObject)trigger).Attach(rectangle); // 使用trigger加載一個frameworkelement             var vm  =  new  TestViewModel();             var binding              var binding  =  new  Binding {                 Source                  Source  =  vm.SimpleCommand             };             BindingOperations.SetBinding(trigger, EventToCommand.CommandProperty, binding);                          };             BindingOperations.SetBinding(trigger, EventToCommand.CommandProperty, binding);              //  <---> <EventToCommand Command="{Binding SimpleCommand}">             trigger.Invoke();             Assert.IsTrue(vm.CommandExecuted);         }     private  static  readonly  DependencyProperty TriggersProperty  =  DependencyProperty.RegisterCoreProperty( 0x32cb typeof (TriggerCollection));    public  TriggerCollection Triggers     {              {         get         {             return  (TriggerCollection)  base .GetValue(TriggersProperty);         }     } }         }     } } {     //  Methods     internal  TriggerCollection();          internal  override  void  AddInternal(TriggerBase value);          internal  override  bool  ContainsInternal(TriggerBase value);          internal  override  TriggerBase GetItemImplSkipMethodPack( int  index);          internal  override  int  IndexOfInternal( TriggerBase value);          internal  override  void  InsertInternal( int  index, TriggerBase value);          internal  override  bool  RemoveInternal(TriggerBase value);          internal  override  void  SetItemImplSkipMethodPack( int  index, TriggerBase value); } } {     //  Methods     internal  TriggerBase() :  base ( 270 )     {     }          {     }     internal  TriggerBase( uint  nKnownTypeIndex) :  base (nKnownTypeIndex)     {     } }     {     } } {    public  object  GetValue(DependencyProperty dp)    {         {     return  this .GetValueInternal(dp);    } }     }
只需要上面這一段代碼放到 frameworklement 裡,然後去viewModels去寫command的邏輯。
1.2測試下的寫法
        [TestMethod]
看到這裡不由得想讓人去看看在他的背後到底做了些什麼的。
2調用的原理剖析
這就有點扯遠了。
首先在任意frameworkelement裡面我們定義了
TriggersProperty 
public  abstract  class  FrameworkElement : UIElement{
下面看 TriggerCollection
public  sealed  class  TriggerCollection : PresentationFrameworkCollection < TriggerBase >
triggerBase
public  abstract  class  TriggerBase : DependencyObject
追踪
base .GetValue()
public  abstract  class  DependencyObject : IManagedPeer, IManagedPeerBase, INativeCoreTypeWrapper
好吧,我目前還沒有理通。他具體是通過怎麼樣的辦法實現把註冊進trigger的東西,得到click或者textchanged的事件的。
3為什麼要使用這種方法。
      只有ButtonBase提供了Command屬性。一般需要的控件需要支持更多的事件響應,比如textbox的textchanged等。

No comments: