This article describes how to build a Flexible Surface Effect for Silverlight 4. You can view an example and download the sourcecode at the Expression Gallery. This effect allows a user to click on the UI as if he taps with his finger on surface water. Since there is a RippleEffect for Silverlight 4 the implementation is quite straightforward. And the result is pretty scalable.
How it works
The basic idea is using a regular Silverlight 4 RippleEffect. For the purpose of demonstration a RippleEffect is added to the LayoutRoot. The Flexible Surface Effect itself is going to be achieved through a StoryBoard in which the values of the RippleEffect are changed over the timeline. A Rectangle as a layer above the LayoutRoot reacts on the MouseLeftButtonDown event, catches the mouse position and passes it to the center value of the RippleEffect that is attached to the LayoutRoot.
Step By Step
Using Expression Blend 4 RC we will build a sample application step by step. The sample app we will create in this article is build from scratch and different from my contribution at the Expression Gallery. But the principles of the implementation are the same. You can download the sourcecode for this sample here, but I recommend to download the sourcecode at the Expression Gallery additionally. (Even if you only download the sourcecode here from my blog you would make me happy if you vote for it at the Expression Gallery and give me some stars if you like it. Your stars are my payment because programming is only a pastime to me.)
Step 1
In a new Silverlight 4 project add a RippleEffect to the LayoutRoot. Name it myRipple.
We attach the RippleEffect to the LayoutRoot only for the purpose of demonstration. Attaching it to LayoutRoot makes the whole UI of the Silverlight 4 app flexible because the RippleEffect then affects every child element of the LayoutRoot element. But in general you can attach it to a UI element of your choice, e.g. only to a single and separated Grid element to affect only the child elements of that Grid.
Step 2
To prepare our layout we set the Width and the Height of the UserControl to Auto and its HorizontalAlignment and VerticalAlignment both to Stretch. Then we define a various number of Rows and Columns in the LayoutRoot. To visualize the effect we set ShowGridLines to True so that our UI looks like this at runtime:

Step 3
Then we create a StoryBoard in which we animate the UI through changing the values of the RippleEffect which is attached to LayoutRoot.
Before that we configure the initial values of the RippleEffect myRipple as follows:
Set Frequency to value 30.
Set Magnitude to value 0.
Set Phase to value 0.
We can ignore the X and Y values of the center property of myRipple because we will modify them in the code behind.
In Blend 4 Press F6 to go to the animation workspace. In the Object and Timeline panel click New Storyboard …

… and name it sbClickRipple.

Set the Timeline zoom to 500% for a more detailed view on the TimeLine.

Select the RippleEffect in the Object and Timeline panel and add a first keyframe at timeline position 0:00,000.

Then add another keyframe at timeline position 0:00,100 …

… and change the Magnitude value of the RippleEffect to 0,02.

Finally we add a third keyframe at timeline position 0:01,100 …

… and set the Frequency and Magnitude value of the RippleEffect each to 0.

At this point you can already take a sneak preview on the effect at design time through clicking the Play button in the Timeline.

Step 4
In the next step we want to achieve that the UI reacts on MouseLeftButtonUp event and furthermore that the center of the wave which is produced by the RippleEffect is always exactly at the mouse click position.
Therefore at first add a Rectangle to the LayoutRoot which will be used as a layer that will catch the MouseLeftButtonDown event. Name the Rectangle rClick and set its HorizontalAlignment and VerticalAlignment both to Stretch and Width and Height both to Auto. Set the Opacity to 1% and the Stroke to No Brush. Here is the XAML of the Rectangle rClick.
<Rectangle x:Name="rClick"
Grid.ColumnSpan="27"
Fill="White"
Grid.RowSpan="17"
Opacity="0.01"/>
Now we are ready for some code behind in Visual Studio 2010 (currently I am using Visual Web Developer 2010 Express).
In the code behind of our MainPage add an event handler for the MouseLeftButtonDown event of the Rectangle rClick. Insert the following code snippet (VB.NET).
VB.NET
Private Sub rClick_MouseLeftButtonDown _
(
ByVal sender As Object,
ByVal e As System.Windows.Input.MouseButtonEventArgs
) _
Handles rClick.MouseLeftButtonDown
Dim CP As Point = e.GetPosition(rClick)
CP.X /= rClick.ActualWidth
CP.Y /= rClick.ActualHeight
myRipple.Center = CP
sbClickRipple.Begin()
End Sub
C#
private void rClick_MouseLeftButtonDown
(
object sender,
System.Windows.Input.MouseButtonEventArgs e
)
{
Point CP = e.GetPosition(rClick);
CP.X /= rClick.ActualWidth;
CP.Y /= rClick.ActualHeight;
myRipple.Center = CP;
sbClickRipple.Begin();
}
This little code snippet simply catches the mouse position relative to rClick using e.GetPosition which returns a Point that has a X and a Y value as the mouse position coordinates at the time the user did a left click. This caught position is assigned to the variable CP which is also of type Point. Then we calculate the values for the X- and Y-coordinates of the Center property of our RippleEffect by dividing the X value of CP by the ActualWidth of rClick and by dividing the Y value of CP by the ActualHeight of rClick respectively. Next we assign the value of variable CP to the Center property of the RippleEffect myRipple, which is also of type Point. Finally we start the StoryBoard.
That’s the whole magic.
What’s next?
In upcomming Part 2 we will take a look at how the Flexible Surface Effect can be easily configured and how to implement the effect on a UI with Buttons, TextBoxes, ScrollViewers etc.
Best regards, Martin (SilverLaw)