Question

I am still working on automated testing of WPF apps. I need to access properties by name to achieve this.

Currently I am wondering about attached properties of WPF controls. I tried to iterate through all properties of a Button object thinking I could find attached properties too. But I couldn't find them.

So I checked using Snoop and it lists a lot of properties like "KeyboardNavigation.AcceptsReturn" and "ToolTipManager.ToolTipKey" which should be attached properties AFAIK.

I used the following code to create a list of names of (attached) properties of Button "object":

   Type^ type = object->GetType();
   while (type)
   {
      array<FieldInfo^>^ fi = type->GetFields(BindingFlags::DeclaredOnly | BindingFlags::Static | BindingFlags::Public);
      for (int i=0; i<fi->Length; i++)
      {
         DependencyProperty^ dp = dynamic_cast<DependencyProperty^>(fi[i]->GetValue(object));
         if (dp)
         {
            DependencyPropertyDescriptor^ dpd = DependencyPropertyDescriptor::FromProperty(dp, type);
            if (dpd->IsAttached)
            {
               propertyNames->Add(fi[i]->Name);
            }
         }
      }

      type = type->BaseType;
   }

However IsAttached is always false and the resulting lsit is empty. Without the "IsAttached" check I get a nice list of properties but without any of the expected attached properties.

Doesn't reflect list the attached properties that way?


I think I now better understand usage of attached properties. However I could not actually solve my problem. The mentioned local enumerator only gets the properties that are set on the object locally, not all the properties available for the object.

Please let me explain what I intend: I am starting with the name of an attached property only... I first need to check if that attached property exists (which probably means if it is registered, right?). Then I want to fetch the attached property's value which may be the locally set value for my object (if one was set) or the default value otherwise.

Currently I don't know how to check if an attached property exists. Is there maybe some function providing a list of all available attached properties? I could use it for validating a given property name and to fetch the corresponding property object.

Was it helpful?

Solution 2

Sorry, work has been keeping me busy. You could do this:

Assuming xaml:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition/>
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>

    <Button x:Name="btn" Grid.Column="1"/>

</Grid>

The following code should give you some options:

    //do this if you can:
    btn.GetValue(Grid.ColumnProperty);

    //Otherwise,
    //gets all the dependency properties in the app domain
    Type depType = typeof(DependencyProperty) ;
    FieldInfo info = depType.GetField("PropertyFromName", BindingFlags.NonPublic | BindingFlags.Static);
    Hashtable AllDependencyProperties = info.GetValue(null) as Hashtable;

    //Index the hashtable of all dependency properties using a FromNameKey type            
    Type FromNameKeyType = depType.Assembly.GetType("System.Windows.DependencyProperty+FromNameKey");            
    ConstructorInfo ctor = FromNameKeyType.GetConstructor(new Type[] { typeof(String), typeof(Type) });
    var NameKey = ctor.Invoke(new object[] { "Column", typeof(Grid) });

    //index the hashtable to get the Dependency property
    DependencyProperty dp = AllDependencyProperties[NameKey] as DependencyProperty;

    //use the dp to get the value
    btn.GetValue(dp);


    //Or, without indexing a list of all dependency properties
    //get a dependency property by name
    System.Reflection.MethodInfo FromNameMethod = depType.GetMethod("FromName",System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic );
    var ret = FromNameMethod.Invoke(null, new object[] { "Column", typeof(Grid) });

    //use it to get a value from an object
    btn.GetValue((ret as DependencyProperty));

Caveat: this is using private members and classes which, MS could well change in some future version.

OTHER TIPS

Attached properties differ from normal dependency properties in several ways. The most noticeable is that they are not wrapped in CLR properties (i.e. standard .NET properties).

Have a look at http://joshsmithonwpf.wordpress.com/2007/06/22/overview-of-attached-properties-in-wpf/ for more detail.

You might want try using GetLocalValueEnumerator to iterate over your properties http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.getlocalvalueenumerator.aspx

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top