【问题标题】:On ValidatesOnExceptions UI is not updating在 ValidatesOnExceptions UI 未更新
【发布时间】:2021-10-12 06:25:45
【问题描述】:

Given 是一个 Wpf .Net5.0 应用程序 带有重置按钮和文本框

  • 将设置路径重置为 Defalut Command="{Binding ResetCommand}" ... FilePath = @"C:\Temp";

  • 文本框:用户可以编辑路径 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");
         }
     }
    

当路径有效时,我可以重置为默认值。用户界面更新 当用户输入无效字符时,边框会变为红色,并且重置按钮不会更新 UI。

我尝试通过 Snoop 进行调试,看起来虚拟机正在重置。但不是用户界面。 怎么了?

工作演示:https://github.com/LwServices/WpfValidationDemo/tree/master/ValidationWpf

【问题讨论】:

    标签: c# .net wpf xaml .net-5


    【解决方案1】:

    简单的解决方案

    你可以通过设置值后直接通知你的UI来解决它

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

    问题原因

    Filepath 与您的正则表达式不匹配时,您只需引发异常而不修改_filePath 的值,它将始终是有效路径

    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");
        }
    }
    

    当您调用 reset() 时,您尝试将 Filepath 设置为 c:/temp 并且如果 _filePath 的最后一个值等于 c:/temp > 问题会从下面出现

    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;
    }
    

    所以正如开头所建议的那样,简单的解决方案是直接通知您的用户界面SetProperty方法中删除检查行

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

    【讨论】:

      【解决方案2】:

      由于缺少 CanExecute 方法而禁用,请使用以下代码

          internal class MainWindowViewModel : NotifyPropertyChanged {
      
          private DelegateCommand _resetCmd;
          public ICommand ResetCommand => _resetCmd ?? new DelegateCommand(Reset, canRest);
      
          
      
          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");
              }
          }
      
          public MainWindowViewModel()
          {
          }
      
          private void Reset(object obj)
          {
              FilePath = @"C:\Temp";
          }
          private bool canRest() {
              return true;
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-01-01
        相关资源
        最近更新 更多