Search code examples
c#windows-store-appsivalueconverter

Windows Store App Development - InvalidateRequerySuggested


in regular WPF projects I've used

CommandManager.InvalidateRequerySuggested();

in order to force a value converter to be executed again.

Now, in Windows Store App development this handy command is no longer available. Does an equivalent command or something else, which does the trick, exist?

Thanks a lot for your help!


Solution

  • The CommandManager doesn't exist in WinRT. You need to manually refresh listeners. Here's my example implementation of DelegateCommand<T> that illustrates this:

    using System;
    using System.Windows.Input;
    
    public class DelegateCommand<T> : ICommand
    {
        private readonly Action<T> m_executeAction;
        private readonly Predicate<T> m_canExecutePredicate;
    
        public DelegateCommand(Action<T> executeAction)
            : this(executeAction, null)
        {
        }
    
        public DelegateCommand(Action<T> executeAction, Predicate<T> canExecutePredicate)
        {
            if (executeAction == null)
            {
                throw new ArgumentNullException("executeAction");
            }
    
            m_executeAction = executeAction;
            m_canExecutePredicate = canExecutePredicate;
        }
    
        public event EventHandler Executed;
    
        public event EventHandler CanExecuteChanged;
    
        bool ICommand.CanExecute(object parameter)
        {
            return CanExecute((T)parameter);
        }
    
        void ICommand.Execute(object parameter)
        {
            Execute((T)parameter);
        }
    
        public bool CanExecute(T parameter)
        {
            var result = true;
            var canExecutePredicate = m_canExecutePredicate;
            if (canExecutePredicate != null)
            {
                result = canExecutePredicate(parameter);
            }
            return result;
        }
    
        public void Execute(T parameter)
        {
            m_executeAction(parameter);
            RaiseExecuted();
        }
    
        public void Refresh()
        {
            RaiseCanExecuteChanged();
        }
    
        protected virtual void RaiseExecuted()
        {
            var handler = Executed;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    
        protected virtual void RaiseCanExecuteChanged()
        {
            var handler = CanExecuteChanged;
            if (handler != null)
            {
                handler(this, EventArgs.Empty);
            }
        }
    }
    

    The WPF version of this class indirectly uses CommandManager.InvalidateRequerySuggested by implementing CanExecuteChanged as follows:

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
    

    However, in WinRT this is not supported and in my WinRT version any code that invalidates the state of the delegate command must call the Refresh method to cause bound items in the view to requery the command.

    I think the best solution to your specific problem would be to implement INotifyPropertyChanged in your view model. Invoking the PropertyChanged event on this interface is equivalent to my Refresh method and forces bound elements in the view to re-evaluate themselves and, thus, to re-run all associated IValueConverter instances.