1

我仍在致力于 WPF 应用程序的自动化测试。我需要按名称访问属性来实现这一点。

目前我想知道 WPF 控件的附加属性。我试图遍历 Button 对象的所有属性,认为我也可以找到附加属性。但我找不到他们。

因此,我使用 Snoop 进行了检查,它列出了许多属性,例如“KeyboardNavigation.AcceptsReturn”和“ToolTipManager.ToolTipKey”,它们应该附加属性 AFAIK。

我使用以下代码创建按钮“对象”的(附加)属性名称列表:

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

但是 IsAttached 始终为 false,并且生成的 lsit 为空。如果没有“IsAttached”检查,我会得到一个很好的属性列表,但没有任何预期的附加属性。

不反映以这种方式列出附加属性吗?


我想我现在更好地理解了附加属性的用法。但是我实际上无法解决我的问题。提到的本地枚举器仅获取在本地对象上设置的属性,而不是对象可用的所有属性。

请让我解释一下我的意图:我仅从附加属性的名称开始...我首先需要检查该附加属性是否存在(这可能意味着它是否已注册,对吗?)。然后我想获取附加属性的值,它可能是我的对象的本地设置值(如果设置了一个)或默认值。

目前我不知道如何检查附加属性是否存在。是否有一些功能提供所有可用附加属性的列表?我可以使用它来验证给定的属性名称并获取相应的属性对象。

4

2 回答 2

2

附加属性在几个方面不同于正常的依赖属性。最值得注意的是它们没有包装在 CLR 属性(即标准 .NET 属性)中。

查看http://joshsmithonwpf.wordpress.com/2007/06/22/overview-of-attached-properties-in-wpf/了解更多详情。

您可能想尝试使用 GetLocalValueEnumerator 来迭代您的属性http://msdn.microsoft.com/en-us/library/system.windows.dependencyobject.getlocalvalueenumerator.aspx

于 2013-04-15T15:59:09.230 回答
0

对不起,工作一直让我很忙。你可以这样做:

假设 xaml:

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

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

</Grid>

以下代码应该为您提供一些选项:

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

警告:这是使用私有成员和类,MS 很可能在未来的某个版本中进行更改。

于 2013-04-18T11:48:02.857 回答