如何运行 IDataErrorInfo 验证代码,当我的 IValueConverter 引发异常时
本文关键字:IValueConverter 我的 异常 代码 何运行 运行 验证 IDataErrorInfo | 更新日期: 2023-09-27 18:36:24
我在 WPF 窗口中验证整数时遇到问题。 我的业务对象具有Age:int
属性。 我想验证该Age >= 5
. 我了解如何使用IDataErrorInfo
并将ValidatesOnDataErrors
设置为 true。 如果我输入一个数字,那行得通。 但是如果我输入一个空字符串或"abc"
,则不会调用验证代码。 这是一个问题,因为我有一个按钮,只有在验证代码成功时才希望启用该按钮。
根据我的输出窗口,问题是默认转换器在 ConvertBack
方法中抛出FormatException
。 这可以防止代码调用 IDataErrorInfo.this[string columnName]
方法。 (我目前正在使用默认的int
转换器)
我已经读过一些解决方案,但它们要么不起作用,要么看起来很笨拙:
-
使用 Nullable
。 这不会阻止异常。 - 使用字符串而不是 int。 这将起作用,但它不允许我利用内置的 WPF 功能。 感觉就像一个黑客。
-
我以为我可以使用自己的
IValueConverter
来拦截 ConvertBack 调用,但我需要向转换器授予对我的业务对象的访问权限,以便它可以设置某种IsValid:bool
属性。 我不知道如何为转换器提供对我的业务对象的引用。
当ConvertBack
引发异常(例如,用户输入空字符串)时,如何验证我的业务对象?
这是我的业务对象:
class DContext : INotifyPropertyChanged, IDataErrorInfo
{
public DContext()
{
this._submit = new Commands.btnSubmit(this);
}
private readonly ICommand _submit;
public ICommand Submit { get { return this._submit; } }
private int _age;
public int Age
{
get { return this._age; }
set
{
if (this._age != value)
{
this._age = value;
this.OnPropertyChanged();
}
}
}
private string _error;
public string Error
{
get { return this._error; }
}
public string this[string columnName]
{
get
{
this._error = null;
if (columnName == "Age" && this._age < 5)
this._error = "Age must be >= 5";
return this._error;
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged([System.Runtime.CompilerServices.CallerMemberNameAttribute]string propertyName = "")
{
if (this.PropertyChanged != null)
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
这是我的 WPF:
<StackPanel Orientation="Horizontal" Height="20" VerticalAlignment="Top">
<TextBlock Text="Age" />
<TextBox Width="100" Text="{Binding Age,ValidatesOnDataErrors=True}" />
<Button Content="Submit" Command="{Binding Submit}" />
</StackPanel>
有趣的是,我注意到ICommand.CanExecute
方法在IDataErrorInfo.this[string columnName]
方法之前被调用。 这意味着ICommand
正在使用尚未验证的值。 这意味着我将不得不复制我的错误检测代码。
我认为解决方案必须是#2或#3。 我倾向于#3,因为它不会给您的视图模型带来任何混乱。 让"ConvertBack"方法尝试解析输入,如果解析失败,则返回无效值(可能是 0 或 -1)。
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
string input = value as string;
int validNumber;
if (input != null && int.TryParse(input, out validNumber))
return validNumber;
else
return 0;
}
您的验证应该与此一起使用,没有其他更改。 我可以看到使用 #2 的唯一原因是,如果您想要不同的错误消息,例如"年龄字段是必需的"和"年龄字段必须是有效数字"。
这意味着 ICommand 正在使用尚未验证的值。这意味着我将不得不复制我的错误检测代码。
我不确定为什么这是必要的。 您不能在验证运行时引发"Command.CanExecuteChanged"吗? 如果没有,那么您可能需要考虑使用 INotifyDataErrorInfo
而不是 IDataErrorInfo
,因为它允许您引发"ErrorsChanged"事件来触发验证。