Sunday, April 20, 2008 1:43 PM szurgot

WPF - Fun with borders (building a playing card)

Two weeks ago, I posted about my Solitaire program with improved WPF animations. I'm still working on code cleanup to release the source, but I'd like to document some cool tricks I learned about Borders that might come in handy.

(As an aside, I said I had an interview. Well, after two cross-country flights, and two grueling rounds of interviews I've been offered a job which I'm going to accept. I'll talk more about that when I can)

All of the cards used in the WPF version of this program were from OpenClipart, including the card backs. I've no problem with the card faces, but I wanted to include several different backs, including the ability to import custom ones. There were a couple of challenges with this. I wanted a rounded corners, a drop shadow, and the ability for the picture to fill the entire inside of the border with it's rounded edges.

The rounded corners were easy enough, just use the CornerRadius property.

<Canvas x:Name="mainCanvas" Background="Green" Width="250" Height="250">
    <Border BorderBrush="White" BorderThickness="5" CornerRadius="15">
    </Border>
</Canvas>


sample1

The drop shadow proved to be a little more difficult, since WPF doesn't provide 3D Borders by default. However, a little searching turned up a method to create the a 3d look for square borders by nesting two borders.  Some experimentation, and I found this would work quite well for a drop shadow.

<Canvas x:Name="mainCanvas" Background="Green" Width="250" Height="250">
    <Border BorderBrush="DarkGray" BorderThickness=".0,.0,2,2" CornerRadius="18">
        <Border BorderBrush="White" BorderThickness="5" CornerRadius="15" >
    </Border>
</Border>
</Canvas>

sample2

Note that you have to set the CornerRadius on the outer Border to a slightly larger value or you get a gap between the outer and the inner border.

Now comes the hard part, getting the image inside the border.

I used the following image, and dropped the <image> tag right into the inner border.

happy sample3

As you can see, it doesn't completely fill the border AND the square corners of the image overlap the rounded corners of the border. Not good. I turns out one more trick is all that's necessary. Instead of putting the image inside the border, you make the image the border of the background. Also, a third nested border gives the black border around the image to give some demarcation to the inner image, and completes the card.

<Canvas x:Name="mainCanvas" Background="Green" Width="250" Height="250">
    <Border BorderBrush="DarkGray" BorderThickness=".0,.0,2,2" CornerRadius="18"
    Height="190" Width="140" Canvas.Top="30" Canvas.Left="55"
    >
        <Border BorderBrush="White" BorderThickness="5" CornerRadius="15" >
            <Border BorderBrush="Black" BorderThickness="1.5" CornerRadius="12">
                <Border.Background>
                <ImageBrush>
                    <ImageBrush.ImageSource>
                        <BitmapImage UriSource="c:\temp\happy.jpg" />
                    </ImageBrush.ImageSource>
                </ImageBrush>
            </Border.Background>
            </Border>
        </Border>
</Border>
</Canvas>

sample4

So there you have it, all the steps to make a card, and hopefully some tricks to add to your bag of tricks.

Filed under:

Comments

# re: WPF - Fun with borders (building a playing card)

Friday, June 13, 2008 12:49 PM by Gary Gealy

I tried adding the followimg to my app, but all I get is a green square with a small white circle in the upper lefthand corner.  Is there some other code that I need?  

<Canvas x:Name="mainCanvas" Background="Green" Width="250" Height="250">

   <Border BorderBrush="DarkGray" BorderThickness=".0,.0,2,2" CornerRadius="18">

       <Border BorderBrush="White" BorderThickness="5" CornerRadius="15" >

   </Border>

</Border>

</Canvas>