在ValidatesOnExceptions UI没有更新



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

  • 将设置路径重置为默认值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(@"[ws\.:-!~]");
    if (r.Matches(value).Count == value.Length)
    {
    SetProperty(ref _filePath, value);
    return;
    }
    throw new ArgumentException("Not an valid windows path");
    }
    }
    

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

我试着用Snoop调试,它看起来像VM正在重置。但不是UI。怎么了?

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

简单解决方案

你可以通过在设置值

后直接通知UI来解决这个问题
private void Reset()
{
FilePath = @"C:Temp";
OnPropertyChanged(nameof(FilePath));
}

原因的问题当Filepath不匹配您的Regex时,您只需在不修改_filePath的值的情况下引发异常,并且它将始终是有效路径

public string FilePath
{
get => _filePath;
set
{
var r = new Regex(@"[ws\.:-!~]");
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;
}
如开头所建议的,简单的解决方案是直接通知UI删除SetProperty方法中的检查行
if (EqualityComparer<T>.Default.Equals(field, value)) return false;

由于缺少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(@"[ws\.:-!~]");
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;
}
}

最新更新