我终于找到了一个可行的解决办法,但是有一个很大的警告,我放在了这个答案的最后。下面是我的CustomAttachManager:
public class CustomAttachManager : DependencyObject
{
#region Object CustomAttachManager.Attached = null
public static IAttachedObject GetAttached(DependencyObject obj) { return (IAttachedObject)obj.GetValue(AttachedProperty); }
public static void SetAttached(DependencyObject obj, IAttachedObject value) { obj.SetValue(AttachedProperty, value); }
public static readonly DependencyProperty AttachedProperty =
DependencyProperty.RegisterAttached("Attached", typeof(IAttachedObject), typeof(CustomAttachManager), new PropertyMetadata(null, StaticHandleAttachedChanged));
static void StaticHandleAttachedChanged(DependencyObject self, DependencyPropertyChangedEventArgs args)
{
var ov = (IAttachedObject)args.OldValue;
var nv = (IAttachedObject)args.NewValue;
if (ov != null) ov.Detach();
if (nv != null) nv.Attach(self);
}
#endregion
}
您可以使用它来附加如下行为:
<my:CustomAttachManager.Attached>
<my:RedBackgroundBehavior></my:RedBackgroundBehavior>
</my:CustomAttachManager.Attached>
我的示例行为将面板的背景更改为红色,在设计器中可见。
剩下的问题是多个行为的情况。我能想到的最好解决方案是使用代理:
[ContentProperty("Children")]
public class MultipleBehavior : Behavior<DependencyObject>
{
DependencyObjectCollection<IAttachedObject> children = new DependencyObjectCollection<IAttachedObject>();
public DependencyObjectCollection<IAttachedObject> Children { get { return children; } }
protected override void OnAttached()
{
foreach (var child in Children) child.Attach(AssociatedObject);
}
protected override void OnDetaching()
{
foreach (var child in Children) child.Detach();
}
}
这可以这样使用:
<my:CustomAttachManager.Attached>
<my:MultipleBehavior>
<my:RedBackgroundBehavior />
<my:SupriseBehavior />
</my:MultipleBehavior>
</my:CustomAttachManager.Attached>
代理存在一个缺陷,即它不能正确处理在已经附加了某些内容之后添加的行为,但这不会在经典用例中发生。
需要注意的是,我不知道如何使 Blend 在对象树中显示这些行为。 "AlternateContentProperty" 无法使用,因为它无法用于附加属性,而 CustomAttachManager 使用的就是附加属性。
如果我找到解决此问题的方法,我会更新此答案。