【问题标题】:Retrieve all Data Bindings from WPF Window从 WPF 窗口中检索所有数据绑定
【发布时间】:2014-07-10 02:08:22
【问题描述】:

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

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

【问题讨论】:

  • 这个问题很模糊,所以我不能确定。但是任何有类似情况的人都可能希望使用BindingGroup 作为组织相关绑定的一种方式,以便可以完成一次性验证。

标签: wpf validation data-binding


【解决方案1】:

在下面试用我的示例。我还没有完全测试这个,所以它可能有问题。此外,性能可能值得怀疑。也许其他人可以帮助加快速度。但无论如何,它似乎可以解决问题。

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

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

  1. 使用 VisualTreeHelper 遍历整个可视化树。
  2. 对于可视树中的每个项目,获取所有依赖项属性。 Reference
  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);
                }
            }
        }

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());
}

【讨论】:

  • 为什么是 VisualTreeHelper 而不是 LogicalTreeHelper?有什么具体原因吗?
  • 在我的情况下,我需要使用 LogicalTreeHelper,否则我的树中的所有 UIElements 都找不到。我对 Visual/LogicalTreeHelper 的了解不够,无法解释这一点,但我只是想让其他人知道。
【解决方案2】:

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

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

【讨论】:

  • 这并不完全相同,因为它只返回处于特定状态的绑定。您不能使用它来查找所有绑定。
猜你喜欢
  • 1970-01-01
  • 2013-03-19
  • 2016-03-23
  • 2021-04-16
  • 1970-01-01
  • 2011-06-05
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
相关资源
最近更新 更多