Disable save button when validation fails

前端 未结 3 606
爱一瞬间的悲伤
爱一瞬间的悲伤 2021-01-14 08:54

As you can likely see from the title, I am about to ask something which has been asked many times before. But still, after reading all these other questions, I cannot find a

相关标签:
3条回答
  • 2021-01-14 09:37

    I've implemented the map approach shown in my comment above, in C# this is called a Dictionary in which I am using anonymous methods to do the validation:

    partial class Player : IDataErrorInfo
    {
        private delegate string Validation(string value);
        private Dictionary<string, Validation> columnValidations;
        public List<string> Errors;
    
        public Player()
        {
            columnValidations = new Dictionary<string, Validation>();
            columnValidations["Firstname"] = delegate (string value) {
                return String.IsNullOrWhiteSpace(Firstname) ? "Geef een voornaam in" : null;
            }; // Add the others...
    
            errors = new List<string>();
        }
    
        public bool CanSave { get { return Errors.Count == 0; } }
    
        public string this[string columnName]
        {
            get { return this.GetProperty(columnName); } 
    
            set
            { 
                var error = columnValidations[columnName](value);
    
                if (String.IsNullOrWhiteSpace(error))
                    errors.Add(error);
                else
                    this.SetProperty(columnName, value);
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-14 09:40

    This approach works with Data Annotations. You can also bind the "IsValid" property to a Save button to enable/disable.

    public abstract class ObservableBase : INotifyPropertyChanged, IDataErrorInfo
    {
        #region Members
        private readonly Dictionary<string, string> errors = new Dictionary<string, string>();
        #endregion
    
        #region Events
    
        /// <summary>
        /// Property Changed Event
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;
    
        #endregion
    
        #region Protected Methods
    
        /// <summary>
        /// Get the string name for the property
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        /// <returns></returns>
        protected string GetPropertyName<T>(Expression<Func<T>> expression)
        {
            var memberExpression = (MemberExpression) expression.Body;
            return memberExpression.Member.Name;
        }
    
        /// <summary>
        /// Notify Property Changed (Shorted method name)
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression"></param>
        protected virtual void Notify<T>(Expression<Func<T>> expression)
        {
            string propertyName = this.GetPropertyName(expression);
            PropertyChangedEventHandler handler = this.PropertyChanged;
            handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        /// <summary>
        /// Called when [property changed].
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="expression">The expression.</param>
        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> expression)
        {
            string propertyName = this.GetPropertyName(expression);
            PropertyChangedEventHandler handler = this.PropertyChanged;
    
            handler?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    
        #endregion
    
        #region Properties
    
        /// <summary>
        /// Gets an error message indicating what is wrong with this object.
        /// </summary>
        public string Error => null;
    
        /// <summary>
        /// Returns true if ... is valid.
        /// </summary>
        /// <value>
        ///   <c>true</c> if this instance is valid; otherwise, <c>false</c>.
        /// </value>
        public bool IsValid => this.errors.Count == 0;
    
        #endregion
    
        #region Indexer
    
        /// <summary>
        /// Gets the <see cref="System.String"/> with the specified column name.
        /// </summary>
        /// <value>
        /// The <see cref="System.String"/>.
        /// </value>
        /// <param name="columnName">Name of the column.</param>
        /// <returns></returns>
        public string this[string columnName]
        {
            get
            {
                var validationResults = new List<ValidationResult>();
                string error = null;
    
                if (Validator.TryValidateProperty(GetType().GetProperty(columnName).GetValue(this), new ValidationContext(this) { MemberName = columnName }, validationResults))
                {
                    this.errors.Remove(columnName);
                }
                else
                {
                    error = validationResults.First().ErrorMessage;
    
                    if (this.errors.ContainsKey(columnName))
                    {
                        this.errors[columnName] = error;
                    }
                    else
                    {
                        this.errors.Add(columnName, error);
                    }
                }
    
                this.OnPropertyChanged(() => this.IsValid);
                return error;
            }
        }
    
        #endregion  
    }
    
    0 讨论(0)
  • 2021-01-14 09:53

    This article http://www.asp.net/mvc/tutorials/older-versions/models-%28data%29/validating-with-the-idataerrorinfo-interface-cs moves the individual validation into the properties:

    public partial class Player : IDataErrorInfo
    {
        Dictionary<string, string> _errorInfo;
    
        public Player()
        {
            _errorInfo = new Dictionary<string, string>();
        }
    
        public bool CanSave { get { return _errorInfo.Count == 0; }
    
        public string this[string columnName]
        {
            get 
            { 
                return _errorInfo.ContainsKey(columnName) ? _errorInfo[columnName] : null;
            }
        }
    
        public string FirstName
        {
            get { return _firstName;}
            set
            {
                if (String.IsNullOrWhiteSpace(value))
                    _errorInfo.AddOrUpdate("FirstName", "Geef een voornaam in");
                else
                {
                    _errorInfo.Remove("FirstName");
                    _firstName = value;
                }
            }
        }
    }
    

    (you would have to handle the Dictionary AddOrUpdate extension method). This is similar to your error count idea.

    0 讨论(0)
提交回复
热议问题