【问题标题】:GetAdornerLayer mysteriously returning nullGetAdornerLayer 神秘地返回 null
【发布时间】:2011-03-03 14:47:24
【问题描述】:

我一直在为我的应用程序的多个版本使用相同的代码,没有任何问题,但我现在神秘地收到NullRerefenceExceptions,其中包含以下内容:

this.Loaded += delegate {
    deleteBrush = new DeleteBrushAdorner( background );
    AdornerLayer al = AdornerLayer.GetAdornerLayer( background );
    al.Add( deleteBrush ); // null ref here??
};

background 只是一个 Border 元素。

我对可能导致它的两个想法是 a) 切换到 .NET 4.0,以及 b) 将上述元素的实例(即 UserControl)放在 ItemsControl 中。

奇怪的是,这种情况并非一直发生,而且很难预测何时会发生,因此并不可靠。

【问题讨论】:

    标签: c# wpf nullreferenceexception adorner adornerlayer


    【解决方案1】:

    AdornerLayer.GetAdornerLayer 的文档指定:

    如果没有找到装饰层,则该方法返回 null。

    所以我的猜测是没有装饰层……你有理由相信这不应该是这样吗?您目前依靠什么保证在视觉树中会有一个装饰层?

    【讨论】:

    • 如果我使用AdornerDecorator 而不是Border,也会发生同样的事情,尽管我现在根据 MSDN 看到它“为元素 下面 提供了一个装饰层在视觉树中。”让我尝试将边框包裹在 AdornerLayer 中...
    • 在我的情况下它为空,因为我试图过早地访问它(构造函数或OnPropertyChanged)。我可以在OnRender() 中访问它,但当然AdornerDecorator 必须在控制模板中
    【解决方案2】:

    我很好奇这是否真的解决了。 AdornerDecorator 为它下面的元素提供了一个 AdornerLayer——所有东西都在它下面。它是一个装饰器,这意味着它有一个作为内容的 Child。该内容由 AdornerLayer 提供。因此,如果您在 XAML 中放置一个 AdornerDecorator 并且子元素是边框,那么边框确实有一个 AdornerLayer。

    此外,Window 将 AdornerDecorator 定义为可视化树的顶部,因此 Window 中的任何元素都将在其上方具有 AdornerLayer。所以,如果你上面的内容是在一个窗口中......

    【讨论】:

    • 最终的解决方案是将AdornerDecorator above(即作为父级)Border 放在可视化树中。它确实在一个窗口中,尽管是一个无铬的窗口,但也许这是 .NET 4 的一个问题,因为它在 .NET 3.5 中没有 AdornerDecorator 时工作正常。
    • 我遇到了同样的问题。我试图装饰窗口内的控件,但 GetAdornerLayer 返回 null,无论我试图获取装饰层的目的是什么。
    【解决方案3】:

    在我的例子中,我有一个基于 WindowGetAdornerLayer() 的类返回 null。事实证明,我的派生类的ControlTemplate 不包含AdornerDecorator。将其添加为 ControlTemplate 的顶层解决了该问题。

    <Style TargetType="my:MyWindow" BasedOn="{StaticResource {x:Type Window}}">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="my:MyWindow">
                    <AdornerDecorator>
                        <DockPanel ...>
                        </DockPanel>
                    </AdornerDecorator>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
    

    【讨论】: