Use WPF to make a download button in C#


This example uses WPF to make a download button similar to the one shown on the C# Helper web site’s blog posts. The following XAML code shows how the program builds the button.

<Window x:Class="howto_download_button.Window1"
    Title="Window1" Height="107" Width="140" Loaded="Window_Loaded"
    <Grid Background="Transparent" Name="grdMain">
        <!-- The button's background -->
        <Ellipse Margin="5" StrokeThickness="5">
                    <GradientStop Color="LightGreen" Offset="0"/>
                    <GradientStop Color="#FF00C000" Offset="1"/>
        <!-- Text -->
        <TextBlock FontFamily="Arial Rounded MT" FontSize="20"
         FontWeight="Bold" Foreground="Black"
         Margin="10" HorizontalAlignment="Center"
        <!-- Highlight -->
        <Ellipse VerticalAlignment="Top"
            Height="30" Margin="20,8,20,0"
            Fill="White" Opacity="0.5">

The program’s window contains a Grid control that contains two Ellipses and a TextBlock. The first Ellipse defines the button’s background. It is filled with a RadialGradientBrush that shades from LightGreen in the center to a darker green around the edges.

The TextBlock displays the text “Download.”

The second Ellipse is white and sits on top of the other controls. It’s positioned so it starts a bit below the top of the button, extends vertically to the middle of the button, and doesn’t cover the entire width of the button. It’s Opacity is 0.5 so it is 50% opaque and the other controls show through.

The result is pretty good considering the button only uses three controls. (Of course it took a lot of fiddling to make the result match the Twitter button reasonably well.)

When it starts, the program uses the following code to save an image of the Grid control into a png file. (This is typical code for saving a control’s image.)

// Save an image of the grid.
private void Window_Loaded(object sender, RoutedEventArgs e)
    // Render the grid.
    RenderTargetBitmap bm = new RenderTargetBitmap(
        (int)grdMain.ActualWidth, (int)grdMain.ActualHeight,
        96, 96, PixelFormats.Default);

    // Save the result into a file.
    using (var fileStream = new FileStream("Download.png",
        BitmapEncoder encoder = new PngBitmapEncoder();

The program creates a RenderTargetBitmap with the same size as the Grid, using 96 pixels per inch resolution, and the default pixel format. It then calls the Grid‘s Render method to make it draw itself (and its contents) onto the RenderTargetBitmap.

Next the program creates a FileStream representing the file that should contain the image. It makes a PngBitmapEncoder to save the image in the png format.

The program then calls the encoder’s Frames.Add method to add a new frame to it. It passes the method a new BitmapFrame generated by the class’s Create method, passing that method the RenderTargetBitmap.

Finally, after it has created the new frame, the program calls the encoder’s Save method.

(If this all seems a annoyingly convoluted, I agree. This is one of my biggest complaints with WPF. Even though .NET programmers have been working with images and saving them into files for years, WPF makes this so much harder. It’s like the WPF designers had never saved an image before. In fact, just about everything is harder. It makes me wonder if the developers who designed WPF had ever programmed in .NET.)

Download Example   Follow me on Twitter   RSS feed

About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in graphics, user interface, wpf, XAML and tagged , , , , , , , , , , , , , , , . Bookmark the permalink.

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.