Comment créer un atsortingbut de validation personnalisé?

Je souhaite créer un atsortingbut de validation personnalisé dans lequel je souhaite comparer la valeur de ma propriété avec la valeur d’une autre propriété dans ma classe de modèle. Par exemple, j’ai dans ma classe de modèle:

... public ssortingng SourceCity { get; set; } public ssortingng DestinationCity { get; set; } 

Et je veux créer un atsortingbut personnalisé pour l’utiliser comme ceci:

 [Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] public ssortingng DestinationCity { get; set; } //this wil lcompare SourceCity with DestinationCity 

Comment puis-je y arriver?

Voici comment vous pouvez obtenir la valeur de l’autre propriété:

 public class CustomAtsortingbute : ValidationAtsortingbute { private readonly ssortingng _other; public CustomAtsortingbute(ssortingng other) { _other = other; } protected override ValidationResult IsValid(object value, ValidationContext validationContext) { var property = validationContext.ObjectType.GetProperty(_other); if (property == null) { return new ValidationResult( ssortingng.Format("Unknown property: {0}", _other) ); } var otherValue = property.GetValue(validationContext.ObjectInstance, null); // at this stage you have "value" and "otherValue" pointing // to the value of the property on which this atsortingbute // is applied and the value of the other property respectively // => you could do some checks if (!object.Equals(value, otherValue)) { // here we are verifying whether the 2 values are equal // but you could do any custom validation you like return new ValidationResult(this.FormatErrorMessage(validationContext.DisplayName)); } return null; } } 

S’il vous plaît regardez ci-dessous pour mon exemple:

La classe de modèle implémente INotifyPropertyChanged

 public class ModelClass : INotifyPropertyChanged { private ssortingng destinationCity; public ssortingng SourceCity { get; set; } public ModelClass() { PropertyChanged += CustomAtsortingbute.ThrowIfNotEquals; } [Custom("SourceCity", ErrorMessage = "the source and destination should not be equal")] public ssortingng DestinationCity { get { return this.destinationCity; } set { if (value != this.destinationCity) { this.destinationCity = value; NotifyPropertyChanged("DestinationCity"); } } } public event PropertyChangedEventHandler PropertyChanged; protected virtual void NotifyPropertyChanged(ssortingng info) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(info)); } } } 

La classe d’atsortingbut contient également l’événement hendler.

 internal sealed class CustomAtsortingbute : Atsortingbute { public CustomAtsortingbute(ssortingng propertyName) { PropertyName = propertyName; } public ssortingng PropertyName { get; set; } public ssortingng ErrorMessage { get; set; } public static void ThrowIfNotEquals(object obj, PropertyChangedEventArgs eventArgs) { Type type = obj.GetType(); var changedProperty = type.GetProperty(eventArgs.PropertyName); var atsortingbute = (CustomAtsortingbute)changedProperty .GetCustomAtsortingbutes(typeof(CustomAtsortingbute), false) .FirstOrDefault(); var valueToCompare = type.GetProperty(atsortingbute.PropertyName).GetValue(obj, null); if (!valueToCompare.Equals(changedProperty.GetValue(obj, null))) throw new Exception("the source and destination should not be equal"); } } 

Usage

  var test = new ModelClass(); test.SourceCity = "1"; // Everything is ok test.DestinationCity = "1"; // throws exception test.DestinationCity ="2"; 

Pour simplifier le code, j’ai décidé d’omettre une validation.

Le meilleur moyen d’y parvenir est d’utiliser IValidatableObject. Voir http://msdn.microsoft.com/en-us/data/gg193959.aspx