我在WPF窗口中对整数进行验证时遇到问题。我的业务对象具有Age:int
属性。我想验证Age >= 5
。我看到如何使用IDataErrorInfo
并将ValidatesOnDataErrors
设置为true来执行此操作。如果我输入一个数字,这是有效的。但是如果我输入一个空字符串或"abc"
,验证码就不会被调用。这是一个问题,因为我有一个按钮,只有在验证代码成功时我才能启用它。
根据我的输出窗口,问题是默认转换器在FormatException
方法中抛出ConvertBack
。这可以防止代码调用IDataErrorInfo.this[string columnName]
方法。 (我目前正在使用默认的int
转换器)
我已经阅读过有关这方面的几个解决方案,但他们要么不工作,要么看起来很蠢:
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
正在使用尚未验证的值。这意味着我必须复制我的错误检测代码。
答案 0 :(得分:1)
我认为解决方案必须是#2或#3。我会倾向于#3,因为它不会在视图模型中引入任何混乱。拥有&#34; ConvertBack&#34;方法尝试解析输入,并在解析失败时返回无效值(可能为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的唯一原因是,如果您想要不同的错误消息,例如&#34;年龄字段是必需的&#34;和&#34;年龄字段必须是有效数字&#34;。
这意味着ICommand正在使用尚未验证的值。这意味着我必须复制我的错误检测代码。
我不确定为什么这是必要的。你不能只提出'#34; Command.CanExecuteChanged&#34;验证运行时?如果没有,那么您可能需要考虑使用INotifyDataErrorInfo
代替IDataErrorInfo
,因为它允许您引发&#34; ErrorsChanged&#34;触发验证的事件。