强制渲染 Viewbox 以便在页面上绘制它

Force render Viewbox in order to draw it on page

我正在使用 FlowDocument 创建报告。现在,我创建了一个分页器,以便能够在每个页面上重复 header,但是,它不会在每个页面上呈现。我怀疑问题是 Viewbox 不是 rendered/created 直到你尝试显示它。

这是我的 GetPage 方法:

public override DocumentPage GetPage(int pageNumber) {
        DocumentPage page = m_Paginator.GetPage(pageNumber);

        ContainerVisual newpage = new ContainerVisual();
        DrawingVisual title = new DrawingVisual();
        using (DrawingContext ctx = title.RenderOpen())
        {
            var header = getHeader();
            RenderTargetBitmap bmp = new RenderTargetBitmap(165, 32, 96, 96,
                PixelFormats.Pbgra32);
            bmp.Render(header);
            ctx.DrawImage(bmp,new Rect(new Point(0,0),new Size(166, 33)));
        }
        ContainerVisual smallerPage = new ContainerVisual();
        title.Children.Add(getHeader());

        newpage.Children.Add(title);
        smallerPage.Children.Add(page.Visual);
        smallerPage.Transform = new MatrixTransform(0.95, 0, 0, 0.95, 0.025 * page.ContentBox.Width, 0.025 * page.ContentBox.Height);

        newpage.Children.Add(smallerPage);
        newpage.Transform = new TranslateTransform(m_Margin.Width, m_Margin.Height);
        return new DocumentPage(newpage, m_PageSize, Move(page.BleedBox), Move(page.ContentBox));
    }

这是移动方法:

Rect Move(Rect rect) {

        if (rect.IsEmpty) {
            return rect;
        }

        else {
            return new Rect(rect.Left + m_Margin.Width, rect.Top + m_Margin.Height,
                            rect.Width, rect.Height);
        }
    }

这是 getHeader()(是的,我知道,它应该是 GetHeader() - 它们的约定)

private Viewbox getHeader() {
        Grid gr = new Grid();
        var sr = Application.GetResourceStream(new Uri("Propuestas;component/img/log.xaml", UriKind.Relative));

        var img = (Canvas)XamlReader.Load(new XmlTextReader(sr.Stream));

        var logo = new Viewbox {
            Child = img,
            HorizontalAlignment = HorizontalAlignment.Left,
            VerticalAlignment = VerticalAlignment.Center,
            Width = 165
        };
        var detalles = new TextBlock {
            FontSize = 10,
            FontFamily = new FontFamily("Verdana"),
            Padding = new Thickness(logo.Width + 15, 0, 0, 0)
        };
        App.Comando.CommandText = "SELECT RazEmp, DirEmp, CpEmp, PobEmp, ProEmp, TelEmp, CifEmp FROM META4.Empresa";
        using (var reader = App.Comando.ExecuteReader())
            while (reader.Read())
                detalles.Text = "" + reader.GetString(0).Trim() + "\n" + reader.GetString(1).Trim() + "\n" +
                                reader.GetDecimal(2) + " - " + reader.GetString(3).Trim() + "(" +
                                reader.GetString(4).Trim() + ")\n" + "Tlf: " + reader.GetString(5).Trim() +
                                "\nCIF: " + reader.GetString(6).Trim();

        var pd = new TextBox {
            Text = "PEDIDO DE COMPRA",
            TextAlignment = TextAlignment.Left,
            FontSize = 19,
            FontFamily = new FontFamily("Verdana"),
            FontWeight = FontWeights.Bold,
            Background = new SolidColorBrush(Color.FromRgb(192, 192, 192)),
            Margin = new Thickness(logo.Width + 15, 10, 0, 20),
            BorderThickness = new Thickness(0)
        };
        gr.ColumnDefinitions.Add(new ColumnDefinition());
        gr.ColumnDefinitions.Add(new ColumnDefinition());
        gr.RowDefinitions.Add(new RowDefinition());
        gr.RowDefinitions.Add(new RowDefinition());
        Grid.SetRow(logo, 0);
        Grid.SetRow(detalles, 0);
        Grid.SetRow(pd, 1);
        Grid.SetColumn(pd, 0);
        Grid.SetColumnSpan(pd, 2);
        Grid.SetColumnSpan(detalles, 2);

        gr.Children.Add(logo);
        gr.Children.Add(detalles);
        gr.Children.Add(pd);
        Viewbox vb = new Viewbox();
        vb.Child = gr;
        return vb;
    }

但是,当我点击打印时,它会正常打印,不会重复 header。我可以在调试中看到查询 运行,所以 addHeader() 被执行。宽度和高度是预先确定和固定的。 header.Width/header.Height 和 header.ActualWidth/header.ActualHeight 都给我 0 或 NaN,这让我相信视图框没有在后台呈现。有什么方法可以让我在每一页上重复这个吗?

问题是我的 header 包含一张图片和两部分文本。我已经将它创建为仅放在第一页上,但现在要求已经改变,我必须在每一页上重复它。

非常感谢任何帮助。

后来编辑:也试过这个,也没用。

private static BitmapSource CaptureScreen(Visual target, double dpiX, double dpiY) {
        if (target == null)
            return null;
        Size size = new Size(165, 31.536);
        RenderTargetBitmap rtb = new RenderTargetBitmap((int)(size.Width * dpiX / 96.0),
                                                    (int)(size.Height * dpiY / 96.0),
                                                    dpiX,
                                                    dpiY,
                                                    PixelFormats.Pbgra32);
        DrawingVisual dv = new DrawingVisual();
        using (DrawingContext ctx = dv.RenderOpen()) {
            VisualBrush vb = new VisualBrush(target);
            ctx.DrawRectangle(vb, null, new Rect(new Point(), size));
        }

        rtb.Render(dv);
        return rtb;
    }

通过添加

修复
        vb.Measure(new System.Windows.Size(headerWidth, headerHeight));
        vb.Arrange(new Rect(15,15,headerWidth,headerHeight));
        vb.UpdateLayout();

到 getHeader 方法。现在看起来像这样:

private Viewbox getHeader() {
        Grid gr = new Grid();
        var sr = Application.GetResourceStream(new Uri("Propuestas;component/img/log.xaml", UriKind.Relative));

        var img = (Canvas)XamlReader.Load(new XmlTextReader(sr.Stream));

        var logo = new Viewbox {
            Child = img,
            HorizontalAlignment = HorizontalAlignment.Left,
            VerticalAlignment = VerticalAlignment.Center,
            Width = 165
        };
        var detalles = new TextBlock {
            FontSize = 10,
            FontFamily = new FontFamily("Verdana"),
            Padding = new Thickness(logo.Width + 15, 0, 0, 0)
        };
        App.Comando.CommandText = "SELECT RazEmp, DirEmp, CpEmp, PobEmp, ProEmp, TelEmp, CifEmp FROM META4.Empresa";
        using (var reader = App.Comando.ExecuteReader())
            while (reader.Read())
                detalles.Text = "" + reader.GetString(0).Trim() + "\n" + reader.GetString(1).Trim() + "\n" +
                                reader.GetDecimal(2) + " - " + reader.GetString(3).Trim() + "(" +
                                reader.GetString(4).Trim() + ")\n" + "Tlf: " + reader.GetString(5).Trim() +
                                "\nCIF: " + reader.GetString(6).Trim();

        var pd = new TextBox {
            Text = "PEDIDO DE COMPRA " + numPCO,
            TextAlignment = TextAlignment.Left,
            FontSize = 19,
            FontFamily = new FontFamily("Verdana"),
            FontWeight = FontWeights.Bold,
            Background = new SolidColorBrush(Color.FromRgb(192, 192, 192)),
            Margin = new Thickness(logo.Width + 15, 10, 0, 20),
            BorderThickness = new Thickness(0)
        };
        gr.ColumnDefinitions.Add(new ColumnDefinition());
        gr.ColumnDefinitions.Add(new ColumnDefinition());
        gr.RowDefinitions.Add(new RowDefinition());
        gr.RowDefinitions.Add(new RowDefinition());
        Grid.SetRow(logo, 0);
        Grid.SetRow(detalles, 0);
        Grid.SetRow(pd, 1);
        Grid.SetColumn(pd, 0);
        Grid.SetColumnSpan(pd, 2);
        Grid.SetColumnSpan(detalles, 2);

        gr.Children.Add(logo);
        gr.Children.Add(detalles);
        gr.Children.Add(pd);
        Viewbox vb = new Viewbox();
        vb.Child = gr;
        vb.Measure(new System.Windows.Size(headerWidth, headerHeight));
        vb.Arrange(new Rect(15,15,headerWidth,headerHeight));
        vb.UpdateLayout();
        return vb;
    }