wpf中使用MVVM模式进行开发,View与ViewModule的交互个人总结
在MVVM模式中,viewer负责向用户展示软件设计意图,以期获得最佳的用户体验。VM则负责实现(一定的)业务逻辑,响应Viewer要求,达到隔离业务逻辑的目的。在实际开发中,两者如何进行交互往往是比较头痛的事情。现将开发中用到的交互方法总结一下:
一、使用Binding Command
利用Command是最常用的手段,因为在软件设计中,软件功能的触发往往是由一些具有Command属性的控件实现的,比如buttonbase、meumItem。在这里推荐一种比较实用的ICommand,代码如下:
该Command可以在响应命令前通过CanExecute方法判断是否该命令有效。但是这种command只适用于具有Command属性的ElementFrame。如果没有,则不能进行Binding。
一、使用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对象的特定事件与你的响应函数进行链接。代码如下:
写到最后:
上面三种方法都是本人平时开发过程中经常使用的方法,基本可以满足大部分的需要。如果有进一步的需求,可以关注一下http://caliburn.codeplex.com/。类似于Message.Attach="[Event Click] = [Action Divide]"的形式就可以实现命令的链接了。
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对象的特定事件与你的响应函数进行链接。代码如下:
XAML
自定义属性
写到最后:
上面三种方法都是本人平时开发过程中经常使用的方法,基本可以满足大部分的需要。如果有进一步的需求,可以关注一下http://caliburn.codeplex.com/。类似于Message.Attach="[Event Click] = [Action Divide]"的形式就可以实现命令的链接了。