X Tutup
Skip to content

WPF- OxyPlot doesn't render inside a Popup (fix included) #1796

@Tetedeiench

Description

@Tetedeiench

Doing my best to format it, as I'm not a git expert by any means.

Steps to reproduce

  1. Put a plotview inside a WPF Popup
  2. Display the popup
  3. See a white graph

Platform: Windows
.NET version: 4.6.1 and others

Expected behaviour

The graph should appear normally inside a popup

Actual behaviour

The graph appears Empty

Why does it happen ?

In PlotViewBase , you're checking if the graph is part of the visual tree by checking if the ancestor is a window :

       /// <summary>
        /// Gets a value indicating whether the <see cref="PlotViewBase"/> is connected to the visual tree.
        /// </summary>
        /// <returns><c>true</c> if the PlotViewBase is connected to the visual tree; <c>false</c> otherwise.</returns>
        private bool IsInVisualTree()
        {
            DependencyObject dpObject = this;
            while ((dpObject = VisualTreeHelper.GetParent(dpObject)) != null)
            {
                if (dpObject is Window)
                {
                    return true;
                }
            }

            return false;
        }

In the case of a WPF popup, the ancestor is a Popuproot :
image

The fix

We need to check if the ancestor is also a Popuproot. If so, it's in the visual tree. But as the popuproot is an internal type, you can't check against it easily. The best way I found is to check if the logical parent of the PopupRoot is a Popup :

        /// <summary>
        /// Gets a value indicating whether the <see cref="PlotViewBase"/> is connected to the visual tree.
        /// </summary>
        /// <returns><c>true</c> if the PlotViewBase is connected to the visual tree; <c>false</c> otherwise.</returns>
        private bool IsInVisualTree()
        {
            DependencyObject dpObject = this;
            while ((dpObject = VisualTreeHelper.GetParent(dpObject)) != null)
            {
                if (dpObject is Window)
                {
                    return true;
                }

                //Check if the logical parent is a popup. If so, we found the popuproot
                var logicalRoot = LogicalTreeHelper.GetParent(dpObject);
                if (logicalRoot is Popup)
                {
                    // popup root found here
                    return true;
                }
            }

            return false;
        }

This isn't enough, as in PlotView, you're getting the window parent from the Visual tree using this call :

        /// <summary>
        /// Returns a reference to the window object that hosts the dependency object in the visual tree.
        /// </summary>
        /// <returns> The host window from the visual tree.</returns>
        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);
        }

I find this Window check superfluous, as if you're there, you have already checked you're in the visual tree. You can thus just walk the visual tree and get the root here, no check needed, and you only need a Visual type in the call, not a Window type :

        private Visual GetAncestorVisualFromVisualTree(DependencyObject startElement)
        {
            
            DependencyObject child = startElement;
            DependencyObject parent = VisualTreeHelper.GetParent(child);
            while (parent != null)
            {
                child = parent;
                parent = VisualTreeHelper.GetParent(child);
            }

            return child is Visual visualChild ? visualChild : Window.GetWindow(this);
        }

This makes Oxyplot work flawlessly in a popup.

Feel free to correct me and point any mistakes !

Following writing all this, I'll try to a PR - not sure I'll succeed though :D

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

      X Tutup