Maybe you heard that PixelShaders are a feature of Silverlight 3 … which is coming our way very soon.
Maybe you’re like I was, thinking that PixelShaders have no place in a business application. Hey, I love those rippling water demos as much as the next guy. But I’ll be looking for new employment the morning after I give my application a psychedelic makeover.
Then my buddy Joe Gershgorin introduced me to the “Grayscale Effect”, a PixelShader effect that de-saturates the colors of the targeted image, “graying” it out.
You say “So what?”
Here’s a hint: What’s the look of a disabled button? It’s gray.
I used to have one image for the active button state and another image for the disabled button state. If I’ve got 10 buttons, that’s 20 images to maintain. That’s double the payload winging over the wire to my Silverlight client.
It takes time (and skills I lack) to produce the first image; adding a disabled version is another step I can do without.
Now, instead of swapping button images when the enabled state changes, I add or remove the grayscale effect.
I’m not sure where Joe found the code for this effect. The first mention I can find is a blog post by Anders Bursjöö from June 2008. I don’t know if Anders post was first; I can confirm that it will take you through the details of the effect as it relates to WPF … which details are the same for Silverlight.
There is no need for me to repeat what Anders had to say or the many who followed him and took their turns at explaining it. I can also recommend Greg Schechter’s series of May 2008 posts on custom GPU-based effects for WPF.
Now put that knowledge to good use by shedding image bloat and waste your creativity on some other project.
Oh … you wanted code?
Dude ... it's XAML. We'll be here all day.
Ok, here are two snippets for your delectation. Imagine we're inside ResourceDictionary defining a style for the button.
Here is the image definition that will use template binding to pick up the image assigned to the button:
Notice how we added the effect, setting the DesaturationFactor to one (meaning … ahem … no desaturation). GrayScaleEffect is the class straight from Anders example.
Now let's look at the pertinent "Disabled" state governed by the VisualStateManager:
<DiscreteDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
Notice how we’re identifying the effect and its DesaturationFactor property using attached property syntax. Setting the factor to zero results in the gray effect. We’re not using animation so the duration is zero-time.
Wouldn’t it be great if there were a one-liner to specify a no-animation Storyboard or just to skip the Storyboard altogether? Maybe someday.