Соответствующий способ принудительной загрузки WPF Visual

Я боролся с печатью, используя пространство имен System.Printing. Я, наконец, понял, что причина, по которой я получал пустые результаты при использовании частей API, заключалась в том, что объекты Visual, которые я пытался печать не была загружена/инициализирована. Если я покажу объекты Visual, поставив их в размер Window соответствующего размера и вызывая Show() до печати, я получаю ожидаемые результаты.

Таким образом, обходной путь, с которым я столкнулся, состоял в том, чтобы вызвать этот метод для каждого Visual

public static void ShowVisual(Visual visual)
{
    Window window = new Window
        {
            Content = visual,
            SizeToContent = SizeToContent.WidthAndHeight,
            Visibility = Visibility.Hidden
        };
    window.Show();
    window.Close();
}


Это кажется взломом, тем более что пользователь ненадолго видит обрамление Window-frame. Я полагаю, что должен быть другой способ, которым это должно быть сделано. Однако я не принимаю никаких других решений. Является ли использование скрытого окна действительно тем, что должно быть сделано здесь?

Использование MenuItem, как описано в WPF - получить размер UIElement в памяти? не работает. Я посмотрел на принудительное рендеринг элемента управления WPF в памяти, но я действительно не хочу визуализировать визуальный образ, который, похоже, является тем, для чего это необходимо. Вызов ApplyTemplate() на Image, который, как описано в wpf force для создания визуального дерева, не помог.


EDIT: Это решение, которое используется вместо ShowVisual сверху

/// <remarks>
/// This method needs to be called in order for 
//  the element to print visibly at the correct size.
/// </remarks>
private static void ArrangeElement(UIElement element)
{
    var box = new Viewbox {Child = element};

    box.Measure(new Size(double.PositiveInfinity, double.PositiveInfinity));
    box.Arrange(new Rect(box.DesiredSize));
}

Ответ 1

Элементы, которые вы хотите распечатать, необходимо добавить в визуальное дерево в WPF для того, чтобы процессы Measure и Arrange вызывались во всех элементах визуального дерева, которое вы хотите отобразить/распечатать или отобразить иначе.

Я не делал этого некоторое время, но вы можете обнаружить, что добавление этих элементов в ViewPort в фоновом режиме, а затем их печать решает проблему. Это должно обойти необходимость фактического отображения их на экране, и, таким образом, пользователь видит их, одновременно заставляя процессы Measure/Arrange.

Ответ 2

У меня была та же проблема. В моем случае я только звоню: Visual.UpdateLayout(), прежде чем пытаться работать с ним. Как сказал Jammer, он автоматически заставит процессы Measure/Arrange.

Я сделал это на окне. Если у вас есть какие-либо проблемы, вероятно, вы должны установить визуальную высоту и ширину перед вызовом UpdateLayout().

Эрик

Ответ 3

У меня была такая же проблема. Решено ApplyTemplate().

Это принудительно создает визуальное дерево элемента Framework.