61
votes

I have a view AttributeView that contains all sorts of attributes. There's also a button that when pressed, it should set the default values to the attributes. I also have a ViewModelBase class that is a base class for all ViewModels I have. The problem is I can't seem to get the button bound to the command with WPF.

I've tried this, but it just doesn't do anything:

<Button Command="{Binding DataInitialization}" Content="{x:Static localProperties:Resources.BtnReinitializeData}"></Button>

The command is defined (in the ViewModelBase) like this:

public CommandBase DataInitialization { get; protected set; }

and on application startup a new instance is created for the command:

DataInitialization = new DataInitializationCommand()

However, the WPF binding doesn't seem to "find" the command (pressing the button does nothing). The ViewModel used in the current view is derived from the ViewModelBase. What else I can try (I'm quite new to WPF so this might be a very simple question)?

1
Does the CommandBase inherits from ICommand? Does the Buttons DataContext contains DataInitialization command? Do you have any message in output panel about the binding? - Miklós Balogh
Yes it inherits ICommand. How do I check the button's DataContext? I'm not sure about the messages in output (should there be any by default?). - kor_
it would be easier if you show more code about the viewmodel and the xaml - Miklós Balogh
Can you please show your VM code where the members of ICommand interface are implemented. - yo chauhan
Do you mean the DataInitializationCommand code (which derives from CommandBase, which in turn implements the ICommand)? How does the VM relate to ICommand interface? - kor_

1 Answers

142
votes
 <Grid >
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>
    <Button Command="{Binding ClickCommand}" Width="100" Height="100" Content="wefwfwef"/>
</Grid>

the code behind for the window:

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModelBase();
    }
}

The ViewModel:

public class ViewModelBase
{
    private ICommand _clickCommand;
    public ICommand ClickCommand
    {
        get
        {
            return _clickCommand ?? (_clickCommand = new CommandHandler(() => MyAction(), ()=> CanExecute));
        }
    }
     public bool CanExecute
     {
        get
        {
            // check if executing is allowed, i.e., validate, check if a process is running, etc. 
            return true/false;
        }
     }

    public void MyAction()
    {

    }
}

Command Handler:

 public class CommandHandler : ICommand
{
    private Action _action;
    private Func<bool> _canExecute;

    /// <summary>
    /// Creates instance of the command handler
    /// </summary>
    /// <param name="action">Action to be executed by the command</param>
    /// <param name="canExecute">A bolean property to containing current permissions to execute the command</param>
    public CommandHandler(Action action, Func<bool> canExecute)
    {
        _action = action;
        _canExecute = canExecute;
    }

    /// <summary>
    /// Wires CanExecuteChanged event 
    /// </summary>
    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    /// <summary>
    /// Forcess checking if execute is allowed
    /// </summary>
    /// <param name="parameter"></param>
    /// <returns></returns>
    public bool CanExecute(object parameter)
    {
        return _canExecute.Invoke();
    }

    public void Execute(object parameter)
    {
        _action();
    }
}

I hope this will give you the idea.