我试图找到一个优雅的解决方案,用INotifiyDataErrorInfo MVVM框架来实现Caliburn.Micro。
我希望限制每个需要实现验证的VM中重复的代码数量。我首先编写了一个继承Screen并实现INotifiyDataErrorInfo的类。它正确地工作,一切都很好,直到我需要验证一个VM,它不是一个Screen,而是一个Conductor。
当然,我可以创建一个继承Conductor并实现INotifyDataErrorInfo的类,但这是非常烦人的,因为我基本上必须创建自己的所有Caliburn.Micro“基类”。
一个解决方案是保留Screen基类并创建一个IValidator接口,然后将其插入到VM中,如下所示:
public interface IValidator<T> where T : INotifyDataErrorInfo
{
void Validates(T instance);
IEnumerable GetErrors(string propertyName);
bool HasErrors { get; }
void Validate();
void ValidateProperty<TValue>(TValue value, string propertyName = null);
void ValidateProperty<TValue, TProperty>(TValue value, Expression<Func<TProperty>> property);
}然后,它将以这种方式在VM中使用。
public class CreateCarViewModel : Conductor<CreateCarViewModel>.Collection.OneActive, INotifyDataErrorInfo
{
private readonly IValidator<CreateCarViewModel> validator;
public CreateExperimentViewModel(IValidator<CreateCarViewModel> validator)
{
this.DisplayName = "Select a car";
this.validator = validator;
this.validator.Validates(this);
}
[Required]
public string CarName
{
get
{
return this.carName;
}
set
{
if (this.carName != value)
{
this.carName = value;
this.validator.ValidateProperty(value, () => this.CarName);
this.NotifyOfPropertyChange(() => CarName);
}
}
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public System.Collections.IEnumerable GetErrors(string propertyName)
{
return this.validator.GetErrors(propertyName);
}
public bool HasErrors
{
get { return this.validator.HasErrors; }
}
...
}这非常好,因为在VM中实现INotifyDataErrorInfo非常简单,但我遇到的问题是触发ErrorChanged事件。它必须由IValidator的实现触发,因为他知道错误何时发生了变化,当然也不能直接触发。
我的一个想法是在IValidator中拥有一个事件,并在VM中订阅它,这样它就可以触发它自己的事件,但是我发现它使很多代码变得毫无意义。
有人有更好的主意吗?
谢谢
发布于 2014-10-21 16:52:39
如果您让IValidator公开与VM相同的事件,那么连线代码不会过多,例如:
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public void Validate()
{
if (ErrorsChanged != null)
ErrorsChanged(instance, new DataErrorsChangedEventArgs("someProperty"));
}在VM中:
validator.ErrorsChanged += (sender, args) => ErrorsChanged(sender, args);但我想你已经没有告诉我们就回答了你自己的问题;)
发布于 2015-01-28 21:18:54
我为CM编写了一个小插件,以支持流畅的构建器风格的验证。也许它能帮到你。您可以随意使用它:https://github.com/AIexandr/Caliburn.Micro.Validation用法示例:
public class PaymentEditorViewModel() : ValidatingScreen
{
public PaymentEditorViewModel()
{
AddValidationRule(() => PaymentSum).Condition(() => PaymentSum <= 0).Message("Please enter payment sum");
}
#region PaymentSum property
decimal _PaymentSum;
public decimal PaymentSum
{
get
{
return _PaymentSum;
}
set
{
_PaymentSum = value;
NotifyOfPropertyChange(() => PaymentSum);
}
}
#endregion
}https://stackoverflow.com/questions/23777395
复制相似问题