WPF DataGrid中IP输入TextBox自定义验证器及ValidationResult访问问题
解决DataGrid中TextBox验证后访问ValidationResult的问题
我来帮你搞定这个问题——在WPF DataGrid的TextBox绑定自定义验证器后,要访问ValidationResult其实有几种实用的方案,你可以根据自己的场景选最合适的:
1. 在ViewModel里跟踪验证状态(推荐MVVM模式)
既然已经用了绑定,最符合MVVM设计的方式就是让你的数据模型(或者ViewModel)暴露一个属性来存验证结果,这样你在代码里就能直接拿到它:
- 先给你的数据模型类(比如叫
IPAddressItem)加几个属性,用来存验证结果和状态:
public class IPAddressItem : INotifyPropertyChanged { private string _ipSrc; public string IPSrc { get => _ipSrc; set { _ipSrc = value; OnPropertyChanged(); // 手动触发验证(也可以让绑定自动触发,这里是主动验证的写法) ValidateIPAddress(); } } private ValidationResult _ipSrcValidationResult; public ValidationResult IPSrcValidationResult { get => _ipSrcValidationResult; set { _ipSrcValidationResult = value; OnPropertyChanged(); // 同步更新你已经在绑定的颜色状态 IPSrcValidationStatus = value.IsValid ? new ValidationStatus(Colors.Green) : new ValidationStatus(Colors.Red); } } public ValidationStatus IPSrcValidationStatus { get; set; } private void ValidateIPAddress() { var validator = new YourCustomIPValidator(); IPSrcValidationResult = validator.Validate(IPSrc, CultureInfo.CurrentCulture); } // 实现INotifyPropertyChanged的标准代码 public event PropertyChangedEventHandler PropertyChanged; protected void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
这样一来,不管是在ViewModel里做逻辑判断,还是在XAML里绑定相关状态,都能直接用IPSrcValidationResult属性拿到验证结果了。
2. 通过WPF的Validation静态类直接获取错误
如果你不想改数据模型,也可以在View的代码后台里,用Validation.GetErrors方法拿到指定TextBox的验证错误:
// 先拿到DataGrid里的那个TextBox实例,比如用VisualTreeHelper查找 TextBox ipTextBox = FindVisualChild<TextBox>(yourDataGridRow); var validationErrors = Validation.GetErrors(ipTextBox); if (validationErrors.Any()) { ValidationResult result = validationErrors.First(); // 这里就能访问结果的错误信息和是否有效了 string errorMsg = result.ErrorContent.ToString(); bool isIpValid = result.IsValid; } // 辅助方法:查找VisualTree里的子元素 private T FindVisualChild<T>(DependencyObject parent) where T : DependencyObject { for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++) { var child = VisualTreeHelper.GetChild(parent, i); if (child is T typedChild) return typedChild; var foundChild = FindVisualChild<T>(child); if (foundChild != null) return foundChild; } return null; }
不过这种方式更适合在代码后台临时处理,不太符合MVVM的分离原则,尽量少用在业务逻辑里。
3. 在自定义验证器里直接处理结果
如果你的验证结果不需要在ViewModel里复用,也可以在自定义验证器的Validate方法里直接处理,比如打日志或者触发其他UI操作:
public class YourCustomIPValidator : ValidationRule { public override ValidationResult Validate(object value, CultureInfo cultureInfo) { string ipAddress = value as string; if (string.IsNullOrWhiteSpace(ipAddress)) { var result = new ValidationResult(false, "IP地址不能为空"); // 在这里直接处理结果,比如通过事件通知其他组件 OnValidationResultReady(result); return result; } // IP格式验证逻辑 if (!System.Net.IPAddress.TryParse(ipAddress, out _)) { var result = new ValidationResult(false, "IP地址格式不正确"); OnValidationResultReady(result); return result; } return ValidationResult.ValidResult; } // 定义一个事件,用来通知验证结果 public event Action<ValidationResult> ValidationResultReady; private void OnValidationResultReady(ValidationResult result) { ValidationResultReady?.Invoke(result); } }
然后在View的代码后台订阅这个事件,就能拿到每次的验证结果了。
小提示
- 你用了
UpdateSourceTrigger="PropertyChanged",每次输入字符都会触发验证,记得确保你的验证逻辑足够轻量,别卡UI。 - 如果要获取整行的验证结果,可以用
Validation.GetErrors(yourDataGridRow)拿到整行的错误集合。
内容的提问来源于stack exchange,提问作者FBGenesy
相关产品推荐
相关产品推荐

