【Avalonia】处理数据绑定中的 InvalidCastException 异常
【Avalonia】处理数据绑定中的 InvalidCastException 异常
绑定数字类型更适合使用 NumericUpDown 控件
在 Avalonia 日常开发中,TextBox 绑定到 int 类型属性是十分常见的情况,但是一旦输入了无效数字,界面上马上就会显示错误消息: System.InvalidCastException: Could not convert '' (System.String) to System.Int32.。这种错误消息完全是不合理的,没有本地化不说,也不该展示完整的类型。
我们知道,Avalonia 的异常信息是存储在 DataValidationErrors.Errors 属性中的,那么解决这个问题的办法大概率也在这里,观察源码可以发现有一个 ErrorConverterProperty, 这就是解决这个问题的关键。
考虑如下界面:
1
2
3
<StackPanel>
<TextBox Name="tb1" Text="{Binding IntValue}"/>
</StackPanel>
在xaml.cs 文件中编写如下代码:
1
2
3
4
5
6
this.tb1.SetValue(DataValidationErrors.ErrorConverterProperty, o =>
{
if (o is InvalidCastException)
return "无效输入";
return o;
});
运行可以发现异常消息已经变成了 无效输入。
封装一下
为每一个TextBox 单独编写显然是十分低效的做法,我们可以创建一个静态属性,然后通过 Style 为所有控件开启添加这个补丁。
1
2
3
4
<Style Selector=":is(Control)">
<Setter Property="DataValidationErrors.ErrorConverter"
Value="{x:Static ve:DataValidation.ErrorConverter}" />
</Style>
1
2
3
4
5
6
7
8
9
public class DataValidation
{
public static Func<object, object> ErrorConverter { get; } = o =>
{
if (o is InvalidCastException)
return "无效输入";
return o;
};
}
只显示无效输入还是过于粗暴了,可以为多种类型定义不同的转换器,并按需使用。
如果需要更强大的功能,这种单纯的转换就不够了,可以通过封装Behavior实现更多功能,这已经超出本文范围,这里不做描述。
走过的弯路
没仔细看定义的时候是这么写的:
1
2
3
4
5
6
7
8
9
DataValidationErrors.ErrorsProperty.Changed
.Subscribe(p =>
{
var arr = p.NewValue.GetValueOrDefault<object[]>();
if (arr != null && arr.Length > 0 && arr[0] is InvalidCastException)
{
arr[0] = "无效输入";
}
});
你还别说,在测试工程内真的可以运行,而且这种方法可以获取控件,比单纯的 Converter 强多了,唯一的问题是,看起来过于野路子,万一开发组把内部类型改成一个只读列表,这种方法就炸了。
但好歹也花了我几分钟时间,记一下吧,万一用到了呢。
本文由作者按照 CC BY 4.0 进行授权