WPF系列之二:解耦View层控件事件与ViewModel层事件的响应

以前的做法:

1.当项目的时间比较紧迫的时候,对UI层中控件的事件的处理,往往采取的是类似Winform中最简单的做法,直接做一个事件的Handler直接去调用VM层的方法。

2.控件只有一个Command属性,其它的事件的处理方法没有办法和ViewModel层进行解耦的时候往往也采取上面提到的方法。

如下图所示:

新的做法:

为了实现事件的处理与View层的解耦,我们可以利用WPF提供的附加属性来为需要的事件添加附加行为。附加属性扮演了一个在View层与Model层牵线的角色。

需要下面三个步骤来实现(以Load事件为例):

1.在ViewModel中定义一个Command属性

 winloadedCommand = new DelegateCommand(this.executeWinloadedCommand, this.canWinloadedCommand);
实例化Command

定义ICommand类型的command

 #region
        private ICommand winloadedCommand;
        public ICommand WinloadedCommand
        {
            get { return winloadedCommand; }
            set
            {
                if (winloadedCommand != value)
                {
                    winloadedCommand = value;
                    OnPropertyChagned("WinloadedCommand");
                }
            }
        }
        private void executeWinloadedCommand()
        {
            CalculatingStatus = "The WinloadedCommand has been called!";
        }
        private bool canWinloadedCommand()
        {
            return true;
        }
        #endregion
WinloadedCommand

2.定义一个CommandBehaviors类,在其中定义一个ICommand类型的附加属性,并在PropertyChangedCallback的回调中链接事件与实际的command实例之间的调用。

public static class CommandBehaviors
    {
        public static ICommand GetWindowLoadCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(WindowLoadCommandProperty);
        }
        public static void SetWindowLoadCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(WindowLoadCommandProperty, value);
        }
        // Using a DependencyProperty as the backing store for WindowLoadCommand.  This enables animation, styling, binding, etc...
        public static readonly DependencyProperty WindowLoadCommandProperty =
            DependencyProperty.RegisterAttached("WindowLoadCommand", typeof(ICommand), typeof(CommandBehaviors), new PropertyMetadata(null, OnWindowLoadedCommandPropertyChanged));
        public static void OnWindowLoadedCommandPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var frameworkElement = d as FrameworkElement;
            if (frameworkElement != null && e.NewValue is ICommand)
            {
                frameworkElement.Loaded
                  += (obj, args) =>
                     {
                         if ((e.NewValue as ICommand).CanExecute(obj))
                         {
                             (e.NewValue as ICommand).Execute(null);
                         }
                     };
            }
        }
    }
CommandBehaviors

3.在xaml中进行Binding

 

大功告成,运行示例如下:

思考1:如何实现带有参数的调用?Event-〉Command

1.如果参数数据来源于控件本身的属性,可以在链接Event与Command时直接传递参数

2.如果数据来自外界,可以在CommandBehaviors类中定义额外的附加属性,然后将参数绑定到此属性上面,当调用command时,检查该属性。

完毕。

作者:Andy Zeng

欢迎任何形式的转载,但请务必注明出处。

http://www.cnblogs.com/andyzeng/p/3708276.html 

 

posted @ 2014-05-05 00:01  AndyZeng  阅读(1808)  评论(0编辑  收藏  举报