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 ответ
Ваше окно отсутствует в визуальном дереве. У вас есть два варианта:
- Слушайте событие Loaded. Затем при загрузке начните прослушивание других событий (Moved, WindowStateChanged, SizeChanged).
- При необходимости используйте диспетчер, а затем надейтесь на лучшее.
Что касается вашего запроса на образец приложения, я могу заверить вас, что проблему, которую вы видите, невероятно трудно воспроизвести.