How to make an ICommand CanExecute start with false?

832 Views Asked by At

I have error validation in my viewModel, such that when the UserName is not at least 2 characters long, it will have a validation error.

When my application starts up, this field is not validated and is considered to have no errors. It is only when the setter is called, does it check if the input is valid. In my form, this has the result that upon load there is no red box around the TextBox. However, as soon as the user types in a character, the UserName setter is called and it sees that the length is less than 2 characters, and as such has a validation error.

This is how it works by default, and this is what I want. I don't want to start off with the form open and having unwelcoming red boxes around the TextBox.

Now, on this form, I have a button that is tied to an ICommand. When the forum loads up, because the UserName field is technically not considered to have any errors, the button is enabled. However, when the user enters one character, it turns to disabled, and if he deletes everything it'll remain disabled as it should.

I want my form to load without any errors, but to have the button be disabled.

Now, my CanExecute() method is checking on a field I Have in my ViewModel which basically checks to see if the errors list count is greater than 0. If it is, it has errors and thus returns true. If not, it returns false.

I have a way to solve my above dilemma, but I do not like it. I have a check as such.

return UserName.Length < 2 || errors.Count > 0

Now this seems fine, but if I have a lot more fields that are being checked, such as Address and Port, I have to add these as well. All this really serves to do is provide this initial false for the CanExeute(), and it's useless at all other times, because it will be redundant. If the UserName.Length < 2, of course the errors. array will have some errors in it.

It would be nice, is if creating my ICommand, which in this case is a DelegateCommand from Prism, I can initialize it to be false and thus disabled.

1

There are 1 best solutions below

5
On

It sounds like all you should have to do is force the "CanExecute" of the command when it starts to ensure it is looking at most recent "criteria".

Since the interface requires the declaration of an event handler via

public event EventHandler CanExecuteChanged;

I'm sure you have something in your ICommand handler class such as

public void RaiseCanExecuteChanged()
{
    if (CanExecuteChanged != null)
        CanExecuteChanged(this, new EventArgs());
}

That said, in the startup of your view model where you have your ICommand object references instantiated, I would just

yourICommandButton.RaiseCanExecuteChanged();

This will force the check of the event and refresh itself as enabled or not before even the first keystroke in the field.

Clarification... Although I mention "button", I know there is no actual "button" in the view model, but an ICommand object that HANDLES the button's action via the Execute/CanExecute bindings.

As for refreshing the "red" border, that should NOT happen when you are just asking the ICommand handler to "RaiseCanExecuteChanged". If the "CanExecute" function returns FALSE, it will be disabled for the user...

public bool CanUserClickMe()
{
   return UserName.Length > 1 && errors.Count == 0;
}

This is not actually calling the validation tests against any explicit fields, just looking at the properties the person already has available to work with. If the user's name is not at least the two characters, it will return FALSE and thus disable the button ASSOCIATED to the ICommand object.