Getting list of all dependency/attached properties of an Object

In Visual Studio, in the XAML view when we add a element tag say <Rectangle...> and hit the spacebar, we get a list of all the attached properties and dependency properties of the object. (For e.g. Canvas.Left).

How can this be achieved through procedural code I tried using Reflection (on a Rectangle object in above case) but it did not help.

Thanks,
Niranjan


Answer this question

Getting list of all dependency/attached properties of an Object

  • R Raghu

    Yep, probably I've missed the original poster's intention, it seems he want to get all the DPs available for an element, actually we can use Doug's code here to get all the DPs defined by the WPF base class library, but how about those DPs defined by ourselves

    Sheva


  • Dorisdvu

    Attached properties that appear in Intellisense don't really have anything to do with the object that are attached to.  For instance, when you create a <Rectangle> and see Canvas.Left in the Intellisense, that is just Visual Studio helping you out. There is no relationship between Rectangle and Canvas.Left besides the fact that you can supply a value on a Rectangle for that attached property.  With that in mind, what do you want to achieve

  • Joshizzle

    you can try something like this

    Type t = typeof(Button);

    while (t != null)

    {

    FieldInfo[] fs = t.GetFields();

    System.Diagnostics.Debug.WriteLine(t.ToString());

    for (int i = 0; i < fs.Length; i++)

    System.Diagnostics.Debug.WriteLine("\t" + fsIdea.Name );

    t = t.BaseType;

    }



  • mr4100

    this might be better

    Type t = typeof(Rectangle);

    while (t != null)

    {

    FieldInfo[] fi = t.GetFields();

    for(int i=0;i<fi.Length;i++)

    if (fiIdea.FieldType.Name == "DependencyProperty")

    System.Diagnostics.Debug.WriteLine(fiIdea.Name);

    t = t.BaseType;

    }



  • venp

    we dont get attached properties, if we do like I mentioned

    I think Doug's way is better



  • Steveinbeloit

    Well, Doug's code is awesome, but what the original poster want to do is get all the attached DPs applied to a specified object, then you can use the following helper methods I create:

     public static class DependencyObjectHelper
      {
        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;
        }
      }

    Sheva


  • RhysDavies

    Doug, lee and Zhou,

    Thanks for your great inputs. I have it working now. Initially I used a combination of Doug's and Lee's code and got it to work. Thougg Zhou's code is more specific to the requirement and works too.

    I had not come across MarkupObject and MarkupWriter classes. Another observation I made was that for these classes to work, the element has to be a part of a logical tree. So if I try to create a new Rectangle object and use it , markupobject.Properties is empty. On the other hand if the rectangle is a part of the logical tree, the relevant properties are returned.
    The documentation says that these classes are primarily used to serialize logical trees into XAML format which seems somewhat in harmony to the above observation.
    Any ideas on this

    Thanks,
    Niranjan.

  • AaronL

    going up the inheritance chain like I did, with some modifications should work

  • donbox5

    You can obtain attached properties using reflection. Here's an example that iterates through all the types in an assembly:

    Note the use of DependencyPropertyDescriptor to obtain additional information about each Dependency Property (this allows us to check if they are Attached or not). There may be a better method that avoids iterating over all the types like this, but I haven't found it yet!

    - Doug

    List<DependencyProperty> attached = new List<DependencyProperty>();
    
    Assembly a = Assembly.Load(
      @"PresentationFramework, Version=3.0.0.0, Culture=neutral,
      PublicKeyToken=31bf3856ad364e35");
    
    foreach (Type t in a.GetTypes())
    {
      foreach (FieldInfo fi in t.GetFields(BindingFlags.DeclaredOnly 
        | BindingFlags.Static | BindingFlags.Public))
      {
        if (fi.FieldType == typeof(DependencyProperty))
        {
          DependencyProperty dp = (DependencyProperty)fi.GetValue(null);
          try
          {
            DependencyPropertyDescriptor dpd = 
              DependencyPropertyDescriptor.FromProperty(dp, t);
    
            if (dpd != null && dpd.IsAttached)
            {
              // found an Attached Dependency Property
              attached.Add(dp);
            }
          }
          catch (ArgumentException)
          {
            // there was a problem obtaining the
            // DependencyPropertyDescriptor 
          }
        }
      }
    }

     


  • Buddhist

    Actually I thought I found a slightly more elegant solution:

    public IList<DependencyProperty> GetAttachedProperties(DependencyObject obj)
    {
      List<DependencyProperty> attached = new List<DependencyProperty>();
    
      foreach (PropertyDescriptor pd in TypeDescriptor.GetProperties(obj,
        new Attribute[] { new PropertyFilterAttribute(PropertyFilterOptions.All) }))
      {
        DependencyPropertyDescriptor dpd =
          DependencyPropertyDescriptor.FromProperty(pd);
    
        if (dpd != null && dpd.IsAttached)
        {
          attached.Add(dpd.DependencyProperty);
        }
      }
    
      return attached;
    }

    But, it would appear this will not give any DP's which we define.

    - Doug


  • Trisk2

    Zhou ,

    your code will only get the properties that are set on the element, not all the properties available for the element. Am I missing something



  • dav3333333

    As a side note, my code can only get the locally set DPs.

    Sheva


  • GreenLeyland

    Hi Josh,

    Thanks for the response. Here is my specific requirement -
    In my logical tree, I want the user to be able to provide any object name and any property name on that object as string inputs. Based on these inputs, I need to set a value on that property for that object (more specifically I want to set a binding on that property).

    Thus, for instance if I had a Rectangle object called "myRect" in the logical tree. The user inputs would be:
    Element Name : myRect
    Element Property : Canvas.Left
    Path : SomeInput (used for databinding)

    I then need to get a Dependency property object corresponding to Canvas.Left and set the binding on myRect object programatically (I am using the FrameworkElement.SetBinding method).

    The problem is , as you already mentioned, Canvas.Left has no relationship to Rectangle so I cannot look into Rectangle properties. And moreover the user can provide any property name that can participate in Data Binding. How can I get the corresponding dependency property object in this case

    Thanks,
    Niranjan.



  • Raoul_BennetH

    Actually, you don't need to add the element to the logical tree to get my code work, the following demo code illustrates this:
    <Window x:Class="TestCode.GetAllDPDemo"
       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
       Title="TestCode" Height="300" Width="300"
       >
      <DockPanel>
       <Button Content="Get All DPs" Name="myButton" Width="100" Height="30" DockPanel.Dock="Top"/>
       <TextBlock Name="myTextBlock" FontSize="16" Foreground="Red"/>
      </DockPanel>
    </Window>

    namespace TestCode
    {
        public partial class GetAllDPDemo : Window
        {
     
           public GetAllDPDemo()
           {
               InitializeComponent();
               myButton.Click += new RoutedEventHandler(myButton_Click);
           }
     
           private void myButton_Click(Object sender, RoutedEventArgs e)
           {
               Button btn = new Button();
               DockPanel.SetDock(btn, Dock.Top);
               FocusManager.SetIsFocusScope(btn, true);
               FooClass.SetBarAttached(btn, true); // Set custom attached dependency property.
               myTextBlock.Text = GetAllDPs(btn);
           }
     
           private String GetAllDPs(DependencyObject element)
           {
               StringBuilder sb = new StringBuilder();
               sb.AppendFormat("Attached DPs applied on {0}: \n", element.GetType().Name);
               MarkupObject markupObject = MarkupWriter.GetMarkupObjectFor(element);
               if (markupObject != null)
               {
                  foreach (MarkupProperty property in markupObject.Properties)
                  {
                      if (property.IsAttached)
                      {
                         sb.AppendLine(property.Name);
                      }
                  }
               }
     
               return sb.ToString();
           }
        }
     
        public static class FooClass
        {
           public static readonly DependencyProperty BarAttachedProperty = DependencyProperty.RegisterAttached(
                       "BarAttached",
                       typeof(Object),
                       typeof(FooClass),
                       new FrameworkPropertyMetadata(null));
     
           public static Object GetBarAttached(DependencyObject element)
           {
               return element.GetValue(BarAttachedProperty);
           }
     
           public static void SetBarAttached(DependencyObject element, Object value)
           {
               element.SetValue(BarAttachedProperty, value);
           }
        }
    }

    Please take a closer look at the code hightlighted in red colour, actually my code also supports custom attched DP scenario.

    Sheva


  • Getting list of all dependency/attached properties of an Object