Search code examples
c#wpfimagepixelsensescatterview

Print a WPF control to an Image control


I'm writing an application for the surface that requires displaying data in a table (i.e. DataGrid). This is great, except the table captures the touch interactions for the ScatterViewItem control (basically a panel that can be spun, shrunk, and moved by the user). This prevents the user from easily manipulating the ScatterViewItem.

To solve this problem, I thought it would be easy to draw the control to an image and just put that up. It seems I was wrong. Here are all my attempts:

http://pastie.org/private/gfkkv9f6apgrqi1ucspwpa (no need to read this, unless you think it will be useful. That's why it's in pastie and not on here)

I'm putting the DataGrid inside of another Grid, because otherwise it won't measure properly:

Grid g = new Grid();
g.Children.Add(dataTable);

SurfaceScrollViewer viewer = new SurfaceScrollViewer();
viewer.Content = Utility.SaveWPFControlAsImage(g);

If we change that last line to

viewer.Content = g;

We get a good table:

enter image description here

If we don't, we get:

enter image description here

SaveWPFControlAsImage is as follows:

    public static System.Windows.Controls.Image SaveWPFControlAsImage(FrameworkElement e)
    {
        e.Measure(new System.Windows.Size(double.PositiveInfinity, double.PositiveInfinity));

        RenderTargetBitmap targetBitmap =
            new RenderTargetBitmap((int)e.DesiredSize.Width,
                                   (int)e.DesiredSize.Height,
                                   96d, 96d,
                                   PixelFormats.Default);
        targetBitmap.Render(e);

        BmpBitmapEncoder encoder = new BmpBitmapEncoder();
        encoder.Frames.Add(BitmapFrame.Create(targetBitmap));

        MemoryStream stream = new MemoryStream();
        encoder.Save(stream);
        BitmapImage bmp = new BitmapImage();
        bmp.BeginInit();
        bmp.StreamSource = new MemoryStream(stream.ToArray());
        bmp.EndInit();

        return new System.Windows.Controls.Image()
        {
            Source = bmp,
        };
    }

So maybe I'm just not rendering it right, or, maybe, I'm just going about this at the wrong angle...


Solution

  • In WPF you have a VisualBrush which allows you to capture a live preview of a given control. Also if you don't want any input of a given control, you can always set IsHitTestVisible="False".