WPF. Find control that binds to specific property

前端 未结 2 1724
猫巷女王i
猫巷女王i 2020-12-06 03:09

Any ideas on how to implement a method that given a propertyname, finds a control (perhaps from a visualtree) which is bound to the given property?

2条回答
  •  伪装坚强ぢ
    2020-12-06 03:24

    I created code based on accepted ASanch answer. This code uses LogicalTreeHelper which makes it 6times faster (130ms vs 20ms when looking for control with specific binding on simple window).

    Plus I fix some errors in ASanch code (look at original "else if (bindingBase is MultiBinding)" or "else if (bindingBase is PriorityBinding)").

    public static class DependencyObjectHelper
    {
        /// 
        /// Gets all dependency objects which has binding to specific property
        /// 
        /// 
        /// 
        /// 
        public static IList GetDependencyObjectsWithBindingToProperty(DependencyObject dependencyObject, string propertyName)
        {
            var list = new List();
            GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, dependencyObject, list);
    
            return list;
        }
    
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// 
        /// Based on ASanch answer on http://stackoverflow.com/questions/3959421/wpf-find-control-that-binds-to-specific-property
        /// >
        private static void GetDependencyObjectsWithBindingToPropertyRecursive(string propertyName, DependencyObject dependencyObject, ICollection sources)
        {
            var dependencyProperties = new List();
            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 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().ToList();
            if (children.Count == 0)
                return;
    
            foreach(var child in children)
            {
                GetDependencyObjectsWithBindingToPropertyRecursive(propertyName, child, sources);
            }
        }
    }
    

提交回复
热议问题