Implémentation de la validation pour les zones de texte WPF

J’ai 3 TextBoxes ( Id1 , Name et Salary ). Id et Salary doivent contenir des entiers et Name doit contenir uniquement des caractères. J’ai besoin de validations pour ma zone de texte, elle devrait afficher des erreurs lorsque je saisis des caractères ou des entiers incorrects. Cela peut-il aussi être fait uniquement dans Xaml sans codebehind? S’il vous plaît aidez-moi avec le code requirejs

C’est le code Xaml:

    

Il y a 3 façons d’implémenter la validation:

  1. Règle de validation
  2. Mise en oeuvre de INotifyDataErrorInfo
  3. Implémentation de IDataErrorInfo

Exemple de règle de validation :

 public class NumericValidationRule : ValidationRule { public Type ValidationType { get; set; } public override ValidationResult Validate(object value, CultureInfo cultureInfo) { ssortingng strValue = Convert.ToSsortingng(value); if (ssortingng.IsNullOrEmpty(strValue)) return new ValidationResult(false, $"Value cannot be coverted to ssortingng."); bool canConvert = false; switch (ValidationType.Name) { case "Boolean": bool boolVal = false; canConvert = bool.TryParse(strValue, out boolVal); return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of boolean"); case "Int32": int intVal = 0; canConvert = int.TryParse(strValue, out intVal); return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Int32"); case "Double": double doubleVal = 0; canConvert = double.TryParse(strValue, out doubleVal); return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Double"); case "Int64": long longVal = 0; canConvert = long.TryParse(strValue, out longVal); return canConvert ? new ValidationResult(true, null) : new ValidationResult(false, $"Input should be type of Int64"); default: throw new InvalidCastException($"{ValidationType.Name} is not supported"); } } } 

XAML:

Très important : n’oubliez pas de définir ValidatesOnTargetUpdated="True" cela ne fonctionnera pas sans cette définition.

             

Exemple INotifyDataErrorInfo :

 public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo { #region INotifyPropertyChanged public event PropertyChangedEventHandler PropertyChanged; public void OnPropertyChanged([CallerMemberName] ssortingng propertyName = null) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } ValidateAsync(); } #endregion public virtual void OnLoaded() { } #region INotifyDataErrorInfo private ConcurrentDictionary> _errors = new ConcurrentDictionary>(); public event EventHandler ErrorsChanged; public void OnErrorsChanged(ssortingng propertyName) { var handler = ErrorsChanged; if (handler != null) handler(this, new DataErrorsChangedEventArgs(propertyName)); } public IEnumerable GetErrors(ssortingng propertyName) { List errorsForName; _errors.TryGetValue(propertyName, out errorsForName); return errorsForName; } public bool HasErrors { get { return _errors.Any(kv => kv.Value != null && kv.Value.Count > 0); } } public Task ValidateAsync() { return Task.Run(() => Validate()); } private object _lock = new object(); public void Validate() { lock (_lock) { var validationContext = new ValidationContext(this, null, null); var validationResults = new List(); Validator.TryValidateObject(this, validationContext, validationResults, true); foreach (var kv in _errors.ToList()) { if (validationResults.All(r => r.MemberNames.All(m => m != kv.Key))) { List outLi; _errors.TryRemove(kv.Key, out outLi); OnErrorsChanged(kv.Key); } } var q = from r in validationResults from m in r.MemberNames group r by m into g select g; foreach (var prop in q) { var messages = prop.Select(r => r.ErrorMessage).ToList(); if (_errors.ContainsKey(prop.Key)) { List outLi; _errors.TryRemove(prop.Key, out outLi); } _errors.TryAdd(prop.Key, messages); OnErrorsChanged(prop.Key); } } } #endregion } 

Voir l’implémentation du modèle:

 public class MainFeedViewModel : BaseViewModel//, IDataErrorInfo { private ObservableCollection _feedItems; [XmlIgnore] public ObservableCollection FeedItems { get { return _feedItems; } set { _feedItems = value; OnPropertyChanged("FeedItems"); } } [XmlIgnore] public ObservableCollection FilteredFeedItems { get { if (SearchText == null) return _feedItems; return new ObservableCollection(_feedItems.Where(x => x.Title.ToUpper().Contains(SearchText.ToUpper()))); } } private ssortingng _title; [Required] [SsortingngLength(20)] //[CustomNameValidationRegularExpression(5, 20)] [CustomNameValidationAtsortingbute(3, 20)] public ssortingng Title { get { return _title; } set { _title = value; OnPropertyChanged("Title"); } } private ssortingng _url; [Required] [SsortingngLength(200)] [Url] //[CustomValidation(typeof(MainFeedViewModel), "UrlValidation")] ///  /// Validation of URL should be with custom method like the one that implemented below, or with ///  public ssortingng Url { get { return _url; } set { _url = value; OnPropertyChanged("Url"); } } public MainFeedViewModel(ssortingng url, ssortingng title) { Title = title; Url = url; } ///  /// ///  public MainFeedViewModel() { } public MainFeedViewModel(ObservableCollection feeds) { _feedItems = feeds; } private ssortingng _searchText; [XmlIgnore] public ssortingng SearchText { get { return _searchText; } set { _searchText = value; OnPropertyChanged("SearchText"); OnPropertyChanged("FilteredFeedItems"); } } #region Data validation local ///  /// Custom URL validation method ///  ///  ///  ///  public static ValidationResult UrlValidation(object obj, ValidationContext context) { var vm = (MainFeedViewModel)context.ObjectInstance; if (!Uri.IsWellFormedUriSsortingng(vm.Url, UriKind.Absolute)) { return new ValidationResult("URL should be in valid format", new List { "Url" }); } return ValidationResult.Success; } #endregion } 

XAML:

                         

IDataErrorInfo :

Voir le modèle:

 public class OperationViewModel : ViewModelBase, IDataErrorInfo { private const int ConstCodeMinValue = 1; private readonly IEventAggregator _eventAggregator; private OperationInfoDefinition _operation; private readonly IEntityFilterer _contextFilterer; private OperationDescriptionViewModel _description; public long Code { get { return _operation.Code; } set { if (SetProperty(value, _operation.Code, o => _operation.Code = o)) { UpdateDescription(); } } } public ssortingng Description { get { return _operation.Description; } set { if (SetProperty(value, _operation.Description, o => _operation.Description = o)) { UpdateDescription(); } } } public ssortingng FriendlyName { get { return _operation.FriendlyName; } set { if (SetProperty(value, _operation.FriendlyName, o => _operation.FriendlyName = o)) { UpdateDescription(); } } } public int Timeout { get { return _operation.Timeout; } set { if (SetProperty(value, _operation.Timeout, o => _operation.Timeout = o)) { UpdateDescription(); } } } public ssortingng Category { get { return _operation.Category; } set { if (SetProperty(value, _operation.Category, o => _operation.Category = o)) { UpdateDescription(); } } } public bool IsManual { get { return _operation.IsManual; } set { if (SetProperty(value, _operation.IsManual, o => _operation.IsManual = o)) { UpdateDescription(); } } } void UpdateDescription() { //some code } #region Validation #region IDataErrorInfo public ValidationResult Validate() { return ValidationService.Instance.ValidateNumber(Code, ConstCodeMinValue, long.MaxValue); } public ssortingng this[ssortingng columnName] { get { var validation = ValidationService.Instance.ValidateNumber(Code, ConstCodeMinValue, long.MaxValue); return validation.IsValid ? null : validation.ErrorContent.ToSsortingng(); } } public ssortingng Error { get { var result = Validate(); return result.IsValid ? null : result.ErrorContent.ToSsortingng(); } } #endregion #endregion } 

XAML:

                                

Vous pouvez également implémenter IDataErrorInfo comme suit dans le modèle de vue. Si vous implémentez IDataErrorInfo , vous pouvez effectuer la validation en ce sens qu’au lieu de définir une propriété particulière, puis, en cas d’erreur, renvoyez un message d’erreur de sorte que la zone de texte à l’origine de l’erreur contienne une zone rouge indiquant un Erreur.

 class ViewModel : INotifyPropertyChanged, IDataErrorInfo { private ssortingng m_Name = "Type Here"; public ViewModel() { } public ssortingng Name { get { return m_Name; } set { if (m_Name != value) { m_Name = value; OnPropertyChanged("Name"); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(ssortingng propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } public ssortingng Error { get { return "...."; } } ///  /// Will be called for each and every property when ever its value is changed ///  /// Name of the property whose value is changed ///  public ssortingng this[ssortingng columnName] { get { return Validate(columnName); } } private ssortingng Validate(ssortingng propertyName) { // Return error message if there is error on else return empty or null ssortingng ssortingng validationMessage = ssortingng.Empty; switch (propertyName) { case "Name": // property name // TODO: Check validiation condition validationMessage = "Error"; break; } return validationMessage; } } 

Et vous devez définir ValidatesOnDataErrors=True dans le code XAML afin d’appeler les méthodes de IDataErrorInfo comme suit:

  

Pour le faire uniquement avec XAML, vous devez append des règles de validation pour des propriétés individuelles. Mais je vous recommanderais d’approuver le code derrière l’approche. Dans votre code, définissez vos spécifications dans les parameters de propriétés et émettez des exceptions chaque fois que cela n’est pas conforme à vos spécifications. Et utilisez le modèle d’erreur pour afficher vos erreurs à l’utilisateur dans l’interface utilisateur. Votre XAML ressemblera à ceci

        

Code Derrière:

 public partial class MainWindow : Window { private ExampleViewModel m_ViewModel; public MainWindow() { InitializeComponent(); m_ViewModel = new ExampleViewModel(); DataContext = m_ViewModel; } } public class ExampleViewModel : INotifyPropertyChanged { private ssortingng m_Name = "Type Here"; public ExampleViewModel() { } public ssortingng Name { get { return m_Name; } set { if (Ssortingng.IsNullOrEmpty(value)) { throw new Exception("Name can not be empty."); } if (value.Length > 12) { throw new Exception("name can not be longer than 12 charectors"); } if (m_Name != value) { m_Name = value; OnPropertyChanged("Name"); } } } public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged(ssortingng propertyName) { if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } } } 

J’ai implémenté cette validation. Mais vous seriez utilisé du code derrière. C’est trop facile et le plus simple.

XAML: Pour le nom valide, entrez uniquement les caractères de A à Z et az.

   

Code Derrière.

 private void first_name_texbox_PreviewTextInput ( object sender, TextCompositionEventArgs e ) { Regex regex = new Regex ( "[^a-zA-Z]+" ); if ( regex.IsMatch ( first_name_texbox.Text ) ) { MessageBox.Show("Invalid Input !"); } } 

Pour la validation des salaires et des identifiants, remplacez la valeur passée par le constructeur de l’expression rationnelle par [0-9]+ . Cela signifie que vous ne pouvez entrer qu’un nombre de 1 à l’infini

Vous pouvez également définir la longueur avec [0-9]{1,4} . Cela signifie que vous ne pouvez entrer qu’un nombre inférieur ou égal à 4 chiffres. Ce baracket signifie {au moins, combien de nombre}. En faisant cela, vous pouvez définir une plage de nombres dans la zone de texte.

Puisse-t-il aider les autres.

XAML:

Code Derrière.

 private void salary_texbox_PreviewTextInput ( object sender, TextCompositionEventArgs e ) { Regex regex = new Regex ( "[^0-9]+" ); if ( regex.IsMatch ( salary_texbox.Text ) ) { MessageBox.Show("Invalid Input !"); } } 

Quand il s’agit de la réponse de Muhammad Mehdi, il vaut mieux faire:

 private void salary_texbox_PreviewTextInput(object sender, TextCompositionEventArgs e) { Regex regex = new Regex ( "[^0-9]+" ); if(regex.IsMatch(e.Text)) { MessageBox.Show("Error"); } } 

Parce que lors de la comparaison avec TextCompositionEventArgs, il obtient également le dernier caractère, contrairement à textbox.Text. Avec zone de texte, l’erreur montrera après le caractère inséré suivant.