Respond to WPF events and save images of WPF in PNG files controls in C#



The example Make a three-dimensional cube that displays different pictures on each side with WPF, XAML, and C# that uses six different images for its sides. This post explains how that program does two other useful things: responding to menu events and saving images in a PNG file.

Responding to WPF Events

There are two ways you can make C# code respond to WPF object events. First, you can use AddHandler. This works just as it does in Windows forms programming. It requires some extra code so it’s not terribly convenient but it is easy.

The second way to make C# code respond to WPF object events is to put the name of the event handler in the XAML code. The following code shows how the example program indicates that the MenuItem named mnuView111 uses the btnView_Click method as the event handler for its Click event.

This isn’t too hard and Visual Studio’s IntelliSense will even help you select an event handler or create a new one. The major drawback to this method is that Expression Blend cannot run the program without the C# code behind. If you try to run the program without the C# code, the program says it can’t find a definition for the btnView_Click event handler. This makes it hard to let different people work on the user interface and the C# code separately, a major goal of WPF.

Still, this isn’t too bug a restriction. For testing purposes you can make stubs of the routines so the interface designer can run the program without the real C# code.

Saving Images

Saving an image isn’t too hard once you know the arcane steps. This example uses the following code to save an image of the three-dimensional cube.

// Save the current image.
private void mnuSave_Click(Object sender, RoutedEventArgs e)
{
// Draw the viewport into a RenderTargetBitmap.
RenderTargetBitmap bm = new RenderTargetBitmap(
(int)dockCube.ActualWidth, (int)dockCube.ActualHeight,
96, 96, PixelFormats.Pbgra32);
bm.Render(dockCube);

// Make a PNG encoder.
PngBitmapEncoder encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bm));

// Save the file.
using (FileStream fs = new FileStream("Saved.png",
FileMode.Create, FileAccess.Write, FileShare.None))
{
encoder.Save(fs);
}

System.Media.SystemSounds.Beep.Play();
}

The code first creates a RenderTargetBitmap on which to draw. It specifies the current actual size of the dockCube control and indicates that the render target should use the Pbgra32 format with 32-bit blue, green, red, and alpha components. The code makes the RenderTargetBitmap render the dockCube control onto itself (yes, that seems backward).

Next the code creates a PngBitmapEncoder and adds a new BitmapFrame to the encoder. It opens the output PNG file and makes the encoder save itself into the file.

(This all seems like a huge step backward to me. It works and the code isn’t too long but it’s amazingly non-intuitive.)

One oddity here is that the Viewport3D object doesn’t have a true background so when you draw it you get a black background. To prevent that, the program puts the Viewport3D inside another control that does have a background, in this case the DockPanel named dockCube.

(For some odd reason, the dockCube control wasn’t drawing its whole background so it was displaying a black stripe at the top. I fixed that by placing it inside yet another DockPanel with a white background. If you figure out why that was happening, let me know.


  

This entry was posted in graphics, wpf, XAML. Bookmark the permalink.

4 Responses to Respond to WPF events and save images of WPF in PNG files controls in C#

  1. bhanu Gupta says:

    I am calling this application from ASP.Net application using

     Startup startWpf = new Startup(images);
    Thread worker = new Thread(new ThreadStart(Startup.Main));
    worker.SetApartmentState(ApartmentState.STA);
    worker.Name = "DisplayDialog";
    worker.Start();
    worker.Join(); 

    Its working fine in local but not working after hosting asp.net application in iis and its saving only blank image.

  2. Rod Stephens says:

    Sorry but I haven’t worked with ASP.NET in a really long time so I can’t help with this. You’ll probably have better luck on a discussion board that focuses on ASP.NET such as Microsoft’s ASP.NET forum.

  3. Greg Ables says:

    Rod, I think that this is a better link to the ASP forums:

    ASP.NET Forums

    HTH

  4. Rod Stephens says:

    Thanks, Greg. Good suggestion.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.