tags:

views:

181

answers:

1

I'm currently trying to persist a canvas to a bitmap, and I've run into some very peculiar behavior. The source code for the 3 following cases appears at the end of the post.

Case 1: A red rectangle appears in the output file (test.png), as expected.

Case 2: No red rectangle appears in the output file.

Case 3: No red rectangle appears in the output file.

It seems that adding the rectangle to the canvas (even though that canvas is never used to render the rectangle to disk) is necessary. It also seems that the button click must initiate the drawing - that it can't occur in the Window constructor. Neither of these makes sense to me, and I assume I'm misunderstanding something.

Also, I apologize in advance for the bad code formatting. I wrestled with it for 20 minutes, but now I'm giving up.

Thanks in advance,

-- Breck Fresen

The XAML used for all 3 cases:

<Window x:Class="ScanOutlineCreator.Window1"   
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"   
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
    Title="Window1" Height="250" Width="250">  
        <Grid>  
            <Grid.RowDefinitions>  
                <RowDefinition Height="20" />  
                <RowDefinition />  
            </Grid.RowDefinitions>  
            <Button x:Name="btnGo" Grid.Row="0">  
                <TextBlock Text="Go" />  
            </Button>  
            <Canvas Grid.Row="1" x:Name="canvas" Width="200" Height="500"></Canvas>  
        </Grid>  
</Window>

Case 1:

using System.IO;  
using System.Windows;  
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Shapes;  
using Common.Drawing;  
namespace ScanOutlineCreator  
{  
        public partial class Window1  
        {  
                static Rectangle r = new Rectangle { Width = 100, Height = 100, Fill = Brushes.Red };  
                public Window1()  
                {  
                        InitializeComponent();  
                        btnGo.Click += new RoutedEventHandler(btnGo_Click);  
                        canvas.Children.Add(r);  
                }  

                static void btnGo_Click(object sender, RoutedEventArgs e)  
                {  
                        using (Stream stm = File.Create("test.png"))  
                        {  
                                RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);  
                                rtb.Render(r);  
                                Util.RenderTargetBitmapToStream(rtb, stm);  
                        }  
                }  
        }  
}  

Case 2:

using System.IO;  
using System.Windows;   
using System.Windows.Media;   
using System.Windows.Media.Imaging;   
using System.Windows.Shapes;   
using Common.Drawing;

namespace ScanOutlineCreator     
{     
    public partial class Window1   
    {   
        static Rectangle r = new Rectangle { Width = 100, Height = 100, Fill = Brushes.Red };  
        public Window1()   
        {   
            InitializeComponent();   
            btnGo.Click += new RoutedEventHandler(btnGo_Click);   
        }  

        static void btnGo_Click(object sender, RoutedEventArgs e)   
        {   
            using (Stream stm = File.Create("test.png"))   
            {   
                RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);   
                rtb.Render(r);   
                Util.RenderTargetBitmapToStream(rtb, stm);   
            }   
        }   
    }   
}   

Case 3:

using System.IO;   
using System.Windows.Media;  
using System.Windows.Media.Imaging;  
using System.Windows.Shapes;  
using Common.Drawing;  
namespace ScanOutlineCreator  
{  
    public partial class Window1  
    {  
        static Rectangle r = new Rectangle { Width = 100, Height = 100, Fill = Brushes.Red };  
        public Window1()
        {  
            InitializeComponent();  
            canvas.Children.Add(r);  
            using (Stream stm = File.Create("test.png"))  
            {  
                RenderTargetBitmap rtb = new RenderTargetBitmap(100, 100, 96, 96, PixelFormats.Pbgra32);  
                rtb.Render(r);  
                Util.RenderTargetBitmapToStream(rtb, stm);  
            }  
        }  
    } 
}
A: 

This is almost certainly to do with layout. If so its been covered many times before.

After you add the children you have to make sure Layout gets performed before you render, so things are actually in the visual tree in the right location etc.

You probably need to call some combination of Measure/Arrange before rendering.

Schneider
Thank you. Calling Measure didn't change anything but Arrange seemed to do the trick.
Breck Fresen