简体   繁体   中英

Why do I need to call Dispatcher.BeginInvoke() to allow a visual to properly bind before printing?

I have a UserControl with a fixed size of 850x1100 to give me the same aspect ratio as a letter-sized piece of paper. I display this in my window inside a Viewbox , and it acts much like a print preview. The control inherits my window's DataContext, and when it's displayed on the screen, all the bindings work and it looks wonderful.

I've written the code below in my window's code behind (I feel it's a totally view-oriented operation) to attempt to print it. If I execute this code as written, the control prints, but does not appear to be data bound.

private void PrintButton_Click(object sender, RoutedEventArgs e) {
    var dlg = new PrintDialog();
    var result = dlg.ShowDialog();
    if (result == null || !(bool)result)
        return;

    var page = new InspectionFormPrintView { DataContext = this.DataContext };

    page.Measure(new Size(dlg.PrintableAreaWidth, dlg.PrintableAreaHeight));
    page.Arrange(new Rect(new Point(0, 0), page.DesiredSize));

    dlg.PrintVisual(page, "Inspection Form");
}

If I modify the last line in that method to

Dispatcher.BeginInvoke(new Action(() => dlg.PrintVisual(page, "Inspection Form")), DispatcherPriority.ApplicationIdle, null);

it will print just fine. Why is this?

As mentioned by LPL in the comments, this is required because WPF needs to perform the all the data bindings. Since WPF operations are queued on the Dispatcher , you need to queue your print operation to complete after DispatcherPriority.DataBind . Therefore, calling BeginInvoke with DispatcherPriority.Render or lower will give WPF time to process the bindings on the control, so they show up in your printed output.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM