我正在使用Entity Framework。
根据这个:https://msdn.microsoft.com/en-us/data/gg193959.aspx
“在应用程序中没有其他代码或标记更改,a 现有的MVC应用程序将执行客户端验证“
绑定是正确的。
验证不会过滤到DataGrid,我在SaveChanges上得到一个例外。
模型
private string _Sponsor;
[Required]
[StringLength(20, MinimumLength = 3)]
public string Sponsor
{
get
{
return _Sponsor;
}
set
{
_Sponsor = value;
NotifyPropertyChanged("Sponsor");
}
}
MainWindow.xaml.cs
JobCollectionContext _context = new JobCollectionContext();
CollectionViewSource jobViewSource = ((CollectionViewSource)(this.FindResource("jobViewSource")));
_context.JobCollection.Load();
jobViewSource.Source = _context.JobCollection.Local;
MainWindow.xaml
<DataGridTextColumn Header="Sponsor" Binding="{Binding Sponsor, UpdateSourceTrigger=LostFocus, Mode=TwoWay, NotifyOnValidationError=true, ValidatesOnExceptions=true}" />
答案 0 :(得分:3)
因为这不是MVC
应用程序。您正在开发WPF
应用程序。
如果要在WPF
应用程序中显示错误,则需要实现接口INotifyDataErrorInfo
。
我有一个实现必要逻辑的基类。只需继承它并调用ValidateProperty("propertyName")
,它就会使用Attributes
来验证给定的属性。
您应该在所有应该验证的属性集中执行此操作,例如使用NotifyPropertyChanged()
进行更新以保持UI更新。
public abstract class NotifyDataErrorModel : INotifyDataErrorInfo
{
/// <summary>
/// Maps properties to their error sets
/// </summary>
protected Dictionary<string, HashSet<string>> errors;
/// <summary>
/// maps a property to a list of properties
/// the list of properties will get the ValidationErrors of the property
/// </summary>
protected NotifyDataErrorModel()
{
errors = new Dictionary<string, HashSet<string>>();
var properties = getProperties();
foreach (var property in properties)
{
errors.Add(property, new HashSet<string>());
}
}
private IEnumerable<string> getProperties()
{
var properties = this.GetType().GetProperties().Select(p => p.Name).ToList();
properties.Remove("HasErrors"); //remove the HasErrors property, because it is part of the interface INotifyDataErrorInfo and not of the actual model
return properties;
}
/// <summary>
///
/// </summary>
/// <param name="property">the property to validate</param>
public virtual void ValidateProperty(string property)
{
//clear the errors on the matched property
errors[property].Clear();
var type = this.GetType();
//the entity framework proxies sometimes dont inherit the attributes of the properties
//so if it is a entity framework proxy object, get the base class (which is the actual model class) instead
if (type.FullName.Contains("System.Data.Entity.DynamicProxies"))
{
type = type.BaseType;
}
var propertyInfo = type.GetProperty(property);
var propertyValue = propertyInfo.GetValue(this);
var validationAttributes = propertyInfo.GetCustomAttributes(true).OfType<ValidationAttribute>();
foreach (var validationAttribute in validationAttributes)
{
if (!validationAttribute.IsValid(propertyValue))
{
errors[property].Add(validationAttribute.FormatErrorMessage(string.Empty));
}
}
raiseErrorsChanged(property);
}
public virtual void ValidateAllProperties()
{
var properties = getProperties();
foreach (var property in properties) ValidateProperty(property);
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
public System.Collections.IEnumerable GetErrors(string propertyName)
{
//if the propertyname is not valid, return an empty IEnumerable
if (String.IsNullOrEmpty(propertyName)) return new List<string>();
return errors[propertyName];
}
public bool HasErrors
{
get { return errors.Any((propertyErrors) => propertyErrors.Value.Count > 0); }
}
private void raiseErrorsChanged(string property)
{
if (ErrorsChanged != null)
{
var eventArgs = new DataErrorsChangedEventArgs(property);
ErrorsChanged(this, eventArgs);
}
}
}