【问题标题】:Using DynamicObject to simulate DependencyProperties使用 DynamicObject 模拟 DependencyProperties
【发布时间】:2012-03-18 08:38:23
【问题描述】:

我正在寻找类似于 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根据我拥有的来源,为 null 的对象不可能为 null

  • {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)
   ...

【问题讨论】:

  • 澄清一下,您想在集合中同时包含静态属性和实例属性? (“SomeClass.SomeAttachedProperty”似乎是静态的,但我在您的 GetValue 调用中看到您没有将 null 作为源传递——这是获取静态值的必要部分。)
  • @Brannon, SomeClass.SomeAttachedProperty 将是一个静态字段,但该属性的值肯定是附加到实例的。使用该语法时,似乎没有调用 DynamicObject 中的任何函数,它只是产生了所述错误。我想这是由于绑定实际上没有使用 DependencyObject 访问器/突变器,而是直接从属性系统中获取值。

标签: c# dependency-properties dynamicobject


【解决方案1】:

使用 OneTime 绑定来防止 WPF 尝试在附加属性上放置侦听器:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-11
    • 1970-01-01
    相关资源
    最近更新 更多