PageRenderTime 42ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/MVVMSidekick/MVVMSidekick.Shared/Commands.cs

https://github.com/zoujuny/MVVM-Sidekick
C# | 342 lines | 207 code | 88 blank | 47 comment | 18 complexity | d3139f0ca25b98f7c68ca28c9b709668 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.ComponentModel;
  6. using System.Linq.Expressions;
  7. using System.Runtime.Serialization;
  8. using System.Reflection;
  9. using System.Threading.Tasks;
  10. using System.Threading;
  11. using System.Windows.Input;
  12. using MVVMSidekick.ViewModels;
  13. using MVVMSidekick.Commands;
  14. using System.Runtime.CompilerServices;
  15. using MVVMSidekick.Reactive;
  16. using System.Reactive.Linq;
  17. using System.Reactive.Subjects;
  18. using System.Reactive;
  19. using System.Collections.ObjectModel;
  20. using System.Collections.Specialized;
  21. using System.IO;
  22. using System.Collections;
  23. using MVVMSidekick.Utilities;
  24. using MVVMSidekick.Patterns;
  25. using MVVMSidekick.Collections;
  26. using MVVMSidekick.Views;
  27. using MVVMSidekick.EventRouting;
  28. #if NETFX_CORE
  29. using Windows.UI.Xaml;
  30. using Windows.UI.Xaml.Data;
  31. using Windows.UI.Xaml.Controls;
  32. using System.Collections.Concurrent;
  33. using Windows.UI.Xaml.Navigation;
  34. using Windows.UI.Xaml.Controls.Primitives;
  35. #elif WPF
  36. using System.Windows;
  37. using System.Windows.Controls;
  38. using System.Windows.Data;
  39. using System.Collections.Concurrent;
  40. using System.Windows.Navigation;
  41. using System.Windows.Controls.Primitives;
  42. #elif SILVERLIGHT_5||SILVERLIGHT_4
  43. using System.Windows;
  44. using System.Windows.Controls;
  45. using System.Windows.Data;
  46. using System.Windows.Navigation;
  47. using System.Windows.Controls.Primitives;
  48. #elif WINDOWS_PHONE_8||WINDOWS_PHONE_7
  49. using System.Windows;
  50. using System.Windows.Controls;
  51. using Microsoft.Phone.Controls;
  52. using System.Windows.Data;
  53. using System.Windows.Navigation;
  54. using System.Windows.Controls.Primitives;
  55. #endif
  56. namespace MVVMSidekick
  57. {
  58. namespace Commands
  59. {
  60. /// <summary>
  61. /// Command被运行触发的事件数据类型
  62. /// </summary>
  63. public class EventCommandEventArgs : EventArgs
  64. {
  65. public Object Parameter { get; set; }
  66. public Object ViewModel { get; set; }
  67. public Object ViewSender { get; set; }
  68. public Object EventArgs { get; set; }
  69. public string EventName { get; set; }
  70. public Type EventHandlerType { get; set; }
  71. public static EventCommandEventArgs Create(
  72. Object parameter = null,
  73. Object viewModel = null,
  74. object viewSender = null,
  75. object eventArgs = null,
  76. string eventName = null,
  77. Type eventHandlerType = null
  78. )
  79. {
  80. return new EventCommandEventArgs { Parameter = parameter, ViewModel = viewModel, ViewSender = viewSender, EventArgs = eventArgs, EventHandlerType = eventHandlerType, EventName = eventName };
  81. }
  82. }
  83. /// <summary>
  84. /// 事件Command的助手类
  85. /// </summary>
  86. public static class EventCommandHelper
  87. {
  88. /// <summary>
  89. /// 为一个事件Command制定一个VM
  90. /// </summary>
  91. /// <typeparam name="TCommand">事件Command具体类型</typeparam>
  92. /// <param name="cmd">事件Command实例</param>
  93. /// <param name="viewModel">VM实例</param>
  94. /// <returns>事件Command实例本身</returns>
  95. public static TCommand WithViewModel<TCommand>(this TCommand cmd, BindableBase viewModel)
  96. where TCommand : EventCommandBase
  97. {
  98. cmd.ViewModel = viewModel;
  99. return cmd;
  100. }
  101. }
  102. /// <summary>
  103. /// 带有VM的Command接口
  104. /// </summary>
  105. public interface ICommandWithViewModel : ICommand
  106. {
  107. BindableBase ViewModel { get; set; }
  108. }
  109. /// <summary>
  110. /// 事件Command,运行后马上触发一个事件,事件中带有Command实例和VM实例属性
  111. /// </summary>
  112. public abstract class EventCommandBase : ICommandWithViewModel
  113. {
  114. /// <summary>
  115. /// VM
  116. /// </summary>
  117. public BindableBase ViewModel { get; set; }
  118. /// <summary>
  119. /// 运行时触发的事件
  120. /// </summary>
  121. public event EventHandler<EventCommandEventArgs> CommandExecute;
  122. /// <summary>
  123. /// 执行时的逻辑
  124. /// </summary>
  125. /// <param name="args">执行时的事件数据</param>
  126. internal protected virtual void OnCommandExecute(EventCommandEventArgs args)
  127. {
  128. if (CommandExecute != null)
  129. {
  130. CommandExecute(this, args);
  131. }
  132. }
  133. /// <summary>
  134. /// 该Command是否能执行
  135. /// </summary>
  136. /// <param name="parameter">判断参数</param>
  137. /// <returns>是否</returns>
  138. public abstract bool CanExecute(object parameter);
  139. /// <summary>
  140. /// 是否能执行的值产生变化的事件
  141. /// </summary>
  142. public event EventHandler CanExecuteChanged;
  143. /// <summary>
  144. /// 是否能执行变化时触发事件的逻辑
  145. /// </summary>
  146. protected void OnCanExecuteChanged()
  147. {
  148. if (CanExecuteChanged != null)
  149. {
  150. CanExecuteChanged(this, EventArgs.Empty);
  151. }
  152. }
  153. /// <summary>
  154. /// 执行Command
  155. /// </summary>
  156. /// <param name="parameter">参数条件</param>
  157. public virtual void Execute(object parameter)
  158. {
  159. if (CanExecute(parameter))
  160. {
  161. OnCommandExecute(EventCommandEventArgs.Create(parameter, ViewModel));
  162. }
  163. }
  164. }
  165. namespace EventBinding
  166. {
  167. public class CommandBinding : FrameworkElement
  168. {
  169. public CommandBinding()
  170. {
  171. base.Width = 0;
  172. base.Height = 0;
  173. base.Visibility = Visibility.Collapsed ;
  174. }
  175. public string EventName { get; set; }
  176. public FrameworkElement EventSource
  177. {
  178. get { return (FrameworkElement)GetValue(EventSourceProperty); }
  179. set { SetValue(EventSourceProperty, value); }
  180. }
  181. // Using a DependencyProperty as the backing store for EventSource. This enables animation, styling, binding, etc...
  182. public static readonly DependencyProperty EventSourceProperty =
  183. DependencyProperty.Register("EventSource", typeof(FrameworkElement), typeof(CommandBinding), new PropertyMetadata(null,
  184. (dobj, arg) =>
  185. {
  186. CommandBinding obj = dobj as CommandBinding;
  187. if (obj == null)
  188. {
  189. return;
  190. }
  191. if (obj.oldEventDispose != null)
  192. {
  193. obj.oldEventDispose.Dispose();
  194. }
  195. var nv = arg.NewValue;
  196. if (nv != null)
  197. {
  198. obj.oldEventDispose = nv.BindEvent(
  199. obj.EventName,
  200. (o, a, en, ehType) =>
  201. {
  202. obj.ExecuteFromEvent(o, a, en, ehType);
  203. });
  204. }
  205. }
  206. ));
  207. IDisposable oldEventDispose;
  208. public ICommand Command
  209. {
  210. get { return (ICommand)GetValue(CommandProperty); }
  211. set { SetValue(CommandProperty, value); }
  212. }
  213. // Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
  214. public static readonly DependencyProperty CommandProperty =
  215. DependencyProperty.Register("Command", typeof(ICommand), typeof(CommandBinding), new PropertyMetadata(null));
  216. public Object Parameter
  217. {
  218. get { return (Object)GetValue(ParameterProperty); }
  219. set { SetValue(ParameterProperty, value); }
  220. }
  221. // Using a DependencyProperty as the backing store for Parameter. This enables animation, styling, binding, etc...
  222. public static readonly DependencyProperty ParameterProperty =
  223. DependencyProperty.Register("Parameter", typeof(Object), typeof(CommandBinding), new PropertyMetadata(null));
  224. public void ExecuteFromEvent(object sender, object eventArgs, string eventName, Type eventHandlerType)
  225. {
  226. object vm = null;
  227. var s = (sender as FrameworkElement);
  228. if (Command == null)
  229. {
  230. return;
  231. }
  232. var cvm = Command as ICommandWithViewModel;
  233. if (cvm != null)
  234. {
  235. vm = cvm.ViewModel;
  236. }
  237. var newe = EventCommandEventArgs.Create(Parameter, vm, sender, eventArgs, eventName, eventHandlerType);
  238. if (Command.CanExecute(newe))
  239. {
  240. var spEventCommand = Command as EventCommandBase;
  241. if (spEventCommand == null)
  242. {
  243. Command.Execute(newe);
  244. }
  245. else
  246. {
  247. spEventCommand.OnCommandExecute(newe);
  248. }
  249. }
  250. }
  251. }
  252. }
  253. }
  254. }