【发布时间】:2011-02-16 22:38:44
【问题描述】:
有没有办法获取 Window 的所有 BindingExpression 对象?
当需要触发以刷新表单的 PropertyChanged 事件的数量太高且不是一个好的选择时,我正在尝试刷新表单。我正在考虑以另一种方式来实现表单/窗口可以重新查询所有绑定。
【问题讨论】:
-
link 的可能重复项
有没有办法获取 Window 的所有 BindingExpression 对象?
当需要触发以刷新表单的 PropertyChanged 事件的数量太高且不是一个好的选择时,我正在尝试刷新表单。我正在考虑以另一种方式来实现表单/窗口可以重新查询所有绑定。
【问题讨论】:
如果您使用具有null 或String.Empty 参数的PropertyChangedEventArgs 引发PropertyChanged,则所有属性的绑定都会更新。
我认为反过来做会复杂得多,而且可能会消耗更多的性能。您需要检查整个窗口中每个 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();
}
}
【讨论】:
仅供参考,当您调用 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 是公开的,因此您也可以使用它。 您应该能够轻松地从中推断出解决方案。
【讨论】: