2010-10-18 1 views

Antwort

11

Versuchen Sie diese. Kopieren Sie zuerst diese DependencyObjectHelper-Klasse in Ihr Projekt. Es verfügt über eine Funktion, mit der Sie alle BindingObjects in einem bestimmten Objekt abrufen können.

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

Dann erstellen Sie diese GetBindingSourcesRecursive Funktion. Es sammelt rekursiv die DependencyObjects in der visuellen Struktur, die mindestens ein Binding-Objekt aufweist, das auf einen bestimmten Eigenschaftsnamen abzielt.

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

Dann wird diese zu verwenden, rufen Sie einfach GetBindingsRecursive in dem Eigenschaftsnamen vorbei, die Wurzel visuelle (zum Beispiel das Fenster), und eine Objektliste, die die Ergebnisse enthält.

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

Hoffe das hilft.

3

Ich erstellte Code basierend auf angenommenen ASanch Antwort. Dieser Code verwendet LogicalTreeHelper, der es sechsmal schneller macht (130ms gegenüber 20ms, wenn nach Kontrolle mit spezifischer Bindung für ein einfaches Fenster gesucht wird).

Plus I einige Fehler in ASanch Code zu beheben (siehe original "else if (Bindingmultibinding ist)" oder "else if (Binding ist Priority)").

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

Die Leistung Ihres Codes ist großartig! –

Verwandte Themen