Creating Drop Shadows in Silverlight Using Nested Borders

While trying to create drop shadows is Silverlight 2.0, I came across the following blog by Pete Brown. He did a great job of showing how to create drop shadows using borders in Silverlight. Unfortunately though, the method he used was not suitable for my situation. I needed to create drop shadows around objects that were created dynamically and the width and height were not known at design time. I also needed to be able to correctly nest the content within the borders. When I tried to nest the borders, I quickly realized that the Opacity property that is set on each border affects the transparency of all the content within the border (which makes sense). So if the outer border has an opacity value of 0.1, all content within the border will be almost invisible.

Using the same basic approach taken by Pete Brown, I was able to achieve the same effect using nested borders and without needing to set the width and height at design time.

The following code shows how to create the same drop effect with nested borders.



<Border CornerRadius="13" BorderThickness="1" BorderBrush="#19000000"
VerticalAlignment="Center" HorizontalAlignment="Center">
<Border CornerRadius="12" BorderThickness="1" BorderBrush="#33000000">
<Border CornerRadius="11" BorderThickness="1" BorderBrush="#66000000">
<Border CornerRadius="10" BorderThickness="1" BorderBrush="#80000000">

<TextBlock Text="Some content with dynamic width and height" Margin="10" />

</Border>
</Border>
</Border>
</Border>





Result:



For my situation, I was creating the following menu control which contains different items depending on its context.



As you can see from the code, instead of setting the Opacity property of the border control, the opacity is set using the BorderBrush property. The first two numbers of the Hex value represents the opacity of the stroke while the last 6 numbers sets the color of the stroke. In the above example, all the border colors are set to black (000000) but they each have varying degrees of transparency (#19 => 0.1, #33 => 0.2, #66 => 0.4, #80 => 0.5). Also, any content that is created inside of the inner border will force the border to size itself appropriately. And if you wanted to explicitly set the width or height, you only need to set the value on one of the borders and the others will correctly resize, which makes maintaining the size much easier.

It’s also worth mentioning that by default, the VerticalAlignment and HorizontalAlignment properties are set to stretch. This means that the border will occupy the entire space of its parent element. In the above example, setting those properties to “Center” causes to border to shrink down to the smallest possibly size and will be centered within the parent element. If you require the border to occupy the entire space of the parent, remove those two properties on the outer border or just set them to “Stretch”.

4 comments:

Tan Silliksaar said...

Very cool!
I made one addition: by setting thinner borders on left/top and thicker on right/bottom this looks more like a drop shadow.

Eugenio said...

Excellent, simple and clean.

Anonymous said...

Good blog but I would not call it simple or clean. Nothing to do with the blogger, just dissapointing that there is no dropshadow/glow functionality built in.

Thanks for the work around, unfortunately too much xaml to be worth it.

Jim Wightman said...

Well, to be fair, it isn't _that_ much XAML...

And the effect looks great.

Jim

http://hcug.groups.live.com