MVVM bind RelayCommand CanExecute to a Property?

后端 未结 3 972
情歌与酒
情歌与酒 2021-01-14 02:04

I have a Timer and three buttons to control it: Start, Stop, and Pause.
Each button is bound to a RelayCommand.
I have a TimerState property of type enum Timer

3条回答
  •  长发绾君心
    2021-01-14 02:52

    Fabio's answer works well. Here's a parameterized version for DelegateCommand. (I've tightened up the code a little, too.)

    public class DepedencyCommand : DelegateCommand
        where TViewModel : INotifyPropertyChanged
    {
        private readonly List _propertiesToWatch;
    
        public DepedencyCommand(Action executedMethod)
            : base(executedMethod) { }
    
        public DepedencyCommand(Action executedMethod, Func canExecuteMethod)
            : base(executedMethod, canExecuteMethod) { }
    
        public DepedencyCommand(TViewModel viewModelInstance, Action executedMethod, Func canExecuteMethod, Expression> propertiesToWatch)
            : base(executedMethod, canExecuteMethod)
        {
    
            _propertiesToWatch = _RegisterPropertiesWatcher(propertiesToWatch);
            viewModelInstance.PropertyChanged += PropertyChangedHandler;
        }
    
    
        /// 
        /// handler that, everytime a monitored property changes, calls the RaiseCanExecuteChanged of the command
        /// 
        /// 
        /// 
        private void PropertyChangedHandler(object sender, PropertyChangedEventArgs e)
        {
            if (_propertiesToWatch.Contains(e.PropertyName))
            {
                this.OnCanExecuteChanged();
            }
        }
    
        /// 
        /// giving an expression that identify a propriety or a list of properties, return the property names obtained from the expression
        /// Examples on selector usage
        /// proprietà singola:
        ///   entity => entity.PropertyName
        /// proprietà multiple
        ///   entity => new { entity.PropertyName1, entity.PropertyName2 }
        /// 
        /// 
        /// 
        private static List _RegisterPropertiesWatcher(Expression> selector)
        {
            var properties = new List();
    
            LambdaExpression lambda = selector;
    
            if (lambda.Body is MemberExpression)
            {
                var memberExpression = (MemberExpression)lambda.Body;
                properties.Add(memberExpression.Member.Name);
            }
            else if (lambda.Body is UnaryExpression)
            {
                var unaryExpression = (UnaryExpression)lambda.Body;
    
                properties.Add(((MemberExpression)unaryExpression.Operand).Member.Name);
            }
            else if (lambda.Body.NodeType == ExpressionType.New)
            {
                var newExp = (NewExpression)lambda.Body;
                foreach (var argument in newExp.Arguments)
                {
                    if (argument is MemberExpression)
                    {
                        MemberExpression mExp = (MemberExpression)argument;
                        properties.Add(mExp.Member.Name);
                    }
                    else
                        throw new SyntaxErrorException("Syntax Error, selector has to be an expression that returns a new object containing a list of properties, e.g.: s => new { s.Property1, s.Property2 }");
                }
            }
            else
                throw new SyntaxErrorException("Syntax Error, selector has to be an expression that returns a new object containing a list of properties, e.g.: s => new { s.Property1, s.Property2 }");
    
            return properties;
        }
    }
    

提交回复
热议问题