In the previous example, you saw how the ViewModelBase.IsComplete
method is used to trigger validation of a viewmodel. This section looks at extending the validation to set control-enabled states based on the presence of validation errors and at hiding validation errors until the user has had a chance to fill out the form.
Before proceeding, you may want to briefly review the section “Performing Group Validation” earlier in the chapter, and in particular Figure 26.7.
The SendEmailViewModel
in the downloadable sample code is a more complex example of asynchronous input validation. In it, the sendEmailCommand
is prevented from executing if it is already in execution or if the form is invalid.
When SendEmailView
is first displayed, the Send button is enabled and no validation errors are displayed (see Figure 26.14).
When the Send button is tapped, the viewmodel is validated. If invalid, the Send button is disabled (see Figure 26.15).
The Send button is bound to the viewmodel’s ICommand
named SendEmailCommand
, as shown:
<Button Content="Send"
Command="{Binding SendEmailCommand}" />
Evaluation of whether the command can execute depends on the following criteria:
If the command is in execution, it cannot be executed.
If an attempt to execute the command has not occurred before, it can be executed.
If the viewmodel has validation errors, it cannot be executed.
SendEmailCommand
is instantiated in the viewmodel constructor, as shown:
sendEmailCommand = new DelegateCommand(arg => SendEmail(),
arg => !sending && (!sendAttempted || !HasErrors));
The SendEmail
method passes three Lambda expressions to the ViewModelBase
class’s IsComplete
method (see Listing 26.6). The first action is performed if the form is deemed complete, in which case an EmailComposeTask
is used to dispatch the email. The second action is performed if the form is not complete, and the third displays a warning message if an error is raised.
void SendEmail()
{
if (sending)
{
return;
}
try
{
sending = sendAttempted = true;
Message = string.Empty;
RefreshCommands();
IsComplete(() =>
{
sending = false;
EmailComposeTaskAdapter task = getEmailTaskAdapter();
task.Body = body;
task.Cc = cc;
task.Subject = subject;
task.To = to;
task.Show();
},
() =>
{
sending = false;
RefreshCommands();
},
obj =>
{
sending = false;
RefreshCommands();
string errorMessage = obj != null
? obj.Message : string.Empty;
Message = "Unable to send email: "
+ errorMessage;
});
}
catch (Exception ex)
{
sending = false;
Message = "Unable to send email: " + ex.Message;
}
}
A call to RefreshCommands
raises the CanExecuteChanged
event of the command, which in turn sets the IsEnabled
property of the button:
void RefreshCommands()
{
sendEmailCommand.RaiseCanExecuteChanged();
}
3.133.146.47