wpf

[WPF] RelayCommand

RelayCommand implement ICommand and lets you define an action that shall be used when Execute called. That is how you end up using one class for all commands and you just change the action instead of creating each class for each command implementing ICommand.

public class RelayCommand : ICommand
    {
        Action _TargetExecuteMethod;
        Func _TargetCanExecuteMethod;
 
        public RelayCommand(Action executeMethod)
        {
            _TargetExecuteMethod = executeMethod;
        }
 
        public RelayCommand(Action executeMethod, Func canExecuteMethod)
        {
            _TargetExecuteMethod = executeMethod;
            _TargetCanExecuteMethod = canExecuteMethod;
        }
 
        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
        #region ICommand Members
 
        bool ICommand.CanExecute(object parameter)
        {
            if (_TargetCanExecuteMethod != null)
            {
                return _TargetCanExecuteMethod();
            }
            if (_TargetExecuteMethod != null)
            {
                return true;
            }
            return false;
        }
 
        // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
        // Prism commands solve this in their implementation
        public event EventHandler CanExecuteChanged = delegate { };
 
        void ICommand.Execute(object parameter)
        {
            if (_TargetExecuteMethod != null)
            {
                _TargetExecuteMethod();
            }
        }
        #endregion
    }
 
    public class RelayCommand : ICommand
    {
        Action _TargetExecuteMethod;
        Func<T, bool> _TargetCanExecuteMethod;
 
        public RelayCommand(Action executeMethod)
        {
            _TargetExecuteMethod = executeMethod;
        }
 
        public RelayCommand(Action executeMethod, Func<T, bool> canExecuteMethod)
        {
            _TargetExecuteMethod = executeMethod;
            _TargetCanExecuteMethod = canExecuteMethod;
        }
 
        public void RaiseCanExecuteChanged()
        {
            CanExecuteChanged(this, EventArgs.Empty);
        }
        #region ICommand Members
 
        bool ICommand.CanExecute(object parameter)
        {
            if (_TargetCanExecuteMethod != null)
            {
                T tparm = (T)parameter;
                return _TargetCanExecuteMethod(tparm);
            }
            if (_TargetExecuteMethod != null)
            {
                return true;
            }
            return false;
        }
 
        // Beware - should use weak references if command instance lifetime is longer than lifetime of UI objects that get hooked up to command
        // Prism commands solve this in their implementation
        public event EventHandler CanExecuteChanged = delegate { };
 
        void ICommand.Execute(object parameter)
        {
            if (_TargetExecuteMethod != null)
            {
                _TargetExecuteMethod((T)parameter);
            }
        }
        #endregion
    }

Example:

I would like to implement a SearchCommand in my following ViewModel. I will first declare a command variable and then create an instant of it in ViewModel constructor, and finally, define the method action.

public class WeatherViewModel: ViewModelBase
    {
        public RelayCommand SearchCommand { get; }
 
        public WeatherViewModel()
        {
            SearchCommand = new RelayCommand(OnSearch);
        }
        private void OnSearch()
        {
            var result = _openWeatherMapHelper.GetResult(Keyword);
 
            Name = result.Name;
            Humidity = result.Main.Humidity;
            Desc = result.Weather[0].Description;
            Temperature = result.Main.Temp;
        }
    }
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s