Search code examples
c#.netwpfxaml.net-5

On ValidatesOnExceptions UI is not updating


Given is an Wpf .Net5.0 Application with an Resetbutton and Textbox

  • Reset set path to Defalut Command="{Binding ResetCommand}" ... FilePath = @"C:\Temp";

  • Textbox: User can edit Path Text="{Binding FilePath, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, ValidatesOnExceptions=True}"

     private string _filePath;
    
     public string FilePath
     {
         get => _filePath;
         set
         {
             var r = new Regex(@"[\w\s\\.:\-!~]");
             if (r.Matches(value).Count == value.Length)
             {
                 SetProperty(ref _filePath, value);
                 return;
             }
    
             throw new ArgumentException("Not an valid windows path");
         }
     }
    

When the path is valid I can reset to Default. UI Updates When user enter an invalid character the border turns red and the Reset button not updating UI.

I try to debug by Snoop and its look like the VM is reseting. But not UI. What is wrong?

Working Demo: https://github.com/LwServices/WpfValidationDemo/tree/master/ValidationWpf


Solution

  • Simple solution

    you can solve it by notifying your UI directly after set the value

    private void Reset()
    {
        FilePath = @"C:\Temp";
        OnPropertyChanged(nameof(FilePath));
    }
    

    reason of the problem

    when the Filepath is not matching your Regex, you just raise an exception without modifying the value of _filePath and it will be always valid path

    public string FilePath
    {
        get => _filePath;
        set
        {
            var r = new Regex(@"[\w\s\\.:\-!~]");
            if (r.Matches(value).Count == value.Length)
            {
                SetProperty(ref _filePath, value); //<<<<<< this will never call if the value passed from the ui doesnot match Regex
                return;
            }
    
            throw new ArgumentException("Not an valid windows path");
        }
    }
    

    when you call reset() you try to set Filepath to c:/temp and if the last value of _filePath is equal to c:/temp the problem will be appear from the following

    protected bool SetProperty<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
    {
       if (EqualityComparer<T>.Default.Equals(field, value)) return false;  /// your code will return 
       field = value;
       OnPropertyChanged(propertyName); // before notify the UI
       return true;
    }
    

    so as suggested in the beginning the simple solution is to notify your UI directly OR delete the check line from SetProperty method

    if (EqualityComparer<T>.Default.Equals(field, value)) return false;