假设我的ViewModel
类中有这个(注意OnSubmit
函数(
public class MyViewModel : ViewModelBase{
private string? _SomeName;
public string? SomeName{
get => _SomeName;
set {
Validate(nameof(SomeName)); //Validate data on changes
SetProperty(ref _SomeName, value);
}
}
//Call this function to Validate the input data
private void Validate(string propertyName){
ClearError(propertyName);
switch(propertyName){
case nameof(SomeName):
if (string.IsNullOrWhiteSpace(_SomeName))
AddError(nameof(SomeName), "Name cannot be empty.");
break;
...
//other validation for propeties here if present
}
}
private ObservableCollection<TransactionItem>? _Transactions;
public ObservableCollection<TransactionItem>? Transactions{
get => _CodeItemDisbursement;
set {
SetProperty(ref _Transactions, value);
}
}
//ICommand Add new item to ObservableCollection
private readonly ButtonCommand _AddItem;
public ICommand AddItem => _AddItem;
private void OnAddItem(object commandParamater){
_Transactions.Add(new TransactionItem(){
... //add the data here...
});
}
//ICommand Form Submission
private readonly ButtonCommand _Submit;
public ICommand Submit => _Submit;
private void OnSubmit(object commandParamater){ //Validate all data before processing it.
//Validate all input is correct before we proceed.
Validate(nameof(SomeName));
// How do I call here, the `Validate()` function
// of each item in my `ObservableCollection<TransactionItem>`
// and check if `HasErrors` property has some value?
if(HasErrors) return; //There are errors, do not proceed.
//If no errors, then do process the data here...
}
//ViewModel Constructor
public MyViewModel() {
_Submit = new ButtonCommand(OnSubmit);
_AddItem = new ButtonCommand(OnAddItem);
}
}
正如您所看到的,我有一个对象为TransactionItem
的ObservableCollection
,这是TransactionItem
类。
public class TransactionItem : ViewModelBase{
public int ID { get; set; }
public string? Description { get; set; }
public string? OtherDetails { get; set; }
private string? _TransactionName;
public string? TransactionName {
get => _TransactionName;
set {
Validate(nameof(TransactionName)); //Validate data on changes
SetProperty(ref _TransactionName, value);
}
}
private decimal _Amount;
public decimal Amount {
get => _Amount;
set {
Validate(nameof(Amount)); //Validate data on changes
SetProperty(ref _Amount, value);
}
}
//Call this function to Validate the input data
private void Validate(string propertyName){
ClearError(propertyName);
switch(propertyName){
case nameof(TransactionName):
if (string.IsNullOrWhiteSpace(_TransactionName))
AddError(nameof(TransactionName), "Name of transaction cannot be empty.");
break;
case nameof(Amount):
if (string.IsNullOrWhiteSpace(_Amount.ToString()) || _Amount < 1)
AddError(nameof(Amount), "Please input a valid amount");
break;
}
}
}
我还有一个实现INotifyPropertyChanged
和INotifyDataErrorInfo
的类ViewModelBase
。
public abstract class ViewModelBase : INotifyPropertyChanged, INotifyDataErrorInfo{
#region INotifyPropertyChanged
public event PropertyChangedEventHandler? PropertyChanged;
protected void OnPropertyChanged([CallerMemberName] string? propertyName = null)
=> PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null){
if (EqualityComparer<T>.Default.Equals(member, value)) return false;
member = value;
OnPropertyChanged(propertyName);
return true;
}
#endregion
#region INotifyDataErrorInfo | Error Handling
private readonly Dictionary<string, string> _propertyErrors = new();
public bool HasErrors => _propertyErrors.Any();
public event EventHandler<DataErrorsChangedEventArgs>? ErrorsChanged;
public void ClearError(string? propertyName){
if (propertyName!=null && _propertyErrors.Remove(propertyName)) OnErrorsChanged(propertyName);
}
public void AddError(string propertyName, string errorMessage){
if (!_propertyErrors.ContainsKey(propertyName)) {
_propertyErrors.Add(propertyName, errorMessage);
}else{
_propertyErrors[propertyName] = errorMessage;
}
if (propertyName != null) OnErrorsChanged(propertyName);
}
private void OnErrorsChanged(string propertyName){
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
}
public IEnumerable GetErrors(string? propertyName){
if (string.IsNullOrEmpty(propertyName))
yield break;
if (_propertyErrors.TryGetValue(propertyName, out string? existingError))
yield return existingError;
}
#endregion
}
这里发生的事情是,当ViewModel
类触发OnSubmit
函数时,我想调用Validate()
函数来检查是否每个所需的属性都有正确的输入。然后,如果我的ViewModelBase
中的HasErrors
属性有值,则不要继续处理数据。
问题出在我的ObservableCollection<TransactionItem>
中。我还想调用对象TransactionItem
中的Validate()
函数来验证每个项目的TransactionName
和Amount
,如果HasErrors
有值,则不继续。但我迷路了,我不知道下一步该怎么办。
您可以在TransactionItem
中创建一个公共函数来触发Validate()
并返回HasErrors
的值,然后在OnSubmit()
中运行一个循环,并在ObservableCollection<TransactionItem>
的每个项中调用该函数。如果其中任何一个返回true,则不要继续。
例如,在TransactionItem
中创建一个公共函数
public bool ContainsError(){
Validate(nameof(TransactionName)); //Validate data on changes
Validate(nameof(Amount)); //Validate data on changes
return HasErrors;
}
然后在ViewModel
类中,在OnSubmit()
函数中执行此
private void OnSubmit(object commandParamater){
Validate(nameof(SomeName)); //First, validate your SomeName or other propeties.
bool ContainsError = false;
foreach(TransactionItem item in _Transactions){
ContainsError = item.ContainsError();
}
if(HasErrors || ContainsError) return; //There are errors, do not proceed.
//If no errors, then do process the data here...
}
应该可以。