WPF中的MVVM模式:View与ViewModule的交互个人总结

出处:http://www.cnblogs.com/oliverxgwang/archive/2009/07/28/1532678.html

 

在MVVM模式中,viewer负责向用户展示软件设计意图,以期获得最佳的用户体验。VM则负责实现(一定的)业务逻辑,响应Viewer要求,达到隔离业务逻辑的目的。在实际开发中,两者如何进行交互往往是比较头痛的事情。现将开发中用到的交互方法总结一下:
一、使用Binding Command
    利用Command是最常用的手段,因为在软件设计中,软件功能的触发往往是由一些具有Command属性的控件实现的,比如buttonbase、meumItem。在这里推荐一种比较实用的ICommand,代码如下:
该Command可以在响应命令前通过CanExecute方法判断是否该命令有效。但是这种command只适用于具有Command属性的ElementFrame。如果没有,则不能进行Binding。

  1     public class RelayCommand<T> : ICommand
  2     {
  3         #region Fields
  4 
  5         readonly Action<T> _execute = null;
  6         readonly Predicate<T> _canExecute = null;
  7 
  8         #endregion
  9 
 10         #region Constructors
 11         /// <summary>
 12         /// 构造函数
 13         /// </summary>
 14         /// <param name="execute"> 执行逻辑,实际执行函数</param>
 15          public RelayCommand(Action<T> execute)
 16             : this(execute, null)
 17         {
 18         }
 19         public RelayCommand(Action<T> execute, Predicate<T> canExecute)
 20         {
 21             if (execute == null)
 22                 throw new ArgumentNullException("execute");
 23 
 24             _execute = execute;
 25             _canExecute = canExecute;
 26         }
 27 
 28         #endregion
 29 
 30         #region ICommand Members
 31         public bool CanExecute(object parameter)
 32         {
 33             return _canExecute == null ? true : _canExecute((T)parameter);
 34         }
 35 
 36         public event EventHandler CanExecuteChanged
 37         {
 38             add
 39             {
 40                 if (_canExecute != null)
 41                     CommandManager.RequerySuggested += value;
 42             }
 43             remove
 44             {
 45                 if (_canExecute != null)
 46                     CommandManager.RequerySuggested -= value;
 47             }
 48         }
 49 
 50         public void Execute(object parameter)
 51         {
 52             _execute((T)parameter);
 53         }
 54 
 55         #endregion
 56     }
 57 
 58     /// <summary>
 59     /// 
 60     /// </summary>
 61     public class RelayCommand : ICommand
 62     {
 63         #region Fields
 64 
 65         readonly Action _execute;
 66         readonly Func<bool> _canExecute;
 67 
 68         #endregion
 69 
 70         #region Constructors
 71 
 72         /// <summary>
 73         /// 构造函数
 74         /// </summary>
 75         /// <param name="execute">实际执行函数</param>
 76         public RelayCommand(Action execute)
 77             : this(execute, null)
 78         {
 79         }
 80 
 81         public RelayCommand(Action execute, Func<bool> canExecute)
 82         {
 83             if (execute == null)
 84                 throw new ArgumentNullException("execute");
 85 
 86             _execute = execute;
 87             _canExecute = canExecute;
 88         }
 89 
 90         #endregion
 91 
 92         #region ICommand Members
 93 
 94         public bool CanExecute(object parameter)
 95         {
 96             return _canExecute == null ? true : _canExecute();
 97         }
 98 
 99         public event EventHandler CanExecuteChanged
100         {
101             add
102             {
103                 if (_canExecute != null)
104                     CommandManager.RequerySuggested += value;
105             }
106             remove
107             {
108                 if (_canExecute != null)
109                     CommandManager.RequerySuggested -= value;
110             }
111         }
112 
113         public void Execute(object parameter)
114         {
115             _execute();
116         }
117 
118         #endregion
119     }
二、使用Binding Property
     绑定属性的方法通常用于实施获取界面某个值的变化,配合Binding的Converter和ValidationRule可以很好的效果,不过在VM中要实现INotifyPropertyChanged,集合通常要实现ObservableCollection<T>。
三、使用Attatch Property
    Attatch方法通常是为了VM能够与V通过binding的方法响应一些非Command的事件,比如WindowClose,OnResized等。实现的主要思路是,自定义一个静态类,该类中定义一个AttatchProperty实现,
在XAML文档中对要施加事件的Element的Style中使用Setter进行设置(类似的方法都行,只要附加该自定义AttatchProperty属性就行)。同时在定义的类中,AttachProperty属性注册附加属性当中的属性原数据响应函数中要将DependencyObject对象的特定事件与你的响应函数进行链接。代码如下:

    <Window.Style>
        
<Style TargetType="{x:Type Window}">
            
<Setter 
            Property
="Host:MainWindowBehavior.OnWindowCloseAction" 
            Value
="{Binding }" 
            
/>
        
</Style>
    
</Window.Style>


        public static readonly DependencyProperty OnWindowCloseActionProperty =
            DependencyProperty.RegisterAttached(
            
"OnWindowCloseAction",
            
typeof(object),
            
typeof(MainWindowBehavior),
            
new UIPropertyMetadata(null, OnHostWindowClose));

        
private static void OnHostWindowClose(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            MainWindow mainWindow 
= d as MainWindow;
            
if (null != mainWindow)
                mainWindow.Closed 
+= new EventHandler(mainWindow_Closed);

        }

        
static void mainWindow_Closed(object sender, EventArgs e)
        {
            MainWindow mainWindow 
= sender as MainWindow;
            
if (null != mainWindow)
            {
                MainWindowPresenter tempPresenter 
= mainWindow.DataContext as MainWindowPresenter;
                
if (null != tempPresenter)
                    tempPresenter.Dispose();
            }
        }

写到最后:
  上面三种方法都是本人平时开发过程中经常使用的方法,基本可以满足大部分的需要。如果有进一步的需求,可以关注一下http://caliburn.codeplex.com/。类似于Message.Attach="[Event Click] = [Action Divide]"的形式就可以实现命令的链接了。

posted on 2010-07-29 11:12  I过T  阅读(1197)  评论(1编辑  收藏  举报

导航