代码改变世界

MVVMLight源码分析之EventToCommand

2010-11-21 22:23  撞破南墙  阅读(3501)  评论(0编辑  收藏  举报

1如何使用

1.1MVVM下的写法

1.2后台如何调用 

2追踪后面的实现

3为什么要使用

  

1.1MVVM下的写法

<i:Interaction.Triggers>     <i:EventTrigger EventName="被包含的frameworklement的事件比如 textchanged">         <cmd:EventToCommand Command="{Binding SimpleCommand(你的command)}"   />     </i:EventTrigger> </i:Interaction.Triggers>

只需要上面这一段代码放到frameworklement里,然后去viewModels去写command的逻辑。

代码
 private class TestViewModel2 : ViewModelBase {       
            
public ICommand SimpleCommand {
                
get;
                  
set;
            }
            
public bool CommandExecuted { getset; }
            
public TestViewModel2() {
                SimpleCommand 
= new RelayCommand(() =>
{ CommandExecuted 
= true;
//你的要处理的逻辑
});

             
 
            }
        }

1.2测试下的写法


        [TestMethod]         
//测试不带参数的调用         public void TestInvokeWithoutParameter() {             var trigger = new EventToCommand();//             var rectangle = new Rectangle();             ((IAttachedObject)trigger).Attach(rectangle);//使用 trigger 加载 一个 frameworkelement             var vm = new TestViewModel();             var binding = new Binding {                 Source = vm.SimpleCommand             };
            BindingOperations.SetBinding(trigger, EventToCommand.CommandProperty, binding);             
// <---> <EventToCommand  Command="{Binding SimpleCommand}">             trigger.Invoke();             Assert.IsTrue(vm.CommandExecuted);         }

看到这里不由得想让人去看看在他的背后到底做了些什么的。


2调用的原理剖析

这就有点扯远了。

首先在任意frameworkelement里面我们定义了

TriggersProperty 

public abstract class FrameworkElement : UIElement{
    
private static readonly DependencyProperty TriggersProperty = DependencyProperty.RegisterCoreProperty(0x32cbtypeof(TriggerCollection));
 
public TriggerCollection Triggers
    {
        
get
        {
            
return (TriggerCollection) base.GetValue(TriggersProperty);
        }
    }
}

 

下面看TriggerCollection

public sealed class TriggerCollection : PresentationFrameworkCollection<TriggerBase>
{
    
// 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);
}

 

triggerBase

public abstract class TriggerBase : DependencyObject
{
    
// Methods
    internal TriggerBase() : base(270)
    {
    }

    
internal TriggerBase(uint nKnownTypeIndex) : base(nKnownTypeIndex)
    {
    }
}

 

 

追踪

base.GetValue()

public abstract class DependencyObject : IManagedPeer, IManagedPeerBase, INativeCoreTypeWrapper
{
   
public object GetValue(DependencyProperty dp)
   {
    
return this.GetValueInternal(dp);
   }

好吧,我目前还没有理通。他具体是通过怎么样的办法实现把注册进trigger的东西,得到click或者textchanged的事件的。


3为什么要使用这种方法。

      只有ButtonBase提供了Command属性。一般需要的控件需要支持更多的事件响应,比如textbox的textchanged等。