This blog post reviews how to create drop shadows around WPF elements in a way which does not have a noticeable impact on an application’s UI performance.
One of the biggest letdowns about the first version of WPF is the fact that bitmap effects are so terribly slow. The most commonly used bitmap effect is the one which creates a drop shadow around an element; the DropShadowBitmapEffect. If you start using that class to create drop shadows you will soon find your UI performance suffering immensely. This is a shame considering how visually appealing a well-placed drop shadow can be.
Here is a screenshot which shows a ListBox with a drop shadow. The drop shadow was created by adding a DropShadowBitmapEffect to the ListBox’s BitmapEffects collection.
If you were to repeatedly resize that Window, you would find that the rendering of the ListBox flickers and is slow. Why? The problem is that bitmap effects are not hardware accelerated, and they can execute quite often. WPF’s support for bitmap effects requires them to be created in unmanaged code (usually C++). There is currently no way to hardware accelerate those unmanaged routines. I suppose it is possible to write your own bitmap effects which run themselves on a graphics card’s GPU, but that is way beyond the scope of this post!!
Fortunately there is an easy way to create drop shadows around WPF elements which does not incur any noticeable performance overhead. The trick is to decorate an element with a SystemDropShadowChrome element. SystemDropShadowChrome does not have nearly as many settings that you can adjust, but it provides a decent drop shadow for many situations. Here’s a screenshot of a ListBox which is decorated with that element:
SystemDropShadowChrome lives in an obscure assembly and namespace. If you want to use it, you must add a reference to one of the PresentationFramework.* assemblies (there are currently .Aero, .Luna, .Royale, and .Classic). You will find the class in the Microsoft.Windows.Themes namespace.
Each of the PresentationFramework.* assemblies has its own version of the SystemDropShadowChrome class, but after checking them out in Reflector I found out that they are all exactly the same. Someone must have written the class once, and then pasted it into each of those assemblies. So, there is no need to worry about choosing the “right” class to use at runtime, based on the user’s current operating system theme settings. Any one of them will do.
In this post’s demo application I chose to reference the PresentationFramework.Aero assembly, as seen below:
Once you have the assembly reference in place, you need to map the Microsoft.Windows.Themes namespace in your XAML file, like this:
At that point, it’s simply a matter of wrapping an element in a SystemDropShadowChrome element, and perhaps setting its Color and/or CornerRadius properties. Here is the XAML which does this in the demo project:
To read another perspective on the SystemDropShadowChrome class, read here.
Download the demo project here: Lightweight DropShadows (demo project) Be sure to change the file extension from .DOC to .ZIP and then decompress it.