bovender framework
C# framework that implements MVVM and more
DelegatingCommand.cs
2 /* DelegatingCommand.cs
3  * part of Daniel's XL Toolbox NG
4  *
5  * Copyright 2014-2018 Daniel Kraus
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  */
19 using System;
20 using System.Collections.Generic;
21 using System.ComponentModel;
22 using System.Linq.Expressions;
23 using System.Windows.Input;
24 using System.Windows.Threading;
25 
26 namespace Bovender.Mvvm
27 {
38  public class DelegatingCommand : ICommand
39  {
40  #region Constructors
41 
46  public DelegatingCommand(Action<object> execute)
47  : this(execute, canExecute: null)
48  {
49  }
50 
56  public DelegatingCommand(Action<object> execute, ViewModelBase viewModel)
57  : this(execute)
58  {
59  _viewModel = viewModel;
60  }
61 
69  public DelegatingCommand(Action<object> execute, Predicate<object> canExecute)
70  {
71  if (execute == null)
72  throw new ArgumentNullException("execute");
73 
74  _execute = execute;
75  _canExecute = canExecute;
76  }
77 
87  public DelegatingCommand(Action<object> execute, Predicate<object> canExecute,
88  ViewModelBase viewModel)
89  : this(execute, canExecute)
90  {
91  _viewModel = viewModel;
92  }
93 
94  #endregion
95 
96  #region ICommand Members
97 
98  public bool CanExecute(object parameter)
99  {
100  return _canExecute == null ? true : _canExecute(parameter);
101  }
102 
103  public event EventHandler CanExecuteChanged
104  {
105  add
106  {
107  CommandManager.RequerySuggested += value;
108  CommandManagerHelper.AddWeakReferenceHandler(ref _canExecuteChangedHandlers, value, 2);
109  }
110  remove
111  {
112  CommandManager.RequerySuggested -= value;
113  CommandManagerHelper.RemoveWeakReferenceHandler(_canExecuteChangedHandlers, value);
114  }
115  }
116 
117  public void Execute(object parameter)
118  {
119  try
120  {
121  _execute(parameter);
122  }
123  catch (Exception e)
124  {
125  // Let the central exception manager do its work.
126  // If the exception was not managed, rethrow it.
127  if (!ExceptionHandler.CentralHandler.Manage(this, e))
128  {
129  throw;
130  }
131  }
132  }
133 
134  #endregion // ICommand Members
135 
136  #region Public methods
137 
142  public DelegatingCommand ListenOn(string propertyName)
143  {
144  if (_viewModel == null)
145  {
146  throw new InvalidOperationException(
147  "To execute 'ListenOn', construct this DelegatingCommand with the parent view model.");
148  }
149  _viewModel.PropertyChanged += (object sender, PropertyChangedEventArgs e) =>
150  {
151  if (e.PropertyName == propertyName)
152  {
153  if (_viewModel.ViewDispatcher != null)
154  {
155  _viewModel.ViewDispatcher.BeginInvoke(
156  new Action(
157  () => this.OnCanExecuteChanged()
158  )
159  );
160  }
161  else
162  {
163  this.OnCanExecuteChanged();
164  }
165  }
166  };
167 
168  return this;
169  }
170 
171  #endregion
172 
173  #region Protected methods
174 
175  protected virtual void OnCanExecuteChanged()
176  {
177  CommandManagerHelper.CallWeakReferenceHandlers(_canExecuteChangedHandlers);
178  }
179 
180  #endregion
181 
182  #region Private properties
183 
184  readonly Action<object> _execute;
185  readonly Predicate<object> _canExecute;
186  readonly ViewModelBase _viewModel;
187  private List<WeakReference> _canExecuteChangedHandlers;
188 
189  #endregion
190  }
191 }
Command that implements ICommand and accepts delegates that contain the command implementation.
DelegatingCommand(Action< object > execute, Predicate< object > canExecute, ViewModelBase viewModel)
Creates a new command object whose executable state is determined by the canExecute method and that ...
DelegatingCommand(Action< object > execute, Predicate< object > canExecute)
Creates a new command object whose executable state is determined by the canExecute method...
DelegatingCommand(Action< object > execute)
Creates a new command object that can always execute.
DelegatingCommand ListenOn(string propertyName)
Makes DelegateCommnand listen on PropertyChanged events of some object, so that DelegateCommnand can ...
DelegatingCommand(Action< object > execute, ViewModelBase viewModel)
Creates a new command object that knows the view model that it belongs to.