2010-10-18 17 views

cevap

11

Bunu deneyin. İlk olarak, projenize bu DependencyObjectHelper sınıfını yapıştırın. Belirli bir nesnede tüm BindingObjects almanıza olanak veren bir işlevi vardır.

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

Sonra, bu GetBindingSourcesRecursive işlevi oluşturun. Belirli bir özellik adını hedefleyen en az bir Bağlama nesnesine sahip görsel ağaçtaki DependencyObjects nesnesini yinelemeli olarak toplar.

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

Daha sonra, bu kullanım, sadece bir özellik adı geçen GetBindingsRecursive çağrı, görsel kök (örneğin pencere) ve sonuçlarını içeren bir amacı listesi.

List<object> sources = new List<object>(); 
GetBindingSourcesRecursive("SomePropertyPath", this, sources); 
sources.ForEach((o) => Console.WriteLine(o.ToString())); 

Bu yardımcı olur umarım.

3

Kabul edilen ASanch yanıtına dayalı bir kod oluşturdum. Bu kod, 6 kez daha hızlı yapan LogicalTreeHelper kullanır (basit pencerede belirli bir ciltleme ile kontrol için baktığınızda 20 ms. Vs 20ms).

Artı ben ASanch kodunda bazı hataları düzeltmek ( veya "else if (bindingBase) PriorityBinding olan" orijinal ") (bindingBase MultiBinding ise başka" bakmak).

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); 
     } 
    } 
} 
+0

Kodunuzun performansı harika! –

İlgili konular