I have a TextBox that is tied to a command like this:
<TextBox Text="{Binding Path=TextContent, UpdateSourceTrigger=PropertyChanged}">
<TextBox.InputBindings>
<KeyBinding Command="{Binding Path=MyCommand}" Key="Enter" />
</TextBox.InputBindings>
</TextBox>
The property TextContent is a string defined in the ViewModel. The command MyCommand is also defined in the ViewModel. The ViewModel does not know the View.
The command will be called whenever the TextBox has focus and the enter key is hit. Unfortunately, if CanExecute returns false, the user cannot see (visually) that the command was not executed, because there is no visual change in the TextBox.
I am looking for advice on how to show the user that the command could not be executed after he had pressed enter.
My ideas (and my doubts about them):
Disabling the TextBox when
CanExecutereturnsfalse: This is no option because the return value ofCanExecutecan change everytime a letter is typed/changed (the text in the TextBox influences the outcome ofCanExecute). When it is disabled for the first time, the user cannot type into it any more, so it will stay disabled forever.Show a message box saying that the command was not executed: Remember, the ViewModel does not know the View. Is it even possible to open a message box from the ViewModel? Furthermore, where should I put the call to opening a message box? Not inside
CanExecutebecause I only want to get the message box after hitting enter, not everytimeCanExecutereturnsfalse. Maybe makeCanExecutealways returntrueand do the checks insideExecute: If checks are okay, do the command stuff, if not, show some message to the user. But then, the point of havingCanExecuteis missed entirely...
I want to keep MVVM, but some codebehind for redirecting stuff to the ViewModel seems okay for me.
I suggest the following solution.
Here's an example on how to notify the user which I'm working on at the moment.
I want the user to type in a data limit which is of type int, double or string. It want to check so the user type in the correct type. I use a property ValidateLimits which checks the string MyLimits which in your case is TextContent.
Everytime the user type in anything in the TextBox, ValidateLimits will check the string. If it is not a valid string in the textbox then return false otherwise return true. If false then highlight it with the DataTrigger by setting some Properties on the TextBox which in my case is some Border and Foreground colors, also a ToolTip.
Also in your case you want to call your Validate method in your CanExecute method.
If you already have a function for checking that the command is OK then just add it to the DataTrigger binding.