Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Appropriate way to force loading of a WPF Visual

I have been struggling with printing using the System.Printing namespace. I have finally figured out that the reason I was getting blank results when using portions of the API was because the Visual objects I was trying to print were not Loaded/Initialized. If I display the Visual objects by putting them in an appropriately-sized Windows and calling Show() prior to printing, I then get the expected results.

Thus, the workaround I came up with was to call this method for every Visual

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


This seems like a hack, especially since the user briefly sees the Window-frame draw. I figure there must be a different way it is supposed to be done. However, I am not turning up any other solutions. Is using a hidden Window really what is supposed to be done here?

Using a MenuItem as described at WPF - Get size of UIElement in Memory? does not work. I looked at Force rendering of a WPF control in memory but I am not really wanting to render the Visual to a bitmap which seems to be what that is for. Calling ApplyTemplate() on the Image that as described in wpf force to build visual tree did not help.


EDIT: This is the solution that is used instead of ShowVisual from above

/// <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));
}
like image 842
vossad01 Avatar asked Apr 25 '13 21:04

vossad01


3 Answers

I had the same issue. Solved by ApplyTemplate().

It force to builds visual tree of an Framework element.

like image 153
ITSGuru Avatar answered Nov 14 '22 16:11

ITSGuru


The items you want to print need to be added to the visual tree in WPF in order for the Measure and Arrange processes to be called on all the elements in the visual tree you want to show / print or otherwise display.

I haven't done this for a while but you may find that adding these items to a ViewPort in the background and then printing them solves the issue. This should get around the need for actually displaying them on the screen and thus the user seeing them whilst also forcing the Measure / Arrange processes.

like image 36
Jammer Avatar answered Nov 14 '22 17:11

Jammer


I had the same problem. In my case I only call: Visual.UpdateLayout() before trying to work with it. As said by Jammer, it will automatically force Measure / Arrange processes.

I did it on window. If you have any problem, you probably should set the Visual Height and Width before call UpdateLayout().

Eric

like image 4
Eric Ouellet Avatar answered Nov 14 '22 17:11

Eric Ouellet