我有一个名为“CustomerDataContract”的类,它具有三个属性:MobilePhone、OfficePhone 和 PrivatePhone。为了与客户取得联系,必须设置至少一个属性。
我创建了一个 Validator-Class 并添加了一个名为“CheckForAnyPhoneNumber”的自定义规则来检查是否至少提供了一个电话号码。这几乎解决了我的问题。我唯一的问题是,如果我清除例如 MobilePhone-Attribute 它会被评估并处于错误状态。如果我现在输入 OfficePhone 号码,MobilePhone-Attribute 不会被重新评估并保持错误模式。
知道如何正确解决这个问题吗?我也尝试创建一个 RuleSet 但没有成功。
这是(部分)CustomerDataContract:
public partial class CustomerDataContract
{
public CustomerDataContract Clone()
{
return (CustomerDataContract) MemberwiseClone();
}
public override ValidationResult SelfValidate()
{
return ValidationHelper.Validate<CustomerDataContractValidator, CustomerDataContract>(this);
}
}
所有 DataContract 的基类:
[Serializable]
public abstract class BDataModel : IDataErrorInfo, INotifyPropertyChanged
{
[field: NonSerialized]
private ValidationResult _currentState = new ValidationResult();
public ValidationResult CurrentValidationState
{
get { return _currentState; }
set
{
_currentState = value;
OnPropertyChanged("CurrentValidationState");
OnPropertyChanged("IsValid");
OnPropertyChanged("Error");
}
}
#region INotifyPropertyChanged
[field: NonSerialized]
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(params string[] propertyName)
{
propertyName.ToList().ForEach(x =>
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(x));
});
}
#endregion
public virtual ValidationResult SelfValidate()
{
return new ValidationResult();
}
public bool IsValid
{
get
{
if (CurrentValidationState == null)
CurrentValidationState = SelfValidate();
return CurrentValidationState.IsValid;
}
}
#region IDataErrorInfo
public string Error
{
get { return ValidationHelper.GetError(CurrentValidationState); }
}
public string this[string columnName]
{
get
{
CurrentValidationState = SelfValidate();
if (_currentState == null) return string.Empty;
var columnResults = _currentState.Errors.FirstOrDefault(x => string.Compare(x.PropertyName, columnName, true) == 0);
return columnResults != null ? columnResults.ErrorMessage : string.Empty;
}
}
#endregion
}
这是验证器类:
public class CustomerDataContractValidator : AbstractValidator<CustomerDataContract>
{
private readonly ILanguageManager _languageManager = LanguageManager.Instance;
public CustomerDataContractValidator()
{
RuleFor(val => val.Lastname).NotEmpty().WithMessage(_languageManager.LanguageData["Global.Validation.ProvideLastname"]);
RuleFor(val => val.Firstname).NotEmpty().WithMessage(_languageManager.LanguageData["Global.Validation.ProvideFirstname"]);
RuleFor(val => val.Active).NotEmpty().WithMessage(_languageManager.LanguageData["Global.Validation.ProvideActive"]);
RuleFor(val => val.Gender).NotEmpty().WithMessage(_languageManager.LanguageData["Global.Validation.ProvideGender"]);
RuleFor(val => val.Mail).EmailAddress().When(val => !String.IsNullOrEmpty(val.Mail)).WithMessage(_languageManager.LanguageData["Global.Validation.ProvideValidEmail"]);
// At least one phone number has to be filled in order to contact the customer
RuleFor(val => val.MobilePhone).Must(CheckForAnyPhoneNumber).WithMessage(_languageManager.LanguageData["Global.Validation.ProvideAnyPhone"]);
RuleFor(val => val.OfficePhone).Must(CheckForAnyPhoneNumber).WithMessage(_languageManager.LanguageData["Global.Validation.ProvideAnyPhone"]);
RuleFor(val => val.PrivatePhone).Must(CheckForAnyPhoneNumber).WithMessage(_languageManager.LanguageData["Global.Validation.ProvideAnyPhone"]);
}
/// <summary>
/// Checks wheter or not any phone number has been provided
/// </summary>
/// <param name="customer">The customer</param>
/// <param name="phoneNumber">The phone number</param>
/// <returns></returns>
private static bool CheckForAnyPhoneNumber(CustomerDataContract customer, string phoneNumber)
{
return (!String.IsNullOrEmpty(customer.MobilePhone) || !String.IsNullOrEmpty(customer.OfficePhone) || !String.IsNullOrEmpty(customer.PrivatePhone));
}
}
和验证助手:
public class ValidationHelper
{
public static ValidationResult Validate<T, K>(K entity)
where T : IValidator<K>, new()
where K : class
{
IValidator<K> validator = new T();
return validator.Validate(entity);
}
public static string GetError(ValidationResult result)
{
var errorMessage = "";
if (result != null)
{
var failure = result.Errors.FirstOrDefault();
if(failure != null)
{
errorMessage = failure.ErrorMessage;
}
}
return errorMessage;
}
}
视图模型:
public class CustomerViewModel : BMovingSelectionViewModel, IEventListener, ICustomerViewModel
{
private CustomerDataContract _customer;
public CustomerDataContract Customer
{
get
{
return _customer;
}
set
{
if (_customer != value)
{
_customer = value;
OnPropertyChanged(() => Customer);
}
}
}
}
和观点:
<TextBlock Text="{MarkupExtensions:LanguageManager Global.Person.PhoneOffice}" Grid.Row="3" Grid.Column="0" VerticalAlignment="Center" />
<TextBox Grid.Row="3" Grid.Column="1" Text="{Validation:ValidationBinding Path=Customer.OfficePhone}" HorizontalContentAlignment="Stretch" />
<TextBlock Text="{MarkupExtensions:LanguageManager Global.Person.PhonePrivate}" Grid.Row="4" Grid.Column="0" VerticalAlignment="Center" />
<TextBox Grid.Row="4" Grid.Column="1" Text="{Validation:ValidationBinding Path=Customer.PrivatePhone}" />
<TextBlock Text="{MarkupExtensions:LanguageManager Global.Person.PhoneMobile}" Grid.Row="5" Grid.Column="0" VerticalAlignment="Center" />
<TextBox Grid.Row="5" Grid.Column="1" Text="{Validation:ValidationBinding Path=Customer.MobilePhone}" />