获取装饰层返回null

6

我遇到了问题:

AdornerLayer AdornerLayer = AdornerLayer.GetAdornerLayer (layout);

这个方法总是返回null。

我做错了什么?

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        Layout layout = new Layout();
        layout.Background = Brushes.White;
        layout.ClipToBounds = true;
        layout.SnapsToDevicePixels = true;
        layout.Width = 4965; layout.Height = 3515;

        AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(layout);
        adornerLayer.Add(new LayoutAdorner(layout));
    }
}


public class Layout : Canvas
{
    public Visual GetVisualChildAtPoint(Point point)
    {
        return VisualTreeHelper.HitTest(this, point).VisualHit as Visual;
    }
}

public class LayoutAdorner : Adorner
{
    public LayoutAdorner(UIElement adornedElement) : base(adornedElement) { }

    protected override void OnRender(DrawingContext drawingContext)
    {

    }
}
3个回答

10

只有当窗口实际加载并且句柄创建后,窗口的AdornerLayer才会被创建。

您可能需要延迟操作,并在窗口加载后添加装饰图层,而不是将其放在构造函数中。


谢谢您的回复。您是什么意思? - user2296810
@user2296810 将装饰器代码移入Loaded事件中 - 参见https://dev59.com/AUbRa4cB1Zd3GeqP4uZc以获取将其放置在那里的管道。 - Reed Copsey
我已经创建了一个按钮,所以窗口被创建了,但是它不起作用。private void button1_Click(object sender, RoutedEventArgs e) { Layout layout = new Layout(); layout.Background = Brushes.White; layout.ClipToBounds = true; layout.SnapsToDevicePixels = true; layout.Width = 4965; layout.Height = 3515; AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(layout); adornerLayer.Add(new LayoutAdorner(layout));} - user2296810
是的,这很有帮助,将代码移动到窗口的OnLoaded处理程序中,代码就可以正常工作了。 - Roboblob

0

AdornerLayer.GetAdornerLayer 在可视树向上搜索 AdornerLayer

在构造函数中,可视树尚未组成。您需要将代码放置在 Window.Loaded 事件中。

其他问题:

Layout layout = new Layout();
...
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(layout);

搜索是向上的。但'layout'是顶层的(没有父级)。然后GetAdornerLayer返回null。
要获取窗口的AdornerLayer,需要在Windows中取一个组件(而不是Window,因为Window是顶层的)。我的解决方案是将XAML中的第一个组件命名为'root':
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.root);

编辑:

这个方法可以从某些类型的WPF元素返回装饰层:

//If no adorner layer is found, return null
private static AdornerLayer GetAdornerLayer(Visual visual)
{
        var decorator = visual as AdornerDecorator;
        if (decorator != null)
            return decorator.AdornerLayer;
        var presenter = visual as ScrollContentPresenter;
        if (presenter != null)
            return presenter.AdornerLayer;
        var visualContent = (visual as Window)?.Content as Visual;
        return AdornerLayer.GetAdornerLayer(visualContent ?? visual);
}

你能否在“取组件”的操作上再加些解释?我也遇到了同样的问题。谢谢。 - CyberFox
好的,谢谢你帮了我。所以如果类型推断失败,你只需要请求一个子级,这样GetAdornerLayer()就可以向上搜索。只是为了做一点修正,你有一个多余的变量"window1"。 - CyberFox

0

在表单刷新后,调用Content.UpdateLayout()以确保Content的所有可视子元素都已正确更新布局。MSDN官方

(我不是很聪明,我只是从这里复制了解决方案):{{link2:AdornerLayer.GetAdornerLayer()返回Panel中所有控件的NULL值}}。


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