Skip to content

"The specified Visual is not an ancestor of this Visual" exception in OxySKElement.OnRender()  #1787

@albtaeler

Description

@albtaeler

Description

We use a docking manager in our application. With it it's possible to dock out windows with plots and arrange them on another screens.
With the current oxyplot version and OxyPlot.SkiaSharp.Wpf.PlotView, we get an exception after undocking a window with a plot.

Partial stack-trace:

System.InvalidOperationException
  HResult=0x80131509
  Message=The specified Visual is not an ancestor of this Visual.
  Source=PresentationCore
  StackTrace:
   at System.Windows.Media.Visual.TrySimpleTransformToAncestor(Visual ancestor, Boolean inverse, GeneralTransform& generalTransform, Matrix& simpleTransform)
   at System.Windows.Media.Visual.TransformToAncestor(Visual ancestor)
   at OxyPlot.SkiaSharp.Wpf.OxySKElement.OnRender(DrawingContext drawingContext)
   at System.Windows.UIElement.Arrange(Rect finalRect)
   at System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
   at System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   at System.Windows.UIElement.Arrange(Rect finalRect)
    ...
    [Call Stack Truncated]

  This exception was originally thrown at this call stack:
    System.Windows.Media.Visual.TrySimpleTransformToAncestor(System.Windows.Media.Visual, bool, out System.Windows.Media.GeneralTransform, out System.Windows.Media.Matrix)
    System.Windows.Media.Visual.TransformToAncestor(System.Windows.Media.Visual)
    OxyPlot.SkiaSharp.Wpf.OxySKElement.OnRender(System.Windows.Media.DrawingContext)
    System.Windows.UIElement.Arrange(System.Windows.Rect)
    System.Windows.Controls.Grid.ArrangeOverride(System.Windows.Size)
    System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
    System.Windows.UIElement.Arrange(System.Windows.Rect)
    System.Windows.Controls.Border.ArrangeOverride(System.Windows.Size)
    System.Windows.FrameworkElement.ArrangeCore(System.Windows.Rect)
    System.Windows.UIElement.Arrange(System.Windows.Rect)
    ...
    [Call Stack Truncated]

Steps to reproduce

  1. Use a docking manager like syncfusion DockingManger
  2. Undock the window with the plot, so that the window with the PlotView is no longer a descendant of the MainWindow in the VisualTree .
    VisualTree of the Application with floating window:
    image

Platform: x86 & x64
.NET version: 4.7.2
Latest OxyPlot Version (nuget packages build from develop brunch)

Actual behaviour

The call Window.GetWindow(this) in OxySKElement.OnRender() returns always the MainWindow. I think it uses the logical tree not the visual tree and this.TransformToAncestor() fails, because the MainWindow is actually not an ancestor of the plot in case of a floating window.

Possible Fix

Get the ancestor from the visual tree with a methode like this

private Window GetAncestorWindowFromVisualTree(DependencyObject startElement)
        {
            DependencyObject parent = startElement;
            while (!(parent is Window))
            {
                if (parent == null) { break; }
                parent = VisualTreeHelper.GetParent(parent);
            }
            return parent as Window ?? Window.GetWindow(this);
        }

var visualOffset = this.TransformToAncestor(GetAncestorWindowFromVisualTree(this)).Transform(default);

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions