On ValidatesOnExceptions UI 未更新
On ValidatesOnExceptions UI is not updating
给出的是一个 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 进行调试,看起来 VM 正在重置。但不是 UI。
怎么了?
工作演示:https://github.com/LwServices/WpfValidationDemo/tree/master/ValidationWpf
由于缺少 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;
}
}
简单的解决方案
设置值后直接通知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;
}
因此,正如开头所建议的,简单的解决方案是直接通知您的 UI 或 从 SetProperty
方法中删除检查行
if (EqualityComparer<T>.Default.Equals(field, value)) return false;
给出的是一个 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 进行调试,看起来 VM 正在重置。但不是 UI。 怎么了?
工作演示:https://github.com/LwServices/WpfValidationDemo/tree/master/ValidationWpf
由于缺少 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;
}
}
简单的解决方案
设置值后直接通知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;
}
因此,正如开头所建议的,简单的解决方案是直接通知您的 UI 或 从 SetProperty
方法中删除检查行
if (EqualityComparer<T>.Default.Equals(field, value)) return false;