示例#1
0
        /// <summary>
        /// This is used to redraw only once instead of on every property change.
        /// </summary>
        internal void ScheduleRedraw()
        {
            if (!_redrawPending) // This ensures that the "BeginInvoke" method is only called once, and it is not called again until its delegate has been executed.
            {
                if (_isLoaded)
                {
                    _redrawPending = true;
                    // We use a dispatcher to avoid redrawing every time that a dependency property is set
                    // (the result is as if we waited for the last property to be set). We use "INTERNAL_DispatcherHelpers.QueueAction"
                    // instead of "Dispatcher.BeginInvoke" because it has better performance than calling Dispatcher.BeginInvoke directly.
                    INTERNAL_DispatcherHelpers.QueueAction(() =>
                    {
                        _redrawPending = false;

                        // We check whether the Shape is visible in the HTML DOM tree, because if the HTML canvas is hidden
                        // (due to a "Dispay:none" on one of the ancestors), we cannot draw on it
                        // (this can be seen by hiding a canvas, drawing, and then showing it: it will appear empty):
                        if (INTERNAL_VisibilityChangedNotifier.IsElementVisible(this))
                        {
                            Redraw();
                        }
                        else
                        {
                            _redrawWhenBecomeVisible = true;
                        }
                    });
                }
            }
        }
        /// <summary>
        /// Determines whether an element is visible on screen, and if it is the foremost element (ie. it is not covered by another element). This is useful for example to hide the TextBox validation tooltips when they become hidden after scrolling (cf. ZenDesk 628).
        /// </summary>
        /// <param name="element">The element to check.</param>
        /// <returns>Returns True if the element is visible on screen and it is the foremost element, False otherwise.</returns>
        internal static bool IsElementVisibleOnScreen(FrameworkElement element)
        {
            // First, verify that the element is in the visual tree:
            if (!element._isLoaded)
            {
                return(false);
            }

            // Then, check whether the element is visible in the DOM tree, regardless of elements that may cover it. This can be false if at least one of the parents has "Visibility=Collapsed".
            if (!INTERNAL_VisibilityChangedNotifier.IsElementVisible(element))
            {
                return(false);
            }

            // Verify that the size of the element can be read:
            Size actualSize = element.INTERNAL_GetActualWidthAndHeight();

            if (double.IsNaN(actualSize.Width) || double.IsNaN(actualSize.Height))
            {
                return(false);
            }

            // Get the bounds of the element:
            Point topLeftCoordinates = INTERNAL_PopupsManager.GetUIElementAbsolutePosition(element);
            Rect  elementBounds      = new Rect(topLeftCoordinates.X, topLeftCoordinates.Y, actualSize.Width, actualSize.Height);

            // Get the bounds of the window:
            Rect windowBounds = Window.Current.Bounds;

            // Verify that the element is at least partially inside the window:
            if (elementBounds.X + elementBounds.Width < 0d ||
                elementBounds.Y + elementBounds.Height < 0d ||
                elementBounds.X > windowBounds.Width ||
                elementBounds.Y > windowBounds.Height)
            {
                return(false);
            }

            // Get the coordinates of the center point:
            Point centerPosition = new Point(elementBounds.X + elementBounds.Width / 2, elementBounds.Y + elementBounds.Height / 2);

            // Do a "HitTest" to verify that there is no element overlapping it:
            var elementAtCenterPosition = VisualTreeHelper.FindElementInHostCoordinates(centerPosition);

            if (elementAtCenterPosition == element)
            {
                return(true);
            }
            else
            {
                return(false);
            }
        }
示例#3
0
        /// <summary>
        /// This is used to redraw only once instead of on every property change.
        /// </summary>
        internal void ScheduleRedraw()
        {
            if (!_redrawPending) // This ensures that the "BeginInvoke" method is only called once, and it is not called again until its delegate has been executed.
            {
                if (INTERNAL_VisualTreeManager.IsElementInVisualTree(this))
                {
                    _redrawPending = true;
                    INTERNAL_DispatcherHelpers.QueueAction(() => // We use a dispatcher to avoid redrawing every time that a dependency property is set (the result is as if we waited for the last property to be set). We use "INTERNAL_DispatcherHelpers.QueueAction" instead of "Dispatcher.BeginInvoke" because it has better performance than calling Dispatcher.BeginInvoke directly.
                    {
                        _redrawPending = false;

                        // We check whether the Shape is visible in the HTML DOM tree, because if the HTML canvas is hidden (due to a "Dispay:none" on one of the ancestors), we cannot draw on it (this can be seen by hiding a canvas, drawing, and then showing it: it will appear empty):
                        if (INTERNAL_VisibilityChangedNotifier.IsElementVisible(this))
                        {
                            Redraw();

                            // Stop listening to the ancestors' Visibility_Changed, if it was listening:
                            if (_isListeningToAncestorsVisibilityChanged)
                            {
                                INTERNAL_VisibilityChangedNotifier.StopListeningToAncestorsVisibilityChanged(this);
                            }
                            _isListeningToAncestorsVisibilityChanged = false;
                        }
                        else
                        {
                            // We listen to the Visibility_Changed event of the ancestors so as try again if a parent becomes visible:
                            if (!_isListeningToAncestorsVisibilityChanged)
                            {
                                _isListeningToAncestorsVisibilityChanged = true;
                                INTERNAL_VisibilityChangedNotifier.StartListeningToAncestorsVisibilityChanged(this,
                                                                                                              () =>
                                {
                                    // Stop listening to the ancestors' Visibility_Changed:
                                    if (_isListeningToAncestorsVisibilityChanged)
                                    {
                                        INTERNAL_VisibilityChangedNotifier.StopListeningToAncestorsVisibilityChanged(this);
                                    }
                                    _isListeningToAncestorsVisibilityChanged = false;

                                    // Try again:
                                    ScheduleRedraw();
                                });
                            }
                        }
                    });
                }
            }
        }