1

我仍在致力于WPF应用程序的自动测试。我需要通过名称访问属性来实现此目的。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始终为假,将所得lsit是空的。没有“IsAttached”检查,我会得到一个很好的属性列表,但没有任何预期的附加属性。

不反映列出附属属性的方式?


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

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

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

回答

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很可能改变在未来的一些版本中。

+0

非常好,谢谢!该代码做我想要的,我只需要一些修改。真是太可惜了,它需要一个内部的实现细节,并且没有官方的API。 – Silicomancer

+0

什么仍然让我想知道(但并不妨碍我使用代码)是什么snoop不... 随着你的代码,我得到一个更大的附加(和非附加)依赖项属性列表。以某种方式,窥探似乎过滤了与所选对象相关的附加属性。 – Silicomancer

+0

首先,我认为只有那些附加的依赖属性(ADP)由Snoop列出,在选定对象中具有本地设置的值。但那不是事实。实际上,Snoop列出的大多数ADP在所选对象上没有本地值。所以必须有另一种解释。 您是否知道是否有某种方式检查ADP是否与某个对象或其类型有关的某种“相关性”? – Silicomancer