Прикрепленные свойства элементов управления WPF

Я все еще работаю над автоматическим тестированием приложений WPF. Мне нужно получить доступ к свойствам по имени, чтобы добиться этого.

В настоящее время меня интересуют прикрепленные свойства элементов управления WPF. Я попытался перебрать все свойства объекта Button, думая, что смогу найти и прикрепленные свойства. Но я не мог их найти.

Итак, я проверил с помощью Snoop, и в нем перечислено множество свойств, таких как «KeyboardNavigation.AcceptsReturn» и «ToolTipManager.ToolTipKey», которые должны быть присоединены к свойствам AFAIK.

Я использовал следующий код для создания списка имен (прикрепленных) свойств объекта Button:

   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» я получаю хороший список свойств, но без каких-либо ожидаемых присоединенных свойств.

Не отражает ли список прикрепленных свойств таким образом?


Думаю, теперь я лучше понимаю использование прикрепленных свойств. Однако на самом деле я не мог решить свою проблему. Упомянутый локальный перечислитель получает только те свойства, которые заданы для объекта локально, а не все свойства, доступные для объекта.

Пожалуйста, позвольте мне объяснить, что я имею в виду: я начинаю с имени только прикрепленного свойства... Сначала мне нужно проверить, существует ли это присоединенное свойство (что, вероятно, означает, зарегистрировано ли оно, верно? ). Затем я хочу получить значение прикрепленного свойства, которое может быть локально заданным значением для моего объекта (если оно было установлено) или значением по умолчанию в противном случае.

В настоящее время я не знаю, как проверить, существует ли прикрепленное свойство. Может быть, есть какая-то функция, предоставляющая список всех доступных прикрепленных свойств? Я мог бы использовать его для проверки заданного имени свойства и для получения соответствующего объекта свойства.


person Silicomancer    schedule 15.04.2013    source источник


Ответы (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 вполне может изменить в какой-то будущей версии.

person A Aiston    schedule 18.04.2013
comment
Очень мило спасибо! Этот код делает то, что я хочу, мне нужно лишь несколько модификаций. Какой позор, что для этого нужны детали внутренней реализации и что для этого нет официального API. - person Silicomancer; 21.04.2013
comment
Что все еще заставляет меня задуматься (но не мешает мне использовать код), так это то, что именно делает snoop... С вашим кодом я получаю гораздо больший список присоединенных (и неприкрепленных) свойств зависимостей. Каким-то образом snoop, кажется, фильтрует прикрепленные свойства в отношении выбранного объекта. - person Silicomancer; 21.04.2013
comment
Сначала я подумал, что Snoop перечисляет только те прикрепленные свойства зависимостей (ADP), которые имеют локально установленные значения в выбранном объекте. Но это не факт. На самом деле большинство ADP, перечисленных Snoop, не имеют локального значения для выбранного объекта. Значит, должно быть другое объяснение. Знаете ли вы, есть ли какой-либо способ проверки ADP на предмет релевантности по отношению к объекту или его типу? - person Silicomancer; 21.04.2013

Присоединенные свойства отличаются от обычных свойств зависимостей несколькими способами. Наиболее заметно то, что они не обернуты в свойства 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

person A Aiston    schedule 15.04.2013