Wpf 为什么我需要调用Dispatcher.BeginInvoke()以允许在打印前正确绑定visual Studio?

Wpf 为什么我需要调用Dispatcher.BeginInvoke()以允许在打印前正确绑定visual Studio?,wpf,data-binding,printing,dispatcher,Wpf,Data Binding,Printing,Dispatcher,我有一个固定大小为850x1100的用户控件,它可以提供与字母大小的纸张相同的纵横比。我在我的窗口中的视图框中显示它,它的作用很像打印预览。该控件继承了我的窗口的DataContext,当它显示在屏幕上时,所有的绑定都能正常工作,看起来非常棒 我已经在窗口的代码隐藏中编写了下面的代码(我觉得这是一个完全面向视图的操作)来尝试打印它。如果我按编写的方式执行此代码,则控件将打印,但似乎没有数据绑定 private void PrintButton_Click(object sender, Route

我有一个固定大小为850x1100的用户控件,它可以提供与字母大小的纸张相同的纵横比。我在我的窗口中的
视图框中显示它,它的作用很像打印预览。该控件继承了我的窗口的DataContext,当它显示在屏幕上时,所有的绑定都能正常工作,看起来非常棒

我已经在窗口的代码隐藏中编写了下面的代码(我觉得这是一个完全面向视图的操作)来尝试打印它。如果我按编写的方式执行此代码,则控件将打印,但似乎没有数据绑定

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");
}
如果我将该方法中的最后一行修改为

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

它可以很好地打印出来。为什么会这样?

正如LPL在评论中提到的,这是必需的,因为WPF需要执行所有数据绑定。由于WPF操作在
Dispatcher
上排队,因此您需要在
DispatcherPriority.DataBind
之后排队完成打印操作。因此,使用
DispatcherPriority.Render
或更低级别调用
BeginInvoke
,将给WPF时间来处理控件上的绑定,因此它们会显示在打印输出中。

我想所有加载了
(枚举值6)或更低版本都可以。我认为使用默认的
DispatcherPriority.Normal
页面布局尚未就绪。您还可以尝试强制使用page.UpdateLayout()而不是page.Measure和page.Arrange。(无法测试,但有一次出现类似问题)。原始的PrintVisual调用无法正常工作,因为UI尚未更新(WPF异步工作)。通过使用调用,用户界面更新后(当应用程序再次空闲时),您的调用将排队并执行,这就是它工作的原因。您所说的“似乎没有数据绑定”是什么意思?当控件打印时,应该有数据的地方(如文本块中)没有数据,使用BooleantVisibilityConverter将可见性绑定到bool属性的项在属性为false时不会崩溃,等等。