6

I have a problem with

AdornerLayer AdornerLayer = AdornerLayer.GetAdornerLayer (layout);

This method returns always null.

What am I doing wrong?

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

    }
}
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
user2296810
  • 69
  • 1
  • 2

3 Answers3

10

The AdornerLayer for the Window won't be created until the window is actually loaded and the handle is created.

Instead of placing this in the constructor, you may need to delay, and add the adorner when the window is loaded instead.

Reed Copsey
  • 554,122
  • 78
  • 1,158
  • 1,373
  • Thank you for your reply. How do you mean it? – user2296810 Apr 30 '13 at 19:37
  • @user2296810 Move the adorner code into the Loaded event - see http://stackoverflow.com/questions/651013/why-to-run-code-in-method-called-by-xaml-window-loaded for plumbing on getting it there – Reed Copsey Apr 30 '13 at 19:39
  • i have create an Button, so the Window is created but it dosen't work 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 Apr 30 '13 at 19:45
  • Yes this helps, moving code to OnLoaded handler of the windows and code works. – Roboblob Oct 23 '14 at 10:27
0

After the Form is Refreshed, call Content.UpdateLayout(); to Ensures that all visual child elements of the Content were properly updated for layout. MSDN Official

(I'm not so smart, I just copied the solution from here): AdornerLayer.GetAdornerLayer() return NULL for all controls in a Panel

Community
  • 1
  • 1
Fleg
  • 336
  • 4
  • 5
0

AdornerLayer.GetAdornerLayer searches for an AdornerLayer in the visual tree to upward.

In the constructor, the visual tree is not composed. You need put your code in the Window.Loaded event.

Other problem :

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

The search is upward. But the 'layout' is the top (no parent). Then GetAdornerLayer return null.

To get the Window's AdornerLayer, you need take a composant in the Windows (not the Window, because Window it is the top). My solution is name the first composant in XAML 'root' :

AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this.root);

edit :

This method can return the adorner layer from some types of WPF element :

//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);
}
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
vernou
  • 6,818
  • 5
  • 30
  • 58
  • Can you add some more explanation on how to "take a composant"? I'm having same issue. Thanks – CyberFox Aug 11 '17 at 10:08
  • Ok thanks that helped me. So if the type inference fails you simply ask for a child so GetAdornerLayer() can search upwards. Just for a little correction you have a redundant variable "window1". – CyberFox Aug 23 '17 at 01:59