PageRenderTime 62ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/VMS-Project/VMS.Client/VMS.Client.TrackingSystem/Commands/DelegateCommand.cs

http://rb-vms.googlecode.com/
C# | 435 lines | 307 code | 52 blank | 76 comment | 48 complexity | 4f31ce6273a157a4f613f6aadcf95dd5 MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Windows;
  4. using System.Windows.Input;
  5. namespace VMS.Client.TrackingSystem.Commands
  6. {
  7. /// <summary>
  8. /// This class allows delegating the commanding logic to methods passed as parameters,
  9. /// and enables a View to bind commands to objects that are not part of the element tree.
  10. /// </summary>
  11. public class DelegateCommand : ICommand
  12. {
  13. #region Constructors
  14. /// <summary>
  15. /// Constructor
  16. /// </summary>
  17. public DelegateCommand(Action executeMethod)
  18. : this(executeMethod, null, false)
  19. {
  20. }
  21. /// <summary>
  22. /// Constructor
  23. /// </summary>
  24. public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod)
  25. : this(executeMethod, canExecuteMethod, false)
  26. {
  27. }
  28. /// <summary>
  29. /// Constructor
  30. /// </summary>
  31. public DelegateCommand(Action executeMethod, Func<bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
  32. {
  33. if (executeMethod == null)
  34. {
  35. throw new ArgumentNullException("executeMethod");
  36. }
  37. _executeMethod = executeMethod;
  38. _canExecuteMethod = canExecuteMethod;
  39. _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
  40. }
  41. #endregion
  42. #region Public Methods
  43. /// <summary>
  44. /// Method to determine if the command can be executed
  45. /// </summary>
  46. public bool CanExecute()
  47. {
  48. if (_canExecuteMethod != null)
  49. {
  50. return _canExecuteMethod();
  51. }
  52. return true;
  53. }
  54. /// <summary>
  55. /// Execution of the command
  56. /// </summary>
  57. public void Execute()
  58. {
  59. if (_executeMethod != null)
  60. {
  61. _executeMethod();
  62. }
  63. }
  64. /// <summary>
  65. /// Property to enable or disable CommandManager's automatic requery on this command
  66. /// </summary>
  67. public bool IsAutomaticRequeryDisabled
  68. {
  69. get
  70. {
  71. return _isAutomaticRequeryDisabled;
  72. }
  73. set
  74. {
  75. if (_isAutomaticRequeryDisabled != value)
  76. {
  77. if (value)
  78. {
  79. CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
  80. }
  81. else
  82. {
  83. CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
  84. }
  85. _isAutomaticRequeryDisabled = value;
  86. }
  87. }
  88. }
  89. /// <summary>
  90. /// Raises the CanExecuteChaged event
  91. /// </summary>
  92. public void RaiseCanExecuteChanged()
  93. {
  94. OnCanExecuteChanged();
  95. }
  96. /// <summary>
  97. /// Protected virtual method to raise CanExecuteChanged event
  98. /// </summary>
  99. protected virtual void OnCanExecuteChanged()
  100. {
  101. CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
  102. }
  103. #endregion
  104. #region ICommand Members
  105. /// <summary>
  106. /// ICommand.CanExecuteChanged implementation
  107. /// </summary>
  108. public event EventHandler CanExecuteChanged
  109. {
  110. add
  111. {
  112. if (!_isAutomaticRequeryDisabled)
  113. {
  114. CommandManager.RequerySuggested += value;
  115. }
  116. CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
  117. }
  118. remove
  119. {
  120. if (!_isAutomaticRequeryDisabled)
  121. {
  122. CommandManager.RequerySuggested -= value;
  123. }
  124. CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
  125. }
  126. }
  127. bool ICommand.CanExecute(object parameter)
  128. {
  129. return CanExecute();
  130. }
  131. void ICommand.Execute(object parameter)
  132. {
  133. Execute();
  134. }
  135. #endregion
  136. #region Data
  137. private readonly Action _executeMethod = null;
  138. private readonly Func<bool> _canExecuteMethod = null;
  139. private bool _isAutomaticRequeryDisabled = false;
  140. private List<WeakReference> _canExecuteChangedHandlers;
  141. #endregion
  142. }
  143. /// <summary>
  144. /// This class allows delegating the commanding logic to methods passed as parameters,
  145. /// and enables a View to bind commands to objects that are not part of the element tree.
  146. /// </summary>
  147. /// <typeparam name="T">Type of the parameter passed to the delegates</typeparam>
  148. public class DelegateCommand<T> : ICommand
  149. {
  150. #region Constructors
  151. /// <summary>
  152. /// Constructor
  153. /// </summary>
  154. public DelegateCommand(Action<T> executeMethod)
  155. : this(executeMethod, null, false)
  156. {
  157. }
  158. /// <summary>
  159. /// Constructor
  160. /// </summary>
  161. public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod)
  162. : this(executeMethod, canExecuteMethod, false)
  163. {
  164. }
  165. /// <summary>
  166. /// Constructor
  167. /// </summary>
  168. public DelegateCommand(Action<T> executeMethod, Func<T, bool> canExecuteMethod, bool isAutomaticRequeryDisabled)
  169. {
  170. if (executeMethod == null)
  171. {
  172. throw new ArgumentNullException("executeMethod");
  173. }
  174. _executeMethod = executeMethod;
  175. _canExecuteMethod = canExecuteMethod;
  176. _isAutomaticRequeryDisabled = isAutomaticRequeryDisabled;
  177. }
  178. #endregion
  179. #region Public Methods
  180. /// <summary>
  181. /// Method to determine if the command can be executed
  182. /// </summary>
  183. public bool CanExecute(T parameter)
  184. {
  185. if (_canExecuteMethod != null)
  186. {
  187. return _canExecuteMethod(parameter);
  188. }
  189. return true;
  190. }
  191. /// <summary>
  192. /// Execution of the command
  193. /// </summary>
  194. public void Execute(T parameter)
  195. {
  196. if (_executeMethod != null)
  197. {
  198. _executeMethod(parameter);
  199. }
  200. }
  201. /// <summary>
  202. /// Raises the CanExecuteChaged event
  203. /// </summary>
  204. public void RaiseCanExecuteChanged()
  205. {
  206. OnCanExecuteChanged();
  207. }
  208. /// <summary>
  209. /// Protected virtual method to raise CanExecuteChanged event
  210. /// </summary>
  211. protected virtual void OnCanExecuteChanged()
  212. {
  213. CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
  214. }
  215. /// <summary>
  216. /// Property to enable or disable CommandManager's automatic requery on this command
  217. /// </summary>
  218. public bool IsAutomaticRequeryDisabled
  219. {
  220. get
  221. {
  222. return _isAutomaticRequeryDisabled;
  223. }
  224. set
  225. {
  226. if (_isAutomaticRequeryDisabled != value)
  227. {
  228. if (value)
  229. {
  230. CommandManagerHelper.RemoveHandlersFromRequerySuggested(_canExecuteChangedHandlers);
  231. }
  232. else
  233. {
  234. CommandManagerHelper.AddHandlersToRequerySuggested(_canExecuteChangedHandlers);
  235. }
  236. _isAutomaticRequeryDisabled = value;
  237. }
  238. }
  239. }
  240. #endregion
  241. #region ICommand Members
  242. /// <summary>
  243. /// ICommand.CanExecuteChanged implementation
  244. /// </summary>
  245. public event EventHandler CanExecuteChanged
  246. {
  247. add
  248. {
  249. if (!_isAutomaticRequeryDisabled)
  250. {
  251. CommandManager.RequerySuggested += value;
  252. }
  253. CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
  254. }
  255. remove
  256. {
  257. if (!_isAutomaticRequeryDisabled)
  258. {
  259. CommandManager.RequerySuggested -= value;
  260. }
  261. CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
  262. }
  263. }
  264. bool ICommand.CanExecute(object parameter)
  265. {
  266. // if T is of value type and the parameter is not
  267. // set yet, then return false if CanExecute delegate
  268. // exists, else return true
  269. if (parameter == null &&
  270. typeof(T).IsValueType)
  271. {
  272. return (_canExecuteMethod == null);
  273. }
  274. return CanExecute((T)parameter);
  275. }
  276. void ICommand.Execute(object parameter)
  277. {
  278. Execute((T)parameter);
  279. }
  280. #endregion
  281. #region Data
  282. private readonly Action<T> _executeMethod = null;
  283. private readonly Func<T, bool> _canExecuteMethod = null;
  284. private bool _isAutomaticRequeryDisabled = false;
  285. private List<WeakReference> _canExecuteChangedHandlers;
  286. #endregion
  287. }
  288. /// <summary>
  289. /// This class contains methods for the CommandManager that help avoid memory leaks by
  290. /// using weak references.
  291. /// </summary>
  292. internal class CommandManagerHelper
  293. {
  294. internal static void CallWeakReferenceHandlers(List<WeakReference> handlers)
  295. {
  296. if (handlers != null)
  297. {
  298. // Take a snapshot of the handlers before we call out to them since the handlers
  299. // could cause the array to me modified while we are reading it.
  300. EventHandler[] callees = new EventHandler[handlers.Count];
  301. int count = 0;
  302. for (int i = handlers.Count - 1; i >= 0; i--)
  303. {
  304. WeakReference reference = handlers[i];
  305. EventHandler handler = reference.Target as EventHandler;
  306. if (handler == null)
  307. {
  308. // Clean up old handlers that have been collected
  309. handlers.RemoveAt(i);
  310. }
  311. else
  312. {
  313. callees[count] = handler;
  314. count++;
  315. }
  316. }
  317. // Call the handlers that we snapshotted
  318. for (int i = 0; i < count; i++)
  319. {
  320. EventHandler handler = callees[i];
  321. handler(null, EventArgs.Empty);
  322. }
  323. }
  324. }
  325. internal static void AddHandlersToRequerySuggested(List<WeakReference> handlers)
  326. {
  327. if (handlers != null)
  328. {
  329. foreach (WeakReference handlerRef in handlers)
  330. {
  331. EventHandler handler = handlerRef.Target as EventHandler;
  332. if (handler != null)
  333. {
  334. CommandManager.RequerySuggested += handler;
  335. }
  336. }
  337. }
  338. }
  339. internal static void RemoveHandlersFromRequerySuggested(List<WeakReference> handlers)
  340. {
  341. if (handlers != null)
  342. {
  343. foreach (WeakReference handlerRef in handlers)
  344. {
  345. EventHandler handler = handlerRef.Target as EventHandler;
  346. if (handler != null)
  347. {
  348. CommandManager.RequerySuggested -= handler;
  349. }
  350. }
  351. }
  352. }
  353. internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler)
  354. {
  355. AddWeakReferenceHandler(ref handlers, handler, -1);
  356. }
  357. internal static void AddWeakReferenceHandler(ref List<WeakReference> handlers, EventHandler handler, int defaultListSize)
  358. {
  359. if (handlers == null)
  360. {
  361. handlers = (defaultListSize > 0 ? new List<WeakReference>(defaultListSize) : new List<WeakReference>());
  362. }
  363. handlers.Add(new WeakReference(handler));
  364. }
  365. internal static void RemoveWeakReferenceHandler(List<WeakReference> handlers, EventHandler handler)
  366. {
  367. if (handlers != null)
  368. {
  369. for (int i = handlers.Count - 1; i >= 0; i--)
  370. {
  371. WeakReference reference = handlers[i];
  372. EventHandler existingHandler = reference.Target as EventHandler;
  373. if ((existingHandler == null) || (existingHandler == handler))
  374. {
  375. // Clean up old handlers that have been collected
  376. // in addition to the handler that is to be removed.
  377. handlers.RemoveAt(i);
  378. }
  379. }
  380. }
  381. }
  382. }
  383. }