Question

I have a very simple button binded to a command

    <Button Content="Add" Margin="10,10,10,0" Command="{Binding SaveCommand}" ></Button>

My command code

    public ICommand SaveCommand
    {
        get;
        internal set;
    }

    private bool CanExecuteSaveCommand()
    {
        return DateTime.Now.Second % 2 == 0;
    }

    private void CreateSaveCommand()
    {
        SaveCommand = new DelegateCommand(param => this.SaveExecute(), param => CanExecuteSaveCommand());
    }

    public void SaveExecute()
    {
        PharmacyItem newItem = new PharmacyItem();
        newItem.Name = ItemToAdd.Name;
        newItem.IsleNumber = ItemToAdd.IsleNumber;
        newItem.ExpDate = ItemToAdd.ExpDate;
        PI.Add(newItem);
    }

The code effectively blocks the command from running based on CanExecuteSaveCommand but the button is never disabled, is there a way to achieve this?

Was it helpful?

Solution

ICommand.CanExecute() is called automatically by WPF whenever it thinks the command availability may have changed. This generally tends to be on user activity, eg keyboard events, focus events etc.

Since your command availability changes purely based on time, WPF has no way of guessing that it has changed. Instead you need to give it a hint by calling CommandManager.InvalidateRequerySuggested();

Since your command availability changes every second, you would need to set up a timer to call this function at least every second.

Note that although InvalidateRequerySuggested() is the easiest solution, it will cause WPF to re-evaluate ALL command availabilities. If this is a performance problem, you can raise the CanExecuteChanged event on your ICommand instance instead.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top