Использование DynamicObject для симуляции DependencyProperties - PullRequest
2 голосов
/ 18 марта 2012

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

Мне удалось реализовать это поведение для свойств CLR с использованием динамического объекта:

  • _knownProperties - это просто список свойств, которые были запрошены ранее
  • _collection - это экземпляр IEnumerable
public override bool TryGetMember( GetMemberBinder binder, out object result ) {
    Debug.WriteLine( "Getting " + binder.Name + "..." );

    if (!_knownProperties.Contains( binder.Name ))
        _knownProperties.Add( binder.Name );

    IEnumerator it = _collection.GetEnumerator();

    if (!it.MoveNext()) {
        result = null;
        Debug.WriteLine( "No elements in collection" );
        return true;
    }

    Type t = it.Current.GetType();
    PropertyInfo pinf = t.GetProperty( binder.Name );
    if (pinf == null) {
        result = null;
        Debug.WriteLine( "Property doesn't exist." );
        return true;
    }
    result = pinf.GetValue( it.Current, null );

    if (result == null) {
        Debug.WriteLine( "Null result" );
        return true;
    }
    while (it.MoveNext())
        if (!result.Equals( it.Current.GetType().GetProperty( binder.Name ).GetValue( it.Current, null ) )) {
            result = null;
            Debug.WriteLine( "Null result" );
            return true;
        }

    Debug.WriteLine( "Result: " + result.ToString() );
    return true;
}

Я обращаюсь к этим свойствам через привязки WPF.Кто-нибудь может придумать способ реализовать это для DependencyProperties?Если я пытаюсь привязать к прикрепленному свойству объекта, я получаю ArgumentNullException в системе свойств (, где нулевой объект не может быть нулевым в соответствии с моим источником )

  • {Binding Selection.SomeClrProperty,...} работает нормально (Selection является одним из динамических объектов, SomeClrProperty является свойством каждого элемента коллекции.
  • {Binding Selection.(SomeClass.SomeAttachedProperty),...} Выдает ошибку вСистема собственности

Исключение:

System.ArgumentNullException was unhandled
Message=Key cannot be null.
Parameter name: key
Source=System
ParamName=key
StackTrace:
   at System.Collections.Specialized.HybridDictionary.get_Item(Object key)
   at System.ComponentModel.PropertyChangedEventManager.PrivateAddListener(INotifyPropertyChanged source, IWeakEventListener listener, String propertyName)
   at System.ComponentModel.PropertyChangedEventManager.AddListener(INotifyPropertyChanged source, IWeakEventListener listener, String propertyName)
   at MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32 k, Object newO, Object parent)
   at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
   at MS.Internal.Data.ClrBindingWorker.AttachDataItem()
   at System.Windows.Data.BindingExpression.Activate(Object item)
   ...

1 Ответ

0 голосов
/ 21 сентября 2012

Используйте привязки OneTime, чтобы WPF не пытался поместить слушателя в присоединенное свойство:

{Binding Selection.(SomeClass.SomeAttachedProperty), Mode=OneTime, ...}
...