ApplicationModalAdorner GetLayoutClip() InvalidOperationException

У меня есть свой собственный ApplicationModalAdorner. Иногда я получаю InvalidOperationException от GetLayoutClip() который я переопределяю. Призыв к TransformToAncestor вызывает исключение. Я не могу воспроизвести исключение (я часто вижу исключение в журнале). Может быть, окно не полностью отображается? Я ищу репродукцию (возможно, в простом приложении) и причину / решение для этого исключения. Я получаю исключение пару раз в одну и ту же минуту. Я предпочитаю решение без диспетчера.

Соответствующая часть callstack:

Wrapped Exception: System.InvalidOperationException: An exception occured while handling another exception;
   bij System.Windows.Media.Visual.TrySimpleTransformToAncestor(Visual ancestor, Boolean inverse, GeneralTransform& generalTransform, Matrix& simpleTransform)
   bij System.Windows.Media.Visual.TransformToAncestor(Visual ancestor)
   bij x.x.x.ApplicationModalAdorner.WindowRect()
   bij x.x.x.ApplicationModalAdorner.GetLayoutClip(Size layoutSlotSize)
   bij System.Windows.UIElement.ensureClip(Size layoutSlotSize)
   bij System.Windows.UIElement.Arrange(Rect finalRect)
   bij System.Windows.Documents.AdornerLayer.ArrangeOverride(Size finalSize)
   bij System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   bij System.Windows.UIElement.Arrange(Rect finalRect)
   bij System.Windows.Documents.AdornerDecorator.ArrangeOverride(Size finalSize)
   bij System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   bij System.Windows.UIElement.Arrange(Rect finalRect)
   bij System.Windows.Controls.Control.ArrangeOverride(Size arrangeBounds)
   bij System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   bij System.Windows.UIElement.Arrange(Rect finalRect)
   bij MS.Internal.Helper.ArrangeElementWithSingleChild(UIElement element, Size arrangeSize)
   bij System.Windows.Controls.ContentPresenter.ArrangeOverride(Size arrangeSize)
   bij System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   bij System.Windows.UIElement.Arrange(Rect finalRect)
   bij System.Windows.Controls.Grid.ArrangeOverride(Size arrangeSize)
   bij System.Windows.FrameworkElement.ArrangeCore(Rect finalRect)
   bij System.Windows.UIElement.Arrange(Rect finalRect) 

Код

public class ApplicationModalAdorner : Adorner
{
    private SolidColorBrush _brush;

    private XamDialogWindow Window
    {
        get
        {
            return (XamDialogWindow)AdornedElement;
        }
    }

    private Window MainWindow
    {
        get
        {
            if (Application.Current != null)
            {
                return Application.Current.MainWindow;
            }
            return null;
        }
    }

    public ApplicationModalAdorner(UIElement adornedElement)
        : base(adornedElement)
    {
        _brush = (SolidColorBrush)FindResource("ModalBackgroundBrush");

        Window.Moved += WindowMoved;
        Window.WindowStateChanged += WindowStateChanged;
        MainWindow.SizeChanged += MainWindowSizeChanged;
    }

    // There is no WindowClosed event. Infragistics states that when a window is closed,
    // the WindowStateChanged event gets triggerd and the value will be Hidden. Because 
    // the ApplicationModal windows cannot be hidden, this is a nice way to clean events.
    private void WindowStateChanged(object sender, WindowStateChangedEventArgs e)
    {
        if (e.NewWindowState == Infragistics.Controls.Interactions.WindowState.Hidden)
        {
            Window.Moved -= WindowMoved;
            Window.WindowStateChanged -= WindowStateChanged;
            if (MainWindow != null)
            {
                MainWindow.SizeChanged -= MainWindowSizeChanged;
            }
        }
    }

    private void WindowMoved(object sender, MovedEventArgs e)
    {
        InvalidateVisual();
    }

    private void MainWindowSizeChanged(object sender, SizeChangedEventArgs e)
    {
        InvalidateVisual();
    }

    protected override void OnRender(DrawingContext drawingContext)
    {
        drawingContext.DrawRectangle(_brush, null, WindowRect());
        base.OnRender(drawingContext);
    }

    protected override Geometry GetLayoutClip(Size layoutSlotSize)
    {
        var xamDialogWindowRect = new Rect(new Point(Window.Left, Window.Top), layoutSlotSize);
        var geometryGroup = new GeometryGroup();
        geometryGroup.Children.Add(new RectangleGeometry(WindowRect()));
        geometryGroup.Children.Add(new RectangleGeometry(xamDialogWindowRect));
        return geometryGroup;
    }

    private Rect WindowRect()
    {
        var transformToAncestor = Window.TransformToAncestor(MainWindow);
        var topLeft = transformToAncestor.Inverse.Transform(new Point(0, 0));
        var bottomRight = transformToAncestor.Inverse.Transform(new Point(MainWindow.ActualWidth, MainWindow.ActualHeight));
        return new Rect(topLeft, bottomRight);
    }

    public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
    {
        InvalidateVisual();
        return base.GetDesiredTransform(transform);
    }
  }
}

1 ответ

Ваше окно отсутствует в визуальном дереве. У вас есть два варианта:

  1. Слушайте событие Loaded. Затем при загрузке начните прослушивание других событий (Moved, WindowStateChanged, SizeChanged).
  2. При необходимости используйте диспетчер, а затем надейтесь на лучшее.

Что касается вашего запроса на образец приложения, я могу заверить вас, что проблему, которую вы видите, невероятно трудно воспроизвести.

Другие вопросы по тегам