我有一个名为Person的类,如下所示,使用Fluent验证进行验证:
注意 :我在Person类中实现了INotifyPropertyChanged,但为了简单起见,我没有在此处显示,因此我的代码看起来很简单。
public class Person : ObjectBase
{
public int PersonId {get; set;}
public string Name {get; set;}
public int Age {get; set;}
class PersonValidator : AbstractValidator<Person>
{
public PersonValidator()
{
RuleFor(x => x.Name).NotEmpty();
RuleFor(x => x.Age).GreaterThan(0);
}
}
}
现在在ViewModel中:
public Class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
NewPerson = new Person();
}
private Person _newPerson;
public Person NewPerson
{
get
{
return _newPerson;
}
set
{
if(_newPerson != value)
{
_newPerson = value;
OnPropertyChanged(() => NewPerson();
}
}
}
public string AgeString
{
get
{
return NewPerson.Age.ToString();
}
set
{
if(value == null)
{
NewParty.Age = 0;
}
else if(NewPerson.Age.ToString() != value)
{
int age = 0;
bool canParse = Int32.TryParse(value, out age);
if(canParse)
NewParty.Age = age;
else
NewParty.age = 0;
}
OnPropertyChanged(() => AgeString);
}
}
}
在视图中:
<Window ..........>
<Textbox Text = {Binding NewPerson.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true} />
<Textbox Text = {Binding AgeString, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true} />
</Window>
现在您可以在上面的XAML中看到,我的第二个文本框没有绑定到NewPerson.Age,而是绑定到AgeString。
现在有些人可能会问我为什么要这样做? 我这样做是因为如果我将我的文本框绑定到NewPerson.Age,那么当textBox被用户保持为空时我无法验证它。所以,我必须将此文本框绑定到字符串属性。
无论如何,我的文本框绑定到AgeString属性。当用户输入任何垃圾值时,它显示为零。太棒了。
回顾Person类及其验证。我已经验证了Age Proerty大于0.现在我想对AgeString属性做同样的事情。
所以,我的问题是如何将此验证错误从NewPerson.Age传递给AgeString属性????
更新
正如第一条评论中所建议的那样,我使用的是Value Converter而不是一个不同的属性。
这是我更新的ViewModel:
public Class MainWindowViewModel : ViewModelBase
{
public MainWindowViewModel()
{
NewPerson = new Person();
SetTo18Command = new RelayCommand(SetTo18());
}
public RelayCommand SetTo18Command {get;set;}
private Person _newPerson;
public Person NewPerson
{
get
{
return _newPerson;
}
set
{
if(_newPerson != value)
{
_newPerson = value;
OnPropertyChanged(() => NewPerson();
}
}
}
private void SetTo18()
{
NewPerson.Age = 18;
}
}
查看:
<Window ..........>
<Textbox Text = "{Binding NewPerson.Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true}" />
<Textbox Text = "{Binding NewPerson.Age, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=true}" />
<Button Command="{Binding SetTo18Command}" Content="Set to 18" />
</Window>
当我点击重置按钮时,它会将NewPerson的年龄设置为18。
这是我的ValueConverter:
public class StringToIntConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
return value.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
if (value == null || value == DependencyProperty.UnsetValue)
return 0;
int output = 0;
bool canParse = Int32.TryParse(value.ToString(), out output);
if (canParse)
return output;
else
return 0;
}
}
这很好用。但是有一个小错误。
当我在文本框中将人的年龄设置为0然后我点击SetTo18按钮时,文本框的值更改为18,但我仍然看到文本框周围出现错误的红色边框。
这是我的Validation Class,它实现了IDataErrorInfo:
public abstract class ObjectBase : IDataErrorInfo
{
public ObjectBase()
{
_Validator = GetValidator();
Validate();
}
protected bool _IsDirty = false;
protected IValidator _Validator = null;
protected IEnumerable<ValidationFailure> _ValidationErrors = null;
protected virtual IValidator GetValidator()
{
return null;
}
[NotNavigable]
public IEnumerable<ValidationFailure> ValidationErrors
{
get { return _ValidationErrors; }
set { }
}
public void Validate()
{
if (_Validator != null)
{
ValidationResult results = _Validator.Validate(this);
_ValidationErrors = results.Errors;
}
}
[NotNavigable]
public virtual bool IsValid
{
get
{
if (_ValidationErrors != null && _ValidationErrors.Count() > 0)
return false;
else
return true;
}
}
string IDataErrorInfo.Error
{
get { return string.Empty; }
}
string IDataErrorInfo.this[string columnName]
{
get
{
StringBuilder errors = new StringBuilder();
if (_ValidationErrors != null && _ValidationErrors.Count() > 0)
{
foreach (ValidationFailure validationError in _ValidationErrors)
{
if (validationError.PropertyName == columnName)
errors.AppendLine(validationError.ErrorMessage);
}
}
return errors.ToString();
}
}
}