我有一个WPF
应用程序(.Net 3.5
),它使用IDataErrorInfo
ViewModel 上的 来验证输入。
效果很好,用户控件获得了正确的 UI 反馈。
问题是用户仍然可以更改所选元素,或保存此元素。
所以我的问题是:我怎么知道我所有的属性都是有效的?或者至少我所有显示的值都是有效的。IsActive
目标是在这个结果上绑定一些
我有一个WPF
应用程序(.Net 3.5
),它使用IDataErrorInfo
ViewModel 上的 来验证输入。
效果很好,用户控件获得了正确的 UI 反馈。
问题是用户仍然可以更改所选元素,或保存此元素。
所以我的问题是:我怎么知道我所有的属性都是有效的?或者至少我所有显示的值都是有效的。IsActive
目标是在这个结果上绑定一些
从您对您的实施的评论将您的实施IDataErrorInfo
更改为这种风格......
#region IDataErrorInfo Members
public string Error
{
get { return this[null] }
}
public string this[string columnName]
{
get
{
StringBuilder result = new StringBuilder();
if (string.IsNullOrEmpty(columnName) || columnName == "FirstName")
{
if (string.IsNullOrEmpty(FirstName))
result.Append("Please enter a First Name\n");
}
if (string.IsNullOrEmpty(columnName) || columnName == "LastName")
{
if (string.IsNullOrEmpty(LastName))
result.Append("Please enter a Last Name\n");
}
if (string.IsNullOrEmpty(columnName) || columnName == "Age")
{
if (Age < = 0 || Age >= 99)
result.Append("Please enter a valid age\n");
}
return (result.Length==0) ? null : result.Remove(result.Length-1,1).ToString();
}
}
#endregion
public bool IsValid {
get { return string.IsNullOrEmpty(this.Error); }
}
然后在您的财产更改事件中
if (e.PropertyName == "Error") {
OnPropertyChanged(this,new PropertyChangedEventArgs("IsValid"));
}
if (e.PropertyName != "Error" && e.PropertyName != "IsValid") {
OnPropertyChanged(this,new PropertyChangedEventArgs("Error"));
}
现在,我在我的模型上添加了这个方法。
public Boolean IsModelValid()
{
Boolean isValid = true;
PropertyInfo[] properties = GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo p in properties)
{
if (!p.CanWrite || !p.CanRead)
{
continue;
}
if (this[p.Name] != null)
{
isValid = false;
}
}
return isValid;
}
我将对象本身绑定在 PropertyChanged 事件上,
public MyClassName()
{
PropertyChanged += CheckModelValidity;
CheckModelValidity(null, null);
}
当它改变时,我调用这个方法,如果结果与我的实际公共成员不同,我更新它:
private void CheckModelValidity(object sender, PropertyChangedEventArgs e)
{
bool isModelValid = IsModelValid();
if(isModelValid!= IsValid)
{
IsValid = isModelValid;
}
}
然后我可以绑定 IsValid 属性。
不知道有没有更好的解决办法?
感谢 Bob Vale 的创意!我注意到我有几个模型并且代码非常重复。我创建了这个基类:
using System;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text;
namespace Core.Models
{
public abstract class ValidatableObject : IDataErrorInfo
{
public virtual bool IsValid() => this[null] == null;
[NotMapped]
public string? Error => this[null];
[NotMapped]
protected abstract (string, Func<string?>)[] Checks { get; }
public virtual string? this[string? name] => validate(name, Checks);
private static string? validate(string? name, params (string, Func<string?>)[] checks)
{
StringBuilder results = new();
foreach ((string val, Func<string?> check) in checks)
{
if (String.IsNullOrEmpty(name) || name == val)
{
string? result = check();
if (result != null)
results.AppendLine(result);
}
}
return results.Length == 0
? null
: results.ToString(0, results.Length - Environment.NewLine.Length);
}
}
}
这是用法:
private class Validatable : ValidatableObject
{
public string Email { get; set; }
public string Comment { get; set; }
protected override (string, Func<string?>)[] Checks => new (string, Func<string?>)[]
{
(nameof(Email), () => Validate.Email(Email)),
(nameof(Comment), () => Validate.LengthOfOptionalString(Comment)),
};
}