When I first display my screen to the user, I\'d rather not have all the validation messages show up for required fields and such before the user has had a chance to fill in
Just to indicate how I handled this utilising IDataErrorInfo
...
I put a call to a new method called OnDataUpdated()
in each setter of my view-bound property, such as:
private string username;
public string Username
{
get { return username; }
set
{
username = value;
OnDataUpdated();
}
}
private string password;
public string Password
{
get { return password; }
set
{
password = value;
OnDataUpdated();
}
}
Then inside OnDataUpdated()
mark a private field boolean as true
indicating data has changed for the first time (FormType
was only necessary for my business case):
private void OnDataUpdated()
{
dataChanged = true;
// .. Any other universal RaisePropertyChanged() events you may want to call to get your UI into sync. Eg. RaisePropertyChanged(() => CanConfirm);
}
Then in my IDataErrorInfo
indexer property I do the following (I split it out so 'ValidForm()' can be called manually to perform form validation too.
public string this[string columnName]
{
get
{
string result = null;
if (columnName == "Username")
{
// If other payment amounts have fully paid for balance, and cash amount has been entered, deny
if (!ValidForm(FormType.Step1, columnName))
result = "Please enter the username field.";
}
else if (columnName == "Password")
{
if (!ValidForm(FormType.Step1, columnName))
result = "Please enter the password field.";
}
return result;
}
}
///
/// Test if valid form.
///
/// Specify which form we should validate.
/// If ommitted, entire form will be validated.
///
private bool ValidForm(FormType formType, string columnName = null)
{
// This field is used to denote when data has changed on the form.
// If data has changed, we know we can activate any form validation.
// We do not activate the form validation until after a user has typed
// something in at least.
if (!dataChanged) return true;
var errors = false;
if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Username") && string.IsNullOrEmpty(Username)))
errors = true;
if (formType == FormType.Step1 && ((string.IsNullOrEmpty(columnName) || columnName == "Password") && string.IsNullOrEmpty(Password)))
errors = true;
return !errors;
}
Works beautifully. Now I only have validation styles appearing after a user edits the form.
If you want some extra icing on the cake, you can comment in my RaisePropertyChanged(() => CanConfirm);
in the OnDataUpdated()
method and bind that to your Confirm Button IsEnabled={Binding CanConfirm}
with the associated property:
///
/// Can the user confirm step 1?
///
public bool CanConfirm
{
get { return ValidForm(FormType.Step1); }
}
and your button will only be enabled when your form is valid too. :)
Enjoy! and best of luck with the behemoth that is WPF.