Reflecting light

Another technique involves adding a semi-opaque layer with a gradient that fades to transparency over the top of our controls to give the appearance of the reflection of a light source. This can easily be achieved using a simple Border element and a LinearGradientBrush instance. Let's look at how we can accomplish this:

<Button Content="Click Me" Width="140" Height="34" FontSize="18"  
  Foreground="White" Margin="20"> 
  <Button.Template> 
    <ControlTemplate TargetType="{x:Type Button}"> 
      <Border Background="#FF007767" CornerRadius="5"  
        SnapsToDevicePixels="True"> 
        <Grid> 
          <Rectangle RadiusX="4" RadiusY="4" Margin="1,1,1,7"  
            SnapsToDevicePixels="True"> 
            <Rectangle.Fill> 
              <LinearGradientBrush StartPoint="0,0" EndPoint="0,1"> 
                <GradientStop Color="#BFFFFFFF" /> 
                <GradientStop Color="#00FFFFFF" Offset="0.8" /> 
              </LinearGradientBrush> 
            </Rectangle.Fill> 
          </Rectangle> 
          <ContentPresenter HorizontalAlignment="Center"  
            VerticalAlignment="Center" /> 
        </Grid> 
      </Border> 
    </ControlTemplate> 
  </Button.Template> 
</Button> 

When run, this example will produce a button that looks like this:

Let's examine this example. We start by declaring the Button element with a few style properties. Rather than defining a separate style or control template in a resources section, as we would in a real-world application, we again declare the template inline to save space here.

In the control template, we first declare a Border element with a jade green background and a CornerRadius value of 5. We again set the SnapsToDevicePixels property to true to ensure that the edges remain sharp.

Inside the border, we define two elements within a Grid panel. The first is the Rectangle element that produces the reflection effect and the second is the required ContentPresenter object. The rectangle uses a value of 4 in the RadiusX and RadiusY properties and sets the Margin property appropriately to ensure that there is a tiny gap around the edge of the reflection.

It also sets its SnapsToDevicePixels property to true to ensure that this tiny gap is not blurred. Note that the value for the bottom margin is 7, because we do not want the reflection effect to cover the bottom half of the button. The Fill property is where the reflection effect is actually created.

In the rectangle's Fill property, we define a vertical LinearGradientBrush element by setting both of the X values of the StartPoint and EndPoint properties and the StartPoint.Y property to 0 and the Endpoint.Y property to 1; plotting these points on a graph will produce a vertical line, and so this produces a vertical gradient.

In the GradientStops collection of the LinearGradientBrush object, we have defined two GradientStop elements. The first has an offset of zero and is set to a white color with a hexadecimal alpha channel value of BF, which approximates an opacity value of 0.7. The second has an offset of 0.8 and is set to a white color that has a hexadecimal alpha channel value of 00, which results in a completely transparent color and could be replaced with the Transparent color.

The resulting gradient, therefore, starts slightly transparent at the top and is fully transparent at the bottom, which, with the bottom margin and offset values, is actually around the middle of the button. As with our other examples, the ContentPresenter object is declared afterwards so that it is rendered on top of the reflection effect.