以下は、依存オブジェクト (およびそのすべての子オブジェクト) の検証エラーを追跡し、デリゲートを呼び出して変更を通知するヘルパー メソッドです。また、検証エラーのある子の削除も追跡します。
public static void AddErrorHandler(DependencyObject element, Action<bool> setHasValidationErrors)
{
var errors = new List<Tuple<object, ValidationError>>();
RoutedEventHandler sourceUnloaded = null;
sourceUnloaded = (sender, args) =>
{
if (sender is FrameworkElement)
((FrameworkElement) sender).Unloaded -= sourceUnloaded;
else
((FrameworkContentElement) sender).Unloaded -= sourceUnloaded;
foreach (var error in errors.Where(err => err.Item1 == sender).ToArray())
errors.Remove(error);
setHasValidationErrors(errors.Any());
};
EventHandler<ValidationErrorEventArgs> errorHandler = (_, args) =>
{
if (args.Action == ValidationErrorEventAction.Added)
{
errors.Add(new Tuple<object, ValidationError>(args.OriginalSource, args.Error));
if (args.OriginalSource is FrameworkElement)
((FrameworkElement)args.OriginalSource).Unloaded += sourceUnloaded;
else if (args.OriginalSource is FrameworkContentElement)
((FrameworkContentElement)args.OriginalSource).Unloaded += sourceUnloaded;
}
else
{
var error = errors
.FirstOrDefault(err => err.Item1 == args.OriginalSource && err.Item2 == args.Error);
if (error != null)
errors.Remove(error);
}
setHasValidationErrors(errors.Any());
};
System.Windows.Controls.Validation.AddErrorHandler(element, errorHandler);
}