В WPF, при каких обстоятельствах делает Визуальный. PointFromScreen бросают InvalidOperationException?

Предположим, что я хотел сделать это, таким образом, я могу найти текущую позицию мыши относительно a Visual, не нуждаясь в доступе к определенному событию от нажатия мыши:

public static Point GetMousePosition(this Visual relativeTo)
{
    return relativeTo.PointFromScreen(GetMousePositionOnScreen());
}

Иногда (обычно, когда я только что переключился между двумя средствами управления вкладкой), PointFromScreen броски InvalidOperationException с сообщением Это Визуальное не подключено к PresentationSource.

При рассмотрении свойств, доступных на Visual Я не вижу, что любой касается a PresentationSource.

Данный a Visual, как я могу сказать, собирается ли это выдать то исключение, когда я звоню PointFromScreen на нем?

15
задан Daniel Earwicker 28 January 2010 в 11:50
поделиться

2 ответа

Существует статический метод Председания. Известный , который:

возвращает источник, в котором представлен прилагаемый визуальный вариант.

Я знаю, что это не решает базовую проблему, но вы могли бы проверить, что визуальный вариант подключен к представлению до вызова PointFromscreen . Это предотвратит исключение, но вам нужно было сделать еще несколько расследований по отношению к тому, почему он не был связан в первую очередь.

24
ответ дан 1 December 2019 в 01:23
поделиться

У меня была аналогичная проблема с созданным на заказ визуалом.

Решением было отложить проблемную задачу через Dispatcher (в данном случае отложенное выполнение с приоритетом фона) ...

public void MyProblematicDisplayMethod(Symbol TargetSymbol)
{
    this.HostingScrollViewer.BringIntoView(TargetSymbol.HeadingContentArea);
    ...
    // This post-call is needed due to WPF tricky rendering precedence (or whatever it is!).
    this.HostingScrollViewer.PostCall(
        (scrollviewer) =>
        {
            // in this case the "scrollviewer" lambda parameter is not needed
            var Location = TargetSymbol.Graphic.PointToScreen(new Point(TargetSymbol.HeadingContentArea.Left, TargetSymbol.HeadingContentArea.Top));
            ShowOnTop(this.EditBox, Location);
            this.EditBox.SelectAll();
        });
     ...
}

/// <summary>
/// Calls, for this Source object thread-dispatcher, the supplied operation with background priority (plus passing the source to the operation).
/// </summary>
public static void PostCall<TSource>(this TSource Source, Action<TSource> Operation) where TSource : DispatcherObject
{
    Source.Dispatcher.BeginInvoke(DispatcherPriority.Background,
        new DispatcherOperationCallback(delegate(Object state)
                                        { Operation(Source); return null; }),
        null);
}

Я использовал этот PostCall в других ситуациях рендеринга, связанных с ScrollViewer.

4
ответ дан 1 December 2019 в 01:23
поделиться
Другие вопросы по тегам:

Похожие вопросы: