Search code examples
wpfnsregularexpression

Using RegularExpression as attribute in .NET


I am testing use of regular expression as attribute in my application, but it is simply not working.

public partial class MainWindow : Window
{
    [Required]
    [RegularExpression(@"^[\d]+")]
    public string number { get; set; }

    public MainWindow()
    {
        InitializeComponent();
        number = "sometext";
    }
 }

No error is being thrown and number accepts anything without caring for RegularExpression attribute.

How can I make number only to accept what is mentioned in regex? Usually I do validate in setter, but have learnt recently about attribute and wish to use it.

Thanks.


Solution

  • Your binding source must implement the IDataErrorInfo interface. Then you can set the ValidatesOnDataErrors and NotifyOnValidationError propeties on the binding.

    See a simplified example below.

    A base class to handle property changes and validation.


    internal abstract class ValidatedObservableBase : INotifyPropertyChanged, IDataErrorInfo
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        public string this[string columnName]
        {
            get
            {
                var results = new List<ValidationResult>();
                var valid = Validator.TryValidateProperty(GetType().GetProperty(columnName)?.GetValue(this), new ValidationContext(this) { MemberName = columnName }, results);
    
                return valid ? null : results[0].ErrorMessage;
            }
        }
    
        public string Error
        {
            get => null;
        }
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    

    The model, derived from the above base class.


    internal class Model : ValidatedObservableBase
    {
        private string number;
    
        [Required(ErrorMessage = "Required error")]
        [RegularExpression(@"^[\d]+", ErrorMessage = "Regex error")]
        public string Number
        {
            get => number;
            set
            {
                number = value;
                OnPropertyChanged();
            }
        }
    }
    

    A simple view model to set as the window's DataContext.


    internal class ViewModel
    {
        public Model Model { get; set; } = new Model();
    }
    

    Lastly, the window.


    <Window
        ...
        xmlns:local="clr-namespace:Demo"
        mc:Ignorable="d">
        <Window.DataContext>
            <local:ViewModel />
        </Window.DataContext>
        <StackPanel>
            <TextBox
                x:Name="TB"
                Margin="24,24,24,0"
                VerticalAlignment="Top"
                Text="{Binding Path=Model.Number, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, NotifyOnValidationError=True}" />
            <TextBlock
                Margin="24,4,24,24"
                Foreground="Red"
                Text="{Binding ElementName=TB, Path=(Validation.Errors)[0].ErrorContent}" />
        </StackPanel>
    </Window>
    

    demo