Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the CanExecute Method from ICommand on WPF

How does one use the CanExecute Method from the ICommand interface?


In my example i have a SaveCommand which i only what to be enable when the object is saveable. The XAML Code of my Savebutton looks like this:

<Button Content="Save" Command="{Binding SaveCommand, Mode=TwoWay}" />

This is the code of my save class:

class Save : ICommand
{
    public MainWindowViewModel viewModel { get; set; }

    public Save(MainWindowViewModel viewModel)
    {
        this.viewModel = viewModel;
    }

    public bool CanExecute(object parameter)
    {

        if (viewModel.IsSaveable == false)
            return false;
        return true;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        viewModel.Save();
    }
}

The save property in the ViewModel looks like this:

    public ICommand SaveCommand
    {
        get
        {
            saveCommand = new Save(this);
            return saveCommand;
        }
        set
        {
            saveCommand = value;
        }
    }

This construct didn't work. The button does not enable its self when isSaveable is true.

like image 591
Christoph Avatar asked May 02 '15 12:05

Christoph


1 Answers

Instead of defining your own implementation of ICommand, use a RelayCommand.

In the below sample code, the save Button is enabled when the user types something in the TextBox.

XAML:

<Window x:Class="RelayCommandDemo.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel HorizontalAlignment="Center">
        <TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged}" Margin="5" Width="120"/>
        <Button Content="Save" Command="{Binding SaveCommand}" Margin="3"/>
    </StackPanel>
</Window>

Code behind:

using System;
using System.Windows;
using System.Windows.Input;

namespace RelayCommandDemo
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            DataContext = new VM();
        }
    }
    public class VM
    {
        public String Name { get; set; }

        private ICommand _SaveCommand;

        public ICommand SaveCommand
        {
            get { return _SaveCommand; }
        }

        public VM()
        {
            _SaveCommand = new RelayCommand(SaveCommand_Execute, SaveCommand_CanExecute);
        }

        public void SaveCommand_Execute()
        {
            MessageBox.Show("Save Called");
        }

        public bool SaveCommand_CanExecute()
        {
            if (string.IsNullOrEmpty(Name))
                return false;
            else
                return true;
        }
    }

    public class RelayCommand : ICommand
    {
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }
        private Action methodToExecute;
        private Func<bool> canExecuteEvaluator;
        public RelayCommand(Action methodToExecute, Func<bool> canExecuteEvaluator)
        {
            this.methodToExecute = methodToExecute;
            this.canExecuteEvaluator = canExecuteEvaluator;
        }
        public RelayCommand(Action methodToExecute)
            : this(methodToExecute, null)
        {
        }
        public bool CanExecute(object parameter)
        {
            if (this.canExecuteEvaluator == null)
            {
                return true;
            }
            else
            {
                bool result = this.canExecuteEvaluator.Invoke();
                return result;
            }
        }
        public void Execute(object parameter)
        {
            this.methodToExecute.Invoke();
        }
    }
}
like image 176
Anand Murali Avatar answered Oct 25 '22 13:10

Anand Murali