Avalonia数据有效性验证与手动设置错误
示例代码:https://github.com/bodong1987/AvaloniaSamples/tree/main/AvaloniaDataValidation
官方文档:https://docs.avaloniaui.net/docs/data-binding/data-validation
Avalonia通过插件来实现数据校验,有三种方法。
1. 直接在属性的set中抛出异常。(个人不推荐这种方案)
2. 使用DataAnnotations特性(Attributes)(个人推荐这种方法)
3. 实现INotifyDataErrorInfo接口
下面是一个简单的数据校验的示例,主要使用了异常方案和DataAnnotations方案:
using ReactiveUI; using System; using System.ComponentModel.DataAnnotations; namespace AvaloniaDataValidation.ViewModels { public class MainWindowViewModel : ViewModelBase { string EmailCore = ""; [EmailAddress] public string Email { get => EmailCore; set => this.RaiseAndSetIfChanged(ref EmailCore, value); } public string[] CombItems => new string[] { "C", "C++", "C#", }; string ProgramLanguageCore = "C"; [LaungageValidation] public string ProgramLanguage { get => ProgramLanguageCore; set { // can't use this // if(value == "C#") // { // throw new ArgumentException($"{nameof(ProgramLanguage)} can not use C#"); // } this.RaiseAndSetIfChanged(ref ProgramLanguageCore, value); } } } internal class LaungageValidationAttribute : ValidationAttribute { protected override ValidationResult? IsValid(object? value, ValidationContext validationContext) { if(value is string lan) { if (lan == "C#") { return new ValidationResult($"[{validationContext.DisplayName}] can not be C#"); } } return ValidationResult.Success; } } }
除此之外,也可以手动设置错误,如:
private void OnShowError(object sender, RoutedEventArgs e) { if(!DataValidationErrors.GetHasErrors(textBox_Errors)) { DataValidationErrors.SetError(textBox_Errors, new ArgumentException("A custom exception error")); } else { DataValidationErrors.SetError(textBox_Errors, null); } }
这样就可以强制设置错误了。本质上底层也是通过调用这个接口来实现这个能力的。内部其实是设置的是DataValidationErrors.ErrorsProperty:
public static IEnumerable<object> GetErrors(Control control) { return control.GetValue(ErrorsProperty); } public static void SetErrors(Control control, IEnumerable<object> errors) { control.SetValue(ErrorsProperty, errors); } public static void SetError(Control control, Exception error) { SetErrors(control, UnpackException(error)); } public static void ClearErrors(Control control) { SetErrors(control, null); } public static bool GetHasErrors(Control control) { return control.GetValue(HasErrorsProperty); }