WPF ToolTip Drop Shadows in Windows 8

The standard ToolTip control template for the Windows 8 theme in WPF (‘Aero2’) has no drop shadow, whether or not the HasDropShadow property is set. The background colour and margins are also slightly off compared to the native style.

The following template produces a result that’s closer to the real thing:

You’ll need to add a reference to PresentationFramework.Aero in your project (note the ‘themes’ namespace used in the control template).

Screenshot of Windows 8 Tooltips

The top image shows a standard Windows 8 tooltip, the middle shows the default tooltip appearance for WPF applications running in Windows 8, and the bottom shows a WPF tooltip using the above template. Note that the Win32 and WPF drop shadows are slightly different in appearance. Additionally, the WPF shadow fades in and out with the tooltip, while the Win32 shadow just pops in and out.

Now, you’ll only want to use this template when the user is running Windows 8, and if the user changes themes you’ll no longer have tooltips that match the native style.

WPF: Using System Colours in Animations

WPF provides access to the Windows system colours through the System.Windows.SystemColors class. As the MSDN documentation indicates, it’s possible to bind to these colours dynamically using the *Key resources, so when the system colours change, so will the appearance of your application.

This code will set the colour of a TextBlock to the ‘GrayText’ system colour, and will change automatically if the user switches themes:

In many cases, there’s no reason not to bind dynamically. Problems arise with animations, however. From MSDN:

You can’t use dynamic resource references or data binding expressions to set Storyboard or animation property values. That’s because everything inside a ControlTemplate must be thread-safe, and the timing system must Freeze Storyboard objects to make them thread-safe. A Storyboard cannot be frozen if it or its child timelines contain dynamic resource references or data binding expressions.

This means that you’re stuck using static references to system colours in your animation storyboards – if the user changes the system colours while your application is running, your storyboards won’t update automatically. Worst-case scenario, you might end up with unreadable text.

I don’t think there are any workarounds that don’t involve reloading windows and/or resource dictionaries (depending on where the style code is located). Reloading a window is easy enough – just be careful if you’re closing your application’s last window: the program will shut down if there are no remaining references to any windows.

The method for reloading a resource dictionary is a bit less obvious. It seems that XAML files accessed by their pack URIs are already compiled, so the system colours will be fixed in place once the program starts up. To get around this, change the build action for the XAML file containing the resource dictionary to ‘Embedded Resource’. You can then (re)build the resource dictionary as you please using XamlReader:

Remove the old resource dictionary from your application’s merged resource dictionaries, then add the new one.

Creating a new resource dictionary like this seems to be fairly slow, so try to avoid doing it on a regular basis. To tell when the Windows theme or system colours have changed, you’ll need to listen for the window messages WM_THEMECHANGED and WM_SYSCOLORCHANGE. See this post for information about listening for window messages in WPF.