有关如何实现给定属性名的方法的任何想法,都会找到绑定到给定属性的控件(可能来自visualtree)?WPF。查找绑定到特定属性的控件
6
A
回答
11
试试这个。首先,在您的项目中复制粘贴此DependencyObjectHelper类。它有一个函数可以让你获得给定对象中的所有BindingObjects。
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(DependencyObjectHelper.GetDependencyProperties(element));
dpList.AddRange(DependencyObjectHelper.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;
}
}
然后,创建这个GetBindingSourcesRecursive功能。它递归地收集可视树中的DependencyObjects,该可视树至少有一个绑定对象,其目标是给定的属性名称。
private void GetBindingSourcesRecursive(string propertyName, DependencyObject root, List<object> sources)
{
List<BindingBase> bindings = DependencyObjectHelper.GetBindingObjects(root);
Predicate<Binding> condition =
(b) =>
{
return (b.Path is PropertyPath)
&& (((PropertyPath)b.Path).Path == propertyName)
&& (!sources.Contains(root));
};
foreach (BindingBase bindingBase in bindings)
{
if (bindingBase is Binding)
{
if (condition(bindingBase as Binding))
sources.Add(root);
}
else if (bindingBase is MultiBinding)
{
MultiBinding mb = bindingBase as MultiBinding;
foreach (Binding b in mb.Bindings)
{
if (condition(bindingBase as Binding))
sources.Add(root);
}
}
else if (bindingBase is PriorityBinding)
{
PriorityBinding pb = bindingBase as PriorityBinding;
foreach (Binding b in pb.Bindings)
{
if (condition(bindingBase as Binding))
sources.Add(root);
}
}
}
int childrenCount = VisualTreeHelper.GetChildrenCount(root);
if (childrenCount > 0)
{
for (int i = 0; i < childrenCount; i++)
{
DependencyObject child = VisualTreeHelper.GetChild(root, i);
GetBindingSourcesRecursive(propertyName, child, sources);
}
}
}
然后,使用此,只需调用GetBindingsRecursive传入属性名,根视觉(例如,窗口),并且将包含结果的对象列表。
List<object> sources = new List<object>();
GetBindingSourcesRecursive("SomePropertyPath", this, sources);
sources.ForEach((o) => Console.WriteLine(o.ToString()));
希望这会有所帮助。
3
我根据接受的ASanch答案创建了代码。这段代码使用了LogicalTreeHelper,它使它快6倍(当在简单的窗口中寻找具有特定绑定的控件时,130ms vs 20ms)。
加上我修复ASanch代码一些错误(看原“否则,如果(bindingBase是MultiBinding)”或“否则,如果(bindingBase是PriorityBinding)”)。
public static class DependencyObjectHelper
{
/// <summary>
/// Gets all dependency objects which has binding to specific property
/// </summary>
/// <param name="dependencyObject"></param>
/// <param name="propertyName"></param>
/// <returns></returns>
public static IList<DependencyObject> GetDependencyObjectsWithBindingToProperty(DependencyObject dependencyObject, string propertyName)
{
var list = new List<DependencyObject>();
GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, dependencyObject, list);
return list;
}
/// <summary>
///
/// </summary>
/// <param name="propertyName"></param>
/// <param name="dependencyObject"></param>
/// <param name="sources"></param>
/// <remarks>
/// Based on ASanch answer on http://stackoverflow.com/questions/3959421/wpf-find-control-that-binds-to-specific-property
/// </remarks>>
private static void GetDependencyObjectsWithBindingToPropertyRecursive(string propertyName, DependencyObject dependencyObject, ICollection<DependencyObject> sources)
{
var dependencyProperties = new List<DependencyProperty>();
dependencyProperties.AddRange(MarkupWriter.GetMarkupObjectFor(dependencyObject).Properties.Where(x => x.DependencyProperty != null).Select(x => x.DependencyProperty).ToList());
dependencyProperties.AddRange(
MarkupWriter.GetMarkupObjectFor(dependencyObject).Properties.Where(x => x.IsAttached && x.DependencyProperty != null).Select(x => x.DependencyProperty).ToList());
var bindings = dependencyProperties.Select(x => BindingOperations.GetBindingBase(dependencyObject, x)).Where(x => x != null).ToList();
Predicate<Binding> condition = binding => binding != null && binding.Path.Path == propertyName && !sources.Contains(dependencyObject);
foreach (var bindingBase in bindings)
{
if (bindingBase is Binding)
{
if (condition(bindingBase as Binding))
sources.Add(dependencyObject);
}
else if (bindingBase is MultiBinding)
{
if (((MultiBinding)bindingBase).Bindings.Any(bindingBase2 => condition(bindingBase2 as Binding)))
{
sources.Add(dependencyObject);
}
}
else if (bindingBase is PriorityBinding)
{
if (((PriorityBinding)bindingBase).Bindings.Any(bindingBase2 => condition(bindingBase2 as Binding)))
{
sources.Add(dependencyObject);
}
}
}
var children = LogicalTreeHelper.GetChildren(dependencyObject).OfType<DependencyObject>().ToList();
if (children.Count == 0)
return;
foreach(var child in children)
{
GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, child, sources);
}
}
}
相关问题
- 1. WPF绑定到特定的属性
- 2. WPF:如何绑定到另一个控件绑定的属性?
- 3. WPF绑定到具有特定属性的对象的属性
- 4. WPF:查找绑定域对象属性
- 5. WPF中控件的属性绑定
- 6. WPF部分绑定到特定控件
- 7. 绑定到父控件属性时,子WPF控件的绑定不会更新
- 8. WPF绑定到自定义控件的属性
- 9. WPF:绑定到MainWindow属性
- 10. WPF绑定到UserControl属性
- 11. WPF自定义控件属性没有收到数据绑定
- 12. WPF:绑定属性到自定义用户控件
- 13. WPF:无法绑定到用户控件中的依赖属性
- 14. 如何将依赖项属性绑定到WPF中的控件?
- 15. 我可以将WPF控件绑定到字段的属性吗?
- 16. WPF绑定到用户控件的属性
- 17. WPF - 绑定到ViewModel中的属性和其他控件
- 18. WPF绑定到控件模板上的非依赖项属性
- 19. 绑定自定义类型属性的WPF控件
- 20. WPF绑定控件到DataView
- 21. WPF绑定到子控件
- 22. WPF属性绑定的TextBlock
- 23. ASP.NET绑定到一个控件属性
- 24. 将控件绑定到嵌套属性
- 25. 单属性绑定到多个控件在WPF
- 26. WPF:多个控件绑定到同一属性
- 27. 将wpf用户控件绑定到父项属性
- 28. 如何将WPF控件绑定到VB.net属性?
- 29. WPF将属性绑定到子控件中的依赖项属性
- 30. WPF ContextMenu将某些属性绑定到同一控件的另一个属性
代码的性能很好! – 2017-07-29 10:04:58