[英]Using INotifyDataErrorInfo with embedded UserControl in WPF (with Caliburn.Micro)
[英]Caliburn.Micro implementing INotifyDataErrorInfo
我正在嘗試找到一種優雅的解決方案,以利用Caliburn.Micro MVVM框架實現INotifiyDataErrorInfo
。
我想限制在每個需要實施驗證的VM中重復的代碼量。 我從編寫一個繼承Screen
並實現INotifiyDataErrorInfo
的類開始。 它可以正常工作,並且一切都很好,直到我需要在不是Screen
而是Conductor
的VM上進行驗證為止。
當然,我可以制作一個繼承Conductor
並實現INotifyDataErrorInfo
的類,但是這很煩人,因為我必須基本上自己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; }
}
...
}
這非常INotifyDataErrorInfo
,因為在VM中實現INotifyDataErrorInfo
非常簡單,但是我遇到的問題是觸發ErrorChanged
事件。 它必須由IValidator
的實現來觸發,因為他是知道錯誤何時已更改的人,當然他不能直接觸發。
我的一個想法是在IValidator
有一個事件,然后在VM中訂閱它,以便它可以觸發自己的事件,但是我發現它無濟於事地編寫了很多代碼。
有誰有更好的主意嗎?
謝謝
我為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
}
如果您讓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);
但是我想你已經回答了自己的問題了,沒有告訴我們;)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.