Silverlight 如何为Datarow实现INotifyDataErrorInfo

Silverlight 如何为Datarow实现INotifyDataErrorInfo,silverlight,inotifydataerrorinfo,Silverlight,Inotifydataerrorinfo,我有一个datarow类,它实现了Dynamicobject和INotifyPropertyChanged以及INotifyDataErrorInfo 在这个类中还有一个名为'GridData'(datarows)的属性,该属性绑定到xaml以在网格中显示 我可以知道如何实现公共IEnumerable GetErrors(string propertyName) 正确,因为“GridData”属性可以有许多属性包 谢谢//这是您的行。。。或多或少 公共类GridData:DynamicObjec

我有一个datarow类,它实现了Dynamicobject和INotifyPropertyChanged以及INotifyDataErrorInfo

在这个类中还有一个名为
'GridData'(datarows)
的属性,该属性绑定到xaml以在网格中显示

我可以知道如何实现公共IEnumerable GetErrors(string propertyName)

正确,因为“GridData”属性可以有许多属性包

谢谢

//这是您的行。。。或多或少
公共类GridData:DynamicObject,INotifyDataErrorInfo
{
私有字典_propertyValues=新字典();
//此对象保存您的错误。
专用词典_errorscocontainer=新词典();
//当触发时,它会通知UI此对象的错误已更改。
公共事件事件处理程序错误更改;
//这会告诉UI有错误。
公共布尔错误
{ 
获取{返回此。\u errorscocontainer.Count>0;}
}
//这允许UI检索给定属性的所有错误
公共IEnumerable GetErrors(字符串propertyName)
{
返回此。\u错误容器[propertyName];
}
//这将为给定属性设置错误,并激发errors changed事件
受保护的void SetError(字符串propertyName、IEnumerable错误)
{
列出存在的错误;
if(this.\u errorsContainer.TryGetValue(propertyName,out existingErrors)!=true)
{
此._errorsContainer[propertyName]=errors.ToList();
}
其他的
{ 
existingErrors.AddRange(错误);
}
此.raiserRorschanged(propertyName);
}
//这将清除给定属性的错误
受保护的无效ClearErrors(字符串propertyName)
{
此.\u errorsContainer.Remove(propertyName);
此.raiserRorschanged(propertyName);
}
//这将引发此对象的错误已更改的事件。
受保护的无效RAISEERROSCHANGED(字符串属性名称)
{
如果(this.ErrorsChanged!=null)
{
this.ErrorsChanged(this,newdataerrorschangedeventargs(propertyName));
}
}
//继承自动态对象,返回给定属性的值。
公共重写bool TryGetMember(GetMemberBinder绑定器,输出对象结果)
{
//这将为您提供属性的名称。
字符串名称=binder.name;
返回_propertyValues.TryGetValue(名称,输出结果);
}
//继承自动态对象,在设置属性时调用。
public override bool TrySetMember(SetMemberBinder绑定器,对象值)
{
字符串propertyName=binder.Name;
列表验证错误=新建列表();
//将该值存储在propertyValues中,无论它是否错误。
_propertyValues[propertyName]=值;
//这是测试属性值的地方。
if(值/*用于测试它的任何条件*/)
{
//没有错误,因此请更新ui。
此.ClearErrors(propertyName);
}
其他的
{ 
//此值存在错误。
ValidationResult=新的ValidationResult(“值错误”);
//将错误添加到此属性的错误列表中
validationErrors.Add(结果);
//更新错误容器,告诉它此属性存在错误。
//触发错误更改事件,并更新ui。
this.SetError(propertyName、validationErrors);
}
返回true;
}
}

我使用公共类GridData:DynamicObject、INotifyDataErrorInfo,我可以知道在哪里进行验证吗?我需要在此处验证此[string index]的公共对象吗?实际上,公共事件事件处理程序ErrorsAnged始终为null,即使错误集合已更改。在设置属性值时,您将验证该值。如果该值不正确,则调用set error方法,传入字符串索引(属性名)和验证结果列表。此对象的绑定使用ErrorsAnged事件,当您设置错误时将触发该事件。谢谢,您还可以发布xaml行吗?这个动态对象是如何绑定的?我正在xaml绑定中使用一个转换器。我将整个对象(GridData)绑定到绑定路径,并使用值转换器获取所需的值(使用转换器的索引和参数),在这种情况下,绑定框架读取GridData属性,而不是GridData的单个属性。
//This is your row... more or less.
public class GridData : DynamicObject, INotifyDataErrorInfo
{
   private Dictionary<string, object> _propertyValues = new Dictionary<string, object>();

   //this object holds your errors.
   private Dictionary<string, List<ValidationResult>> _errorsContainer = new Dictionary<string, List<ValidationResult>>();

   //when this fires it notifies the UI the errors of this object have changed.
   public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;

   //This tells the UI there are errors.
   public bool HasErrors
   { 
      get { return this._errorsContainer.Count > 0; }
   }

   //this allows the UI to retrieve all errors for a given property
   public IEnumerable GetErrors(string propertyName)
   {
      return this._errorsContainer[propertyName];
   }

   //This sets the error for a given property and fires the errors changed event
   protected void SetError(string propertyName, IEnumerable<ValidationResult> errors)
   {
      List<ValidationResult> existingErrors;

      if(this._errorsContainer.TryGetValue(propertyName, out existingErrors) != true)
      {
         this._errorsContainer[propertyName] = errors.ToList();
      }
      else
      { 
         existingErrors.AddRange(errors);
      }

      this.RaiseErrorsChanged(propertyName);
   }

   //This clears the errors for a given property
   protected void ClearErrors(string propertyName)
   {
      this._errorsContainer.Remove(propertyName);
      this.RaiseErrorsChanged(propertyName);
   }

   //This raises the event that the errors of this object have changed.
   protected void RaiseErrorsChanged(string propertyName)
   {
      if(this.ErrorsChanged != null)
      {
         this.ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName));
      }
   }

   //inherited from dynamic object this returns the value for a given property.
   public override bool TryGetMember(GetMemberBinder binder, out object result)
   {
      //this gives you the name of the property.
      string name = binder.Name;

      return _propertyValues.TryGetValue(name, out result);
   }

   //inherited from dynamic object, this is called when a property is set.
   public override bool TrySetMember(SetMemberBinder binder, object value)
   {
      string propertyName = binder.Name;

      List<ValidationResult> validationErrors = new List<ValidationResult>();

      //store the value in the propertyValues regardless if it is erroneous.
      _propertyValues[propertyName] = value;

      //this is where you test the value of the property.
      if(value /* whatever condition you use to test it */)
      {
         //no errors so update the ui.
         this.ClearErrors(propertyName);
      }
      else
      { 
         //there was an error for this value.
         ValidationResult result = new ValidationResult("The value is wrong.");

         //add the error to the list of errors for this property
         validationErrors.Add(result);

         //update the error container telling it there are errors for this property.
         //fire the errors changed event, and update ui.
         this.SetError(propertyName, validationErrors);  
      }

      return true;
   }

}