从WPF窗口检索所有数据绑定

时间:2010-08-27 17:52:33

标签: wpf validation data-binding

我有一个WPF表单,上面有很多控件。许多(但不是全部)这些控件都被数据绑定到底层对象。在某些时候,例如按下“保存”按钮时,我需要检查控件的所有验证规则。有没有办法以编程方式执行此操作,没有硬编码要验证的控件列表?我希望在另一个开发人员添加另一个控件和另一个绑定之后继续工作,而不必更新一些要刷新的绑定列表。

简而言之,有没有办法从WPF窗口检索所有数据绑定的集合?

2 个答案:

答案 0 :(得分:5)

试试下面的示例。我没有对此进行全面测试,因此可能存在问题。此外,性能可能有问题。也许其他人可以帮助他们加快速度。但无论如何,它似乎成功了。

注意:但是,对此的限制是它可能无法获取Styles或DataTemplates中定义的绑定。我不确定。需要更多测试。

无论如何,解决方案基本上分为三个部分:

  1. 使用VisualTreeHelper遍历整个可视树。
  2. 对于可视化树中的每个项目,获取所有依赖项属性。 Reference
  3. 使用BindingOperations.GetBindingBase获取每个属性的绑定。
  4. GetBindingsRecursive 功能:

    void GetBindingsRecursive(DependencyObject dObj, List<BindingBase> bindingList)
            {
                bindingList.AddRange(DependencyObjectHelper.GetBindingObjects(dObj));
    
                int childrenCount = VisualTreeHelper.GetChildrenCount(dObj);
                if (childrenCount > 0)
                {
                    for (int i = 0; i < childrenCount; i++)
                    { 
                        DependencyObject child = VisualTreeHelper.GetChild(dObj, i);
                        GetBindingsRecursive(child, bindingList);
                    }
                }
            }
    

    DependencyObjectHelper 类:

    public static class DependencyObjectHelper
        {
            public static List<BindingBase> GetBindingObjects(Object element)
            {
                List<BindingBase> bindings = new List<BindingBase>();
                List<DependencyProperty> dpList = new List<DependencyProperty>();
                dpList.AddRange(GetDependencyProperties(element));
                dpList.AddRange(GetAttachedProperties(element));
    
                foreach (DependencyProperty dp in dpList)
                {
                    BindingBase b = BindingOperations.GetBindingBase(element as DependencyObject, dp);
                    if (b != null)
                    {
                        bindings.Add(b);
                    }
                }
    
                return bindings;
            }
    
            public static List<DependencyProperty> GetDependencyProperties(Object element)
            {
                List<DependencyProperty> properties = new List<DependencyProperty>();
                MarkupObject markupObject = MarkupWriter.GetMarkupObjectFor(element);
                if (markupObject != null)
                {
                    foreach (MarkupProperty mp in markupObject.Properties)
                    {
                        if (mp.DependencyProperty != null)
                        {
                            properties.Add(mp.DependencyProperty);
                        }
                    }
                }
    
                return properties;
            }
    
            public static List<DependencyProperty> GetAttachedProperties(Object element)
            {
                List<DependencyProperty> attachedProperties = new List<DependencyProperty>();
                MarkupObject markupObject = MarkupWriter.GetMarkupObjectFor(element);
                if (markupObject != null)
                {
                    foreach (MarkupProperty mp in markupObject.Properties)
                    {
                        if (mp.IsAttached)
                        {
                            attachedProperties.Add(mp.DependencyProperty);
                        }
                    }
                }
    
                return attachedProperties;
            }
        }
    

    样本用法:

    List<BindingBase> bindingList = new List<BindingBase>();
    GetBindingsRecursive(this, bindingList);
    
    foreach (BindingBase b in bindingList)
    {
         Console.WriteLine(b.ToString());
    }
    

答案 1 :(得分:4)

.NET 4.5及更高版本中有一个更好的解决方案:

foreach (BindingExpressionBase be in BindingOperations.GetSourceUpdatingBindings(element))
{
    be.UpdateSource();
}