Điều này thực sự phụ thuộc vào thực hiện lại IDataErrorInfo. Nếu bạn căn cứ nó xung quanh một từ điển thông báo lỗi bạn có thể kiểm soát khi xác thực chạy mà thêm vào danh sách đó. Bạn thường sẽ muốn làm điều đó từ setters tài sản của bạn (như bất cứ khi nào bạn gọi PropertyChange), đây gọi CheckValidationState:
public string this[string columnName]
{
get
{
return ValidateProperty(columnName);
}
}
public Dictionary<string, string> Errors { get; private set; }
protected void SetError(string propertyName, string errorMessage)
{
Debug.Assert(!String.IsNullOrEmpty(propertyName), "propertyName is null or empty.");
if (String.IsNullOrEmpty(propertyName))
return;
if (!String.IsNullOrEmpty(errorMessage))
{
if (Errors.ContainsKey(propertyName))
Errors[propertyName] = errorMessage;
else
Errors.Add(propertyName, errorMessage);
}
else if (Errors.ContainsKey(propertyName))
Errors.Remove(propertyName);
NotifyPropertyChanged("Errors");
NotifyPropertyChanged("Error");
NotifyPropertyChanged("Item[]");
}
protected virtual string ValidateProperty(string propertyName)
{
return Errors.ContainsKey(propertyName) ? Errors[propertyName] : null;
}
protected virtual bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
}
Bạn có thể sau đó cũng bao gồm một phương pháp mà xác nhận tất cả các thuộc tính của bạn (như trong một tiết kiệm):
protected bool Validate()
{
if (Errors.Count > 0)
return false;
bool result = true;
foreach (PropertyInfo propertyInfo in GetType().GetProperties())
{
if (!CheckValidationState(propertyInfo.Name, propertyInfo.GetValue(this, null)))
result = false;
NotifyPropertyChanged(propertyInfo.Name);
}
return result;
}
UPDATE:
tôi sẽ khuyên bạn nên đặt đoạn code trên vào một lớp cơ sở ViewModel để bạn có thể tái sử dụng nó. Sau đó bạn có thể tạo ra một lớp có nguồn gốc như thế này:
public class SampleViewModel : ViewModelBase
{
private string _firstName;
public SampleViewModel()
{
Save = new DelegateCommand<object>(SaveExecuted);
}
public DelegateCommand<object> Save { get; private set; }
public string FirstName
{
get { return _firstName; }
set
{
if (_firstName == value)
return;
CheckValidationState("FirstName", value);
_firstName = value;
NotifyPropertyChanged("FirstName");
}
}
public void SaveExecuted(object obj)
{
bool isValid = Validate();
MessageBox.Show(isValid ? "Saved" : "Validation Error. Save canceled"); // TODO: do something appropriate to your app here
}
protected override bool CheckValidationState<T>(string propertyName, T proposedValue)
{
// your validation logic here
if (propertyName == "FirstName")
{
if (String.IsNullOrEmpty(proposedValue as String))
{
SetError(propertyName, "First Name is required.");
return false;
}
else if (proposedValue.Equals("John"))
{
SetError(propertyName, "\"John\" is not an allowed name.");
return false;
}
else
{
SetError(propertyName, String.Empty); // clear the error
return true;
}
}
return true;
}
}
Trong trường hợp này tôi đang sử dụng một DelegateCommand để kích hoạt các hoạt động tiết kiệm nhưng nó có thể là bất cứ điều gì mà làm cho một lời gọi phương thức để thực hiện tiết kiệm. Thiết lập này cho phép trạng thái trống ban đầu hiển thị là hợp lệ trong giao diện người dùng nhưng thay đổi hoặc cuộc gọi để Lưu cập nhật trạng thái xác thực. Bạn cũng có thể nhận được tổng quát hơn và phức tạp hơn theo cách bạn thực sự thực hiện xác thực để nó không kết thúc bằng một phương pháp (ở đây có một số giả định về loại) nhưng điều này được đơn giản hóa để giúp dễ dàng bắt đầu với .
Nguồn
2010-01-22 22:29:49
Cảm ơn bạn đã trả lời John, bạn có thể mở rộng câu trả lời của mình một chút được không. Tôi đã cố gắng thực hiện những gì bạn đã thảo luận và bị mất một chút. Cảm ơn ... – Burt
Burt - Tôi đã cập nhật để thêm mã khác để cho biết cách một lớp có thể triển khai thực hiện điều này mà tôi hy vọng sẽ điền vào một số lỗ cho bạn. Điều đó có giúp bạn không? –
Cảm ơn John thực sự đánh giá cao nó, đã đi lên bầu cử bạn nhưng bằng cách nào đó quản lý để loại bỏ một phiếu bầu nó đã không cho phép tôi thêm nó một lần nữa. – Burt