Silverlight Blend行为在设计时无法附加。

4
我已经开发了一种行为,可以更改AssociatedObject的Clip属性。当我运行应用程序时,一切都很好。但是当我在Blend中查看页面时,似乎该行为不影响其关联对象。
我尝试通过将Visual Studio 2010调试器附加到它的进程并在行为的OnAttached方法上设置断点来“调试”Blend,但断点从未被触发。就像Blend阻止在设计时附加该行为一样。
是否有解决方法?
谢谢。

据我所知,这个问题在使用Visual Studio 2013的WPF中也存在(其中包含Blend集成在其设计师内部)。我遇到了您的问题,因为我在这个环境中有类似的情况。 - FrankyB
2个回答

2

我终于找到了一个可行的解决办法,但是有一个很大的警告,我放在了这个答案的最后。下面是我的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 使用的就是附加属性。

如果我找到解决此问题的方法,我会更新此答案。


谢谢,约翰,那实际上是一个非常好的解决方案。我也为Win8商店应用程序实现了自己的行为集合(其中没有本地行为支持),并且实际上在设计时间内设法让它们工作,尽管在使用多个行为时存在传递数据上下文的问题,正如你在你的解决方案中注意到的那样。 - Kobi Hari
@KobiHari 如果你有关于Win8商店xaml的链接,如果你能在这里发布这样的链接就太好了。我还没有尝试过它与Silverlight相比如何,也许在将来的某个时候我会不得不尝试一下。 - John

0

我不确定,但我认为关联对象只能在行为“附加”后受到影响。这是在“OnAttached”事件期间调用的,我不认为此事件在设计时被调用。据我所知,控件的设计时更改发生在它们的初始化/创建阶段。 OnAttached发生在所有这些之后(因此关联对象可用于操作),因此使得行为难以在设计时更改控件。我并不是说这是不可能的,但从控件生命周期和行为的明显设计来看,这种方法似乎很困难。 解决方案:

  • 采用模板操作的方法。设计一种自定义的样式或资源字典键,以创造出你所追求的印象。
  • 在Visual Studio中创建一个自定义控件,该控件暴露一个属性,可以将另一个控件绑定到该属性上。让这个自定义控件在其初始化方法之一中操纵这个“属性”,即您带有剪辑属性的控件。例如,在InitializeComponent期间,检查内容是否加载完毕,然后调用一个方法来调整您所期望的“Clip”属性。详细了解Silverlight控件的生命周期可能会对您有所帮助-http://stuff.seans.com/2009/03/23/hello-silverlight-world-part-3-the-lifecycle-of-a-silverlight-control/

就像我说的那样,我对答案不确定,但是我可以说这么多-如果解决方案看起来太复杂,可能有更简洁的方法;)


Neel,正如我所写的,我知道行为的OnAttached方法没有被调用,问题是为什么。我可以选择很多不同的方法(例如,一个附加属性,我已经尝试过了,它在设计时和运行时都有效)。由于附加行为是基于附加属性的,所以它们在设计时表现出不同的行为似乎有点奇怪。我想知道的是,是否有人知道为什么OnAttached方法在设计时没有被调用,是否有什么不同的方法可以使其被调用。 - Kobi Hari
啊。我相信这只是设计时生命周期的一部分。我记得在做一个ASP.NET项目时遇到了类似的情况。我正在做一个自定义组合框,希望在设计时稍微预先填充一些内容,然后我意识到有些方法直到运行时才会被调用。我还没有找到文档说明哪些方法在设计时调用,哪些方法在运行时调用。 - Neel Edwards
我的最后一次赌注是确保您正在使用DependencyProperties而不是普通属性。除此之外,在VS 2010中它是否做相同的事情?@KobiHari - Neel Edwards
当然,只有依赖属性。而且,在VS2010中也是这样做的。 - Kobi Hari
在这种情况下,这似乎是一个Silverlight问题本身...希望有人能找到答案,因为我必须说,我很困惑。@KobiHari - Neel Edwards

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接