【问题标题】:Attached properties of WPF controlsWPF 控件的附加属性
【发布时间】:2013-04-15 15:31:37
【问题描述】:

我仍在致力于 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”检查,我会得到一个很好的属性列表,但没有任何预期的附加属性。

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


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

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

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

【问题讨论】:

    标签: wpf dependency-properties attached-properties system.reflection snoop


    【解决方案1】:

    附加属性不同于普通的依赖属性 几种方式。最引人注目的是它们没有被包裹在 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

    【讨论】:

      【解决方案2】:

      抱歉,工作一直让我很忙。你可以这样做:

      假设 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 很可能在未来的某个版本中进行更改。

      【讨论】:

      • 非常好,谢谢!该代码可以满足我的要求,我只需要进行一些修改。可惜它需要一个内部实现细节,而且没有官方 API。
      • 仍然让我想知道(但不阻止我使用代码)是 snoop 到底是做什么的...使用您的代码,我得到了一个更大的附加(和非附加)依赖项列表特性。在某种程度上,窥探似乎过滤了与所选对象相关的附加属性。
      • 首先我认为只有那些由 Snoop 列出的附加依赖属性 (ADP) 在所选对象中具有本地设置的值。但事实并非如此。实际上,Snoop 列出的大多数 ADP 在所选对象上都没有本地值。所以必须有另一种解释。您是否知道是否有某种方法可以检查 ADP 是否与对象或其类型相关的某种“相关性”?