0

给出的是一个带有重置按钮和文本框的 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 更新当用户输入无效字符时,边框会变为红色,并且“重置”按钮不会更新 UI。

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

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

4

2 回答 2

2

简单的解决方案

您可以通过在设置值后直接通知您的 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()您尝试设置Filepathc:/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;
}

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

if (EqualityComparer<T>.Default.Equals(field, value)) return false;
于 2021-10-12T06:54:35.957 回答
0

由于缺少 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;
    }
}
于 2021-10-12T06:41:59.510 回答