Esto realmente depende de su aplicación de IDataErrorInfo. Si lo basa en un Diccionario de mensajes de error, puede controlar cuándo se ejecuta la validación que se agrega a esa lista. Que normalmente se desee hacerlo desde su set de propiedad (como siempre que llame PropertyChange), aquí llamando CheckValidationState:
public string this[string columnName]
{
get
{
return ValidateProperty(columnName);
}
}
public Dictionary<string, string> Errors { get; private set; }
protected void SetError(string propertyName, string errorMessage)
{
Debug.Assert(!String.IsNullOrEmpty(propertyName), "propertyName is null or empty.");
if (String.IsNullOrEmpty(propertyName))
return;
if (!String.IsNullOrEmpty(errorMessage))
{
if (Errors.ContainsKey(propertyName))
Errors[propertyName] = errorMessage;
else
Errors.Add(propertyName, errorMessage);
}
else if (Errors.ContainsKey(propertyName))
Errors.Remove(propertyName);
NotifyPropertyChanged("Errors");
NotifyPropertyChanged("Error");
NotifyPropertyChanged("Item[]");
}
protected virtual string ValidateProperty(string propertyName)
{
return Errors.ContainsKey(propertyName) ? Errors[propertyName] : null;
}
protected virtual bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
}
También se puede incluir un método que valida todas sus propiedades (como durante una guardar):
protected bool Validate()
{
if (Errors.Count > 0)
return false;
bool result = true;
foreach (PropertyInfo propertyInfo in GetType().GetProperties())
{
if (!CheckValidationState(propertyInfo.Name, propertyInfo.GetValue(this, null)))
result = false;
NotifyPropertyChanged(propertyInfo.Name);
}
return result;
}
ACTUALIZACIÓN:
yo recomendaría poner el código anterior en una clase de modelo de vista de base para que pueda volver a utilizarlo. A continuación, podría crear una clase derivada de esta manera:
public class SampleViewModel : ViewModelBase
{
private string _firstName;
public SampleViewModel()
{
Save = new DelegateCommand<object>(SaveExecuted);
}
public DelegateCommand<object> Save { get; private set; }
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName == value)
return;
CheckValidationState("FirstName", value);
_firstName = value;
NotifyPropertyChanged("FirstName");
}
}
public void SaveExecuted(object obj)
{
bool isValid = Validate();
MessageBox.Show(isValid ? "Saved" : "Validation Error. Save canceled"); // TODO: do something appropriate to your app here
}
protected override bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
if (propertyName == "FirstName")
{
if (String.IsNullOrEmpty(proposedValue as String))
{
SetError(propertyName, "First Name is required.");
return false;
}
else if (proposedValue.Equals("John"))
{
SetError(propertyName, "\"John\" is not an allowed name.");
return false;
}
else
{
SetError(propertyName, String.Empty); // clear the error
return true;
}
}
return true;
}
}
En este caso estoy usando un DelegateCommand para activar la operación de almacenamiento, pero podría ser cualquier cosa que hace una llamada a un método para hacer el ahorro. Esta configuración permite que el estado vacío inicial aparezca como válido en la interfaz de usuario, pero un cambio o una llamada a Guardar actualiza el estado de validación. También puede ser mucho más general y más complicado en la forma en que realiza la validación, de modo que no todo termina en un método (aquí con algunas suposiciones sobre el tipo), pero esto se simplifica para que sea más fácil comenzar con .
Gracias por la respuesta John, ¿podría ampliar su respuesta un poco por favor? Traté de implementar lo que discutiste y me perdí un poco. Gracias ... – Burt
Burt - Actualicé para agregar más código para mostrar cómo una clase podría implementar esto que espero complete algunos de los agujeros para usted. ¿Eso te ayuda? –
Gracias John realmente lo aprecio, fui a votar, pero de alguna manera logré eliminar un voto que no me permitió agregarlo nuevamente. – Burt