You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET MAUI中ObservableValidator调用GetErrors()触发异常

.NET MAUI ObservableValidator 验证异常解决方案

问题根源

异常触发点在k.MemberNames.First(),原因是自定义GreaterThanAttribute返回错误时,未指定关联的属性名,导致MemberNames为空集合,调用First()直接抛出"Sequence has no Elements"异常;同时索引器逻辑未处理空MemberNames的边界情况。

修复步骤

1. 修正自定义验证属性的错误返回逻辑

在GreaterThanAttribute中,返回错误时必须指定当前验证的属性名到MemberNames,同时增加空值判断避免额外报错:

public sealed class GreaterThanAttribute : ValidationAttribute
{
    public GreaterThanAttribute(string propertyName)
    {
        PropertyName = propertyName;
    }

    public string PropertyName { get; }

    protected override ValidationResult IsValid(object value, ValidationContext validationContext)
    {
        object instance = validationContext.ObjectInstance;
        var otherProperty = instance.GetType().GetProperty(PropertyName);
        
        // 检查对比属性是否存在
        if (otherProperty == null)
        {
            return new ValidationResult($"Property {PropertyName} not found", new[] { validationContext.MemberName });
        }
        
        object otherValue = otherProperty.GetValue(instance);

        // 处理空值,避免强制转换IComparable报错
        if (value == null || otherValue == null)
        {
            return new ValidationResult("Value cannot be null", new[] { validationContext.MemberName });
        }

        if (((IComparable)value).CompareTo(otherValue) > 0)
        {
            return ValidationResult.Success;
        }

        // 指定当前验证的属性名到MemberNames
        return new ValidationResult("out of specification", new[] { validationContext.MemberName });
    }
}

2. 修复索引器的错误处理逻辑

在获取错误字典时,先过滤掉无MemberNames的错误,避免调用First()报错:

[IndexerName("Item")]
public ValidationStatus this[string propertyName]
{
    get
    {
        var errors = this.GetErrors()
                         .Where(error => error.MemberNames.Any()) // 过滤无效错误项
                         .ToDictionary(error => error.MemberNames.First(), error => error.ErrorMessage) 
                     ?? new Dictionary<string, string?>();

        var hasErrors = errors.TryGetValue(propertyName, out var error);
        return new ValidationStatus(hasErrors, error ?? string.Empty);
    }
}

3. 优化ViewModel属性设置逻辑

ObservableValidator的SetProperty方法已内置验证触发逻辑,无需手动调用ClearErrors和ValidateAllProperties,简化代码:

[GreaterThan(nameof(StaticPressSpec))]
public double? StaticPressResult
{
    get => this.staticPressResult;
    set
    {
        if (SetProperty(ref this.staticPressResult, value, true))
        {
            OnPropertyChanged("Item[StaticPressResult]");
        }
    }
}

额外注意事项

  • 确保StaticPressSpec有有效值:若该属性未初始化,验证时会触发空值错误,建议设置默认值或加入必填验证。
  • 保留XAML绑定逻辑不变:原有的[StaticPressResult].HasError绑定可正常工作。

内容的提问来源于stack exchange,提问作者scott

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.30 02:18:16