【问题标题】:Is there a way to get all BindingExpression objects for a Window?有没有办法获取 Window 的所有 BindingExpression 对象?
【发布时间】:2011-02-16 22:38:44
【问题描述】:

有没有办法获取 Window 的所有 BindingExpression 对象?

当需要触发以刷新表单的 PropertyChanged 事件的数量太高且不是一个好的选择时,我正在尝试刷新表单。我正在考虑以另一种方式来实现表单/窗口可以重新查询所有绑定。

【问题讨论】:

  • link 的可能重复项

标签: wpf binding


【解决方案1】:

如果您使用具有nullString.Empty 参数的PropertyChangedEventArgs 引发PropertyChanged,则所有属性的绑定都会更新。

[MSDN Reference]

我认为反过来做会复杂得多,而且可能会消耗更多的性能。您需要检查整个窗口中每个 DependencyObject 的每个 DependencyProperty 是否有绑定。

编辑:编写了以下粗略的扩展方法,它可以满足您的要求,它的效率非常低(可能还有改进的余地,但您仍在处理相当复杂的算法):

public static void UpdateAllBindings(this DependencyObject o)
{
    //Immediate Properties
    List<FieldInfo> propertiesAll = new List<FieldInfo>();
    Type currentLevel = o.GetType();
    while (currentLevel != typeof(object))
    {
        propertiesAll.AddRange(currentLevel.GetFields());
        currentLevel = currentLevel.BaseType;
    }
    var propertiesDp = propertiesAll.Where(x => x.FieldType == typeof(DependencyProperty));
    foreach (var property in propertiesDp)
    {
        BindingExpression ex = BindingOperations.GetBindingExpression(o, property.GetValue(o) as DependencyProperty);
        if (ex != null)
        {
            ex.UpdateTarget();
        }
    }

    //Children
    int childrenCount = VisualTreeHelper.GetChildrenCount(o);
    for (int i = 0; i < childrenCount; i++)
    {
        var child = VisualTreeHelper.GetChild(o, i);
        child.UpdateAllBindings();
    }
}

【讨论】:

    【解决方案2】:

    仅供参考,当您调用 BindingOperations.ClearAllBindings() 时,WPF 本身就是这样做的(遍历所有数据绑定属性)。 代码如下:

    public static void ClearAllBindings(DependencyObject target)
    {
        if (target == null)
        {
            throw new ArgumentNullException("target");
        }
        LocalValueEnumerator localValueEnumerator = target.GetLocalValueEnumerator();
        ArrayList arrayList = new ArrayList(8);
        while (localValueEnumerator.MoveNext())
        {
            LocalValueEntry current = localValueEnumerator.Current;
            if (BindingOperations.IsDataBound(target, current.Property))
            {
                arrayList.Add(current.Property);
            }
        }
        for (int i = 0; i < arrayList.Count; i++)
        {
            target.ClearValue((DependencyProperty)arrayList[i]);
        }
    }
    

    LocalValueEnumerator 是公开的,因此您也可以使用它。 您应该能够轻松地从中推断出解决方案。

    【讨论】:

      猜你喜欢
      • 2011-03-21
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 2022-01-18
      • 2010-11-23
      • 2017-06-15
      • 2022-01-07
      • 2012-03-21
      相关资源
      最近更新 更多