150 lines
6.2 KiB
C#
150 lines
6.2 KiB
C#
// Copyright (c) 2017 schick Informatik
|
|
// Description: Validation / Highlighting helper class
|
|
//
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using System.Windows;
|
|
using System.Windows.Data;
|
|
using System.Windows.Markup.Primitives;
|
|
using bsmd.database;
|
|
|
|
namespace ENI2.Util
|
|
{
|
|
class ValidationContext
|
|
{
|
|
private BindingExpression _bindingExpression;
|
|
private UIElement _uiElement;
|
|
|
|
public ValidationContext(BindingExpression bindingExpression, UIElement anUIElement)
|
|
{
|
|
_bindingExpression = bindingExpression;
|
|
_uiElement = anUIElement;
|
|
}
|
|
|
|
#region Properties
|
|
|
|
public BindingExpression BindingExpression { get { return this._bindingExpression; } }
|
|
|
|
public UIElement UIElement { get { return this._uiElement; } }
|
|
|
|
#endregion
|
|
|
|
#region static creation
|
|
|
|
/// <summary>
|
|
/// Rekursive Funktion mit Reflection
|
|
/// </summary>
|
|
/// <param name="boundType"></param>
|
|
/// <param name="boundPropertyName"></param>
|
|
/// <param name="root"></param>
|
|
/// <returns></returns>
|
|
private static ValidationContext GetBindingForProperty(Type boundType, string boundPropertyName, FrameworkElement root)
|
|
{
|
|
foreach (FrameworkElement element in LogicalTreeHelper.GetChildren(root).OfType<FrameworkElement>())
|
|
{
|
|
FieldInfo[] properties = element.GetType().GetFields(BindingFlags.Public | BindingFlags.GetProperty | BindingFlags.FlattenHierarchy); // | BindingFlags.Static
|
|
foreach (FieldInfo field in properties)
|
|
{
|
|
if (field.FieldType == typeof(DependencyProperty))
|
|
{
|
|
DependencyProperty dp = (DependencyProperty)field.GetValue(null);
|
|
if (BindingOperations.IsDataBound(element, dp))
|
|
{
|
|
BindingExpression bindingExpression = BindingOperations.GetBindingExpression(element, dp);
|
|
if (boundType == bindingExpression.DataItem.GetType())
|
|
{
|
|
if (boundPropertyName == bindingExpression.ParentBinding.Path.Path)
|
|
{
|
|
return new ValidationContext(bindingExpression, element as UIElement);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Not found so check all child elements
|
|
ValidationContext bindingContext = GetBindingForProperty(boundType, boundPropertyName, element);
|
|
if (bindingContext != null) return bindingContext;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// Gets all dependency objects which has binding to specific property
|
|
/// </summary>
|
|
/// <param name="dependencyObject"></param>
|
|
/// <param name="propertyName"></param>
|
|
/// <returns></returns>
|
|
public static IList<DependencyObject> GetDependencyObjectsWithBindingToProperty(DependencyObject dependencyObject, string propertyName)
|
|
{
|
|
var list = new List<DependencyObject>();
|
|
ValidationContext.GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, dependencyObject, list);
|
|
|
|
return list;
|
|
}
|
|
|
|
/// <summary>
|
|
///
|
|
/// </summary>
|
|
/// <param name="propertyName"></param>
|
|
/// <param name="dependencyObject"></param>
|
|
/// <param name="sources"></param>
|
|
/// <remarks>
|
|
/// Based on ASanch answer on http://stackoverflow.com/questions/3959421/wpf-find-control-that-binds-to-specific-property
|
|
/// </remarks>>
|
|
private static void GetDependencyObjectsWithBindingToPropertyRecursive(string propertyName, DependencyObject dependencyObject,
|
|
ICollection<DependencyObject> sources)
|
|
{
|
|
var dependencyProperties = new List<DependencyProperty>();
|
|
if ((dependencyObject == null) || (propertyName.IsNullOrEmpty())) return; // sanity
|
|
|
|
dependencyProperties.AddRange(MarkupWriter.GetMarkupObjectFor(dependencyObject).Properties.Where(x => x.DependencyProperty != null).Select(x => x.DependencyProperty).ToList());
|
|
dependencyProperties.AddRange(MarkupWriter.GetMarkupObjectFor(dependencyObject).Properties.Where(x => x.IsAttached && x.DependencyProperty != null).Select(x => x.DependencyProperty).ToList());
|
|
|
|
var bindings = dependencyProperties.Select(x => BindingOperations.GetBindingBase(dependencyObject, x)).Where(x => x != null).ToList();
|
|
|
|
Predicate<Binding> condition = binding => binding != null && binding.Path.Path == propertyName && !sources.Contains(dependencyObject);
|
|
|
|
foreach (var bindingBase in bindings)
|
|
{
|
|
if (bindingBase is Binding)
|
|
{
|
|
if (condition(bindingBase as Binding))
|
|
sources.Add(dependencyObject);
|
|
}
|
|
else if (bindingBase is MultiBinding)
|
|
{
|
|
if (((MultiBinding)bindingBase).Bindings.Any(bindingBase2 => condition(bindingBase2 as Binding)))
|
|
{
|
|
sources.Add(dependencyObject);
|
|
}
|
|
}
|
|
else if (bindingBase is PriorityBinding)
|
|
{
|
|
if (((PriorityBinding)bindingBase).Bindings.Any(bindingBase2 => condition(bindingBase2 as Binding)))
|
|
{
|
|
sources.Add(dependencyObject);
|
|
}
|
|
}
|
|
}
|
|
|
|
var children = LogicalTreeHelper.GetChildren(dependencyObject).OfType<DependencyObject>().ToList();
|
|
if (children.Count == 0)
|
|
return;
|
|
|
|
foreach (var child in children)
|
|
{
|
|
GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, child, sources);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|