编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Avalonia低入侵数据验证实现(landsat数据)

wxchong 2024-07-22 23:01:57 开源技术 20 ℃ 0 评论

1.概要

目前在.NET8 Avalonia 11.0.10版本中有三种常见的数据验证方式:

  1. IDataErrorInfo:这是一种较旧的数据验证方式,主要用于WPF和WinForms。在这种方法中,模型需要实现IDataErrorInfo接口,该接口包含一个索引器和一个Error属性。索引器用于获取特定属性的错误消息,Error属性用于获取对象级别的错误消息。

  2. INotifyDataErrorInfo:这是一种更现代的数据验证方式,它允许异步验证并能提供多个错误消息。在这种方法中,模型需要实现INotifyDataErrorInfo接口,该接口包含一个ErrorsChanged事件和两个方法:GetErrors和HasErrors。GetErrors方法用于获取特定属性的错误消息,HasErrors属性用于确定对象是否有任何错误。

  3. 还有一种通过FluentValidation库进行数据验证的方式。

    FluentValidation是一个流行的.NET库,用于构建强大、可维护的验证规则。它使用流畅的API创建验证规则,支持复杂的验证场景,并可以很好地与Avalonia一起工作。

    使用FluentValidation,您可以在单独的验证类中定义规则,这样可以使模型类保持简洁。

在Avalonia中,最佳实践是使用INotifyDataErrorInfo接口进行数据验证。

2.详细内容

在以上的三种验证中我选择的是INotifyDataErrorInfo来实现,看到的一些示例实现的比较麻烦或者不够简洁我做了一些改进。

ValidateBindbleBase

因为INotifyDataErrorInfo需要在每个ViewModel或Model中进行数据验证,所以我将BindableBase和INotifyDataErrorInfo进行封装。这样继承了之后就不需要每次都编写相同的逻辑。

public class ValidateBindbleBase : BindableBase, INotifyDataErrorInfo
{
private readonly Dictionary<string, ICollection<string>> _validationErrors = new Dictionary<string, ICollection<string>>();

public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

public bool HasErrors => _validationErrors.Count > 0;

public IEnumerable GetErrors(string propertyName)
{
//If is not returned, there will be two identical exception prompts on the view
return ;
}

protected void ValidateProperty<T>(string propertyName, T value)
{
if (value == ) return;

var context = new ValidationContext(this) { MemberName = propertyName };
var validationResults = new List<ValidationResult>();

Validator.TryValidateProperty(value, context, validationResults);

if (_validationErrors.ContainsKey(propertyName))
{
_validationErrors.Remove(propertyName);
}

HandleValidationResults(propertyName, validationResults);
}

private void HandleValidationResults(string propertyName, ICollection<ValidationResult> validationResults)
{
if (validationResults.Any())
{
_validationErrors.Add(propertyName, new List<string>());
foreach (var validationResult in validationResults)
{
_validationErrors[propertyName].Add(validationResult?.ErrorMessage);
}

ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
}
}

ViewModel

这里在ViewModel层做了一个简单的示例,ViewModel继承ValidateBindbleBase之后即获得了数据验证和数据通知的能力。再通过系统或自定义的验证特性进行附加,这样就可以复用验证规则避免出现大量的if else。

public class ViewModel : ValidateBindbleBase
{
private string _packetName;

[MinLength(2)]
[StringValidator]
public string PacketName
{
get => _packetName;
set
{
if (SetProperty(ref _packetName, value))
ValidateProperty(nameof(PacketName), value);
}
}
}

Validation

如果系统的验证特性不能满足需要,那么我们可以通过自定义特性继承ValidationAttribute,通过重写IsValid、FormatErrorMessage来实现自定义验证规则和验证错误提示。

public partial class StringValidator : ValidationAttribute
{
public override string FormatErrorMessage(string name)
{
return "The field is invaild!";
}

public override bool IsValid(object? value)
{
try
{
return StringRegex().IsMatch(value?.ToString());
}
catch
{
return false;
}
}

[GeneratedRegex(@"^[a-zA-Z0-9_\-\.\u4e00-\u9fa5]+$")]
private static partial Regex StringRegex();
}

View

在view层正常绑定即可。

<TextBox
Grid.Row="2"
Grid.Column="1"
Margin="5"
Text="{Binding CurrnetConfig.PacketName}" />

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表