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

GWL*_*osa 2 data-binding validation wpf

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

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

ASa*_*nch 5

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

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

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

  1. 使用VisualTreeHelper遍历整个可视树.
  2. 对于可视化树中的每个项目,获取所有依赖项属性. 参考.
  3. 使用BindingOperations.GetBindingBase获取每个属性的绑定.

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);
                }
            }
        }
Run Code Online (Sandbox Code Playgroud)

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;
        }
    }
Run Code Online (Sandbox Code Playgroud)

样品用法:

List<BindingBase> bindingList = new List<BindingBase>();
GetBindingsRecursive(this, bindingList);

foreach (BindingBase b in bindingList)
{
     Console.WriteLine(b.ToString());
}
Run Code Online (Sandbox Code Playgroud)


can*_*ari 5

.NET 4.5 及以上版本有更好的解决方案:

foreach (BindingExpressionBase be in BindingOperations.GetSourceUpdatingBindings(element))
{
    be.UpdateSource();
}
Run Code Online (Sandbox Code Playgroud)

  • 这并不完全相同,因为它只返回处于特定状态的绑定。您不能使用它来查找所有绑定。 (2认同)