Welcome to WindowsClient.net | My Blog | Sign in | Join

Faisal's Blog

Creating reflection with Silverlight 2.0 beta

I was searching for some WPF videos, after googling I found a site named contentpresenter . I found couple of interesting video there on WPF. After releasing of Silverlight 2.0 beta , my intention is implementing those WPF stuff in Silverlight as much as possible cause they're quite similar now. Let's start how I did this.

I found a video at contentpresenter on reflection. The idea behind this is video running on media element will be reflected. Much like mirror effect we've seen created in photoshop. Reflection will exactly be the reverse of original video which will be reflected on a rectangle located just beneath the media element. I have done that by changing XAML a little bit and the job was done. Here's my XAML step by step:

Inside my root Grid I have set both the Horizontal and Vertical alignment to center. This will center anything inside this Grid.Fixed it's width to 800 and height to 640 something like this :

<Grid x:Name="LayoutRoot" HorizontalAlignment="Center" 
  VerticalAlignment="Center" Width="800" Height="640" 
  MouseLeftButtonDown="TopElement_OnFullScreenChaged">

</
Grid>
 
After this I've Open Expression Blend 2.5 March 2008 Preview to Fill 
the background of my grid named LayoutRoot. Here's screen shot :
grid background 
 
Note that Under the interaction panel(Objects and Timeline) which is in this case
LayOutRoot name of my root grid has been selected to fix the Background color. I've
selected LinearGradientBrush to change the Background of my grid and this created the
following XAML :
<Grid.Background>
<
LinearGradientBrush EndPoint="0.493999987840652,1"
                    StartPoint="0.505999982357025,0">
<
GradientStop Color="#FF000000"/>
<
GradientStop Color="#FFA29C9C" Offset="1"/>
</
LinearGradientBrush>
</Grid.Background>

 

Next I've used StackPanel to have my Video top of the StackPanel and the reflection of the video bottom of the StackPanel.In the first section of the stack panel is the Border to add some border around MediaElement, you can also use the Grid .

Inside this Border I've placed my MediaElement. The MediaElement which i've named mElement is selected under the properties panel selecting the media tab and changing the source property has set the source of the video. Here's the Screen Shot :

 

media element Source

 

MediaElement is now inside the border. To absolutely size the media element I've set the width and height of the border to 328 and 248.I've fixed the background of my Broder to LinearGraidient.To stretching all the way through the border I've fixed the horizontal and vertical alignment to stretch.To bring in each side to 4 pixels I've set margin to 4 pixels to have that border.

Stretched Horizontal and Vertical Alignment

 

Now it's time to paint the actual video file to Rectangle. At first I have set the fill property of the Rectangle to fix the Background. This going to serve as reflection.

I've just set the Rectangle.Fill property to VideoBrush and set it's SourceName property to the the Border grdVideo that contains the media element. Now we can have perfect copy of the video playing beneath the original video painted over a Rectangle. But it's not the reflection of the video because it's actually needs to be flipped on the Y axes.To do that we can use transform property of the VideoBrush.

First it has been scaled on Y axes and then translated so I needed to use TransformGroup to allow multiple transform. Under the <TransformGroup> tag I've used the ScaleTransform and set it's ScaleY to negative 1. This flips on the Y axes.

To translate to the Y axes I've set the TranslateTransform Y property equal to our Border's height which is 248.Here's the screen shot on full screen mode :

Reflection FullScreen

 

This looks good but this is bit too strong cause in reflection opacity is much lighter and fades out towards the bottom. To achieve this I've played a bit with the opacity mask of the Rectangle. I've used the Gradient Brush for the opacity masks. First i've selected the right color key of the gradient and set it's alpha value to 0 and Left  color key somewhere round 30. I've used the gradient transform tool change the direction of the gradient by holding shift key for the perfection.Below is the screen shot after this modifications:

 

 

RealisticReflection

 

Now it's much more realistic. You can add video of your choice and play with the gradient background,Rectangle opacity mask etc. as much as you like to make it more realistic. Here's my XAML after all of this :

<UserControl x:Class="SilverlightReflection.Page"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Width="800" Height="640" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" OpacityMask="#FF000000" >


<
Grid x:Name="LayoutRoot" HorizontalAlignment="Center" VerticalAlignment="Center" Width="800" Height="640" MouseLeftButtonDown="TopElement_OnFullScreenChaged">
<
Grid.Background>
<
LinearGradientBrush EndPoint="0.474999994039536,0.523000001907349" StartPoint="0.47299998998642,0.181999996304512">
<
GradientStop Color="#FF8E8C8C"/>
<
GradientStop Color="#E9928F8F" Offset="0.8880000114440918"/>
<
GradientStop Color="#FFA4A4A4" Offset="0.656"/>
<
GradientStop Color="#FF6D6B6B" Offset="0.451"/>
<
GradientStop Color="#FF7E7C7C" Offset="0.21899999678134918"/>
</
LinearGradientBrush>
</
Grid.Background>
<
StackPanel Margin="0,0,0,0">
<
Border x:Name="grdVideo" Width="328" Height="248" MouseLeftButtonDown="grid_MouseLeftButtonDown">
<
Border.Background>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.493999987840652,1.79799997806549">
<
GradientStop Color="#FF000000"/>
<
GradientStop Color="#FF686565" Offset="1"/>
</
LinearGradientBrush>
</
Border.Background>
<
MediaElement x:Name="mElement" Source="Media/sl1.wmv" Margin="4,4,4,4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<
MediaElement.OpacityMask>
<
LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<
GradientStop Color="#FF000000"/>
<
GradientStop Color="#FF878383" Offset="1"/>
</
LinearGradientBrush>
</
MediaElement.OpacityMask>
</
MediaElement>
</
Border>
<
Rectangle x:Name="recVideo" Width="328" Height="248" Margin="4,1,4,1" StrokeThickness="4" RenderTransformOrigin="0.5,0.5">
<
Rectangle.OpacityMask>
<
LinearGradientBrush EndPoint="0.50900000333786,0.83899998664856" StartPoint="0.5,-0.208000004291534">
<
GradientStop Color="#4D000000"/>
<
GradientStop Color="#00FFFFFF" Offset="1"/>
</
LinearGradientBrush>
</
Rectangle.OpacityMask>
<
Rectangle.Fill>
<
VideoBrush SourceName="mElement">
<
VideoBrush.Transform>
<
TransformGroup>
<
ScaleTransform ScaleY="-1"/>
<
TranslateTransform Y="248"/>
</
TransformGroup>
</
VideoBrush.Transform>
</
VideoBrush>
</
Rectangle.Fill>

</
Rectangle>
</
StackPanel>

</
Grid>
</
UserControl>

To wire some event and get this in Full Screen I've added something in my Page.xaml.cs section which is quite simple and shown below  :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Interop;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace SilverlightReflection
{
public partial class Page : UserControl
{
private SilverlightHost slHost = new SilverlightHost();

public Page()
{
InitializeComponent();
}

private void TopElement_OnFullScreenChaged(object sender,
                                                   EventArgs e)
{
SizeUI();
}

private void SizeUI()
{
grdVideo.Width = this.ActualWidth/2;
grdVideo.Height =this.ActualHeight/2;
recVideo.Width = grdVideo.Width;
recVideo.Height = grdVideo.Height;
}

private void grid_MouseLeftButtonDown(object sender,
                                             MouseEventArgs e)
{
if (slHost.Content.IsFullScreen)
{
slHost.Content.IsFullScreen = false;
}
else
{
slHost.Content.IsFullScreen = true;
}
}
}
}

 

That's all . Expecting your opinion and  suggestion to do much better than this.

Happy coding.

kick it on DotNetKicks.com
Posted: Mar 24 2008, 08:48 PM by ilves | with 15 comment(s)
Filed under:

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com
# March 24, 2008 10:58 AM

Dew Drop - March 25, 2008 | Alvin Ashcraft's Morning Dew said:

Pingback from Dew Drop - March 25, 2008 | Alvin Ashcraft's Morning Dew
# March 25, 2008 8:41 AM

Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog said:

Pingback from Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog
# March 31, 2008 3:03 PM

DarkAura said:

hey,is there any way i can reflect an entire grid?
# May 17, 2008 3:54 AM

ilves said:

Would you please tell me clearly what you're trying to do?
# May 18, 2008 3:11 AM

RickP said:

I would like to know that to. Now you make a reflection with videobrush of the video itself. But is it possible to make a reflection of lets say a grid with multiple buttons since there is no visualbrush in silverlight.
# May 28, 2008 10:26 AM

nocomp said:

hi,

first of all thank you very much for this nice tutorial.

i gave it a try, but wasn t successfull :'(

once i build the project i go this message:

"the type,or the space named "page" could not be found" on line 21 colomn 26 wich is:

       public Page()

       {

           InitializeComponent();

       }

any idea about what went wrong?

thx for your attention

best regards

herve

# August 5, 2008 4:57 PM

ilves said:

Can you please show me the Xaml you've written?

# August 5, 2008 5:44 PM

nocomp said:

i just copied the one above thx for reply
# August 6, 2008 6:05 AM

ilves said:

You didn't copy your Xaml. I want to see your Xaml.
# August 6, 2008 2:58 PM

nocomp said:

hi

sorry, here it is, thx for your time!

----------------------------------

<UserControl x:Class="SilverlightReflection.Page"

   xmlns="schemas.microsoft.com/.../2007"

   xmlns:x="schemas.microsoft.com/.../xaml"

   Width="800" Height="640" xmlns:d="schemas.microsoft.com/.../2008" xmlns:mc="schemas.openxmlformats.org/.../2006" mc:Ignorable="d" OpacityMask="#FF000000" >

       <Grid x:Name="LayoutRoot" HorizontalAlignment="Center" VerticalAlignment="Center" Width="800" Height="640" MouseLeftButtonDown="TopElement_OnFullScreenChaged">

       <Grid.Background>

           <LinearGradientBrush EndPoint="0.474999994039536,0.523000001907349" StartPoint="0.47299998998642,0.181999996304512">

               <GradientStop Color="#FF8E8C8C"/>

               <GradientStop Color="#E9928F8F" Offset="0.8880000114440918"/>

               <GradientStop Color="#FFA4A4A4" Offset="0.656"/>

               <GradientStop Color="#FF6D6B6B" Offset="0.451"/>

               <GradientStop Color="#FF7E7C7C" Offset="0.21899999678134918"/>

           </LinearGradientBrush>

       </Grid.Background>

       <StackPanel Margin="0,0,0,0">

             <Border x:Name="grdVideo"  Width="328" Height="248" MouseLeftButtonDown="grid_MouseLeftButtonDown">

               <Border.Background>

                   <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.493999987840652,1.79799997806549">

                       <GradientStop Color="#FF000000"/>

                       <GradientStop Color="#FF686565" Offset="1"/>

                   </LinearGradientBrush>

               </Border.Background>

               <MediaElement x:Name="mElement" Source="Media/sl1.wmv" Margin="4,4,4,4" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">

                   <MediaElement.OpacityMask>

                       <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                           <GradientStop Color="#FF000000"/>

                           <GradientStop Color="#FF878383" Offset="1"/>

                       </LinearGradientBrush>

                   </MediaElement.OpacityMask>

               </MediaElement>

           </Border>

           <Rectangle x:Name="recVideo" Width="328" Height="248"  Margin="4,1,4,1" StrokeThickness="4" RenderTransformOrigin="0.5,0.5">

               <Rectangle.OpacityMask>

                   <LinearGradientBrush EndPoint="0.50900000333786,0.83899998664856" StartPoint="0.5,-0.208000004291534">

                       <GradientStop Color="#4D000000"/>

                       <GradientStop Color="#00FFFFFF" Offset="1"/>

                   </LinearGradientBrush>

               </Rectangle.OpacityMask>          

               <Rectangle.Fill>

                   <VideoBrush SourceName="mElement">

                       <VideoBrush.Transform>

                           <TransformGroup>

                               <ScaleTransform ScaleY="-1"/>

                               <TranslateTransform Y="248"/>

                           </TransformGroup>

                       </VideoBrush.Transform>

                   </VideoBrush>

               </Rectangle.Fill>  

           </Rectangle>

       </StackPanel>

   </Grid>

</UserControl>

-------------------------------------

# August 7, 2008 1:42 AM

ilves said:

Everything is ok. I don't see any problem in your Xaml. Try to create the project again and build. See what errors your'e getting and let me inform of that.
# August 7, 2008 3:58 PM

nocomp said:

hi, thx for your time, i truely appreciate. i just rebuild, and this is a screen cap of the error that i get: http://no-comp.net/img/reflection.JPG hope it ll help you out best regards herve
# August 7, 2008 4:24 PM

ilves said:

Use Visual Studio to build the project.
# August 7, 2008 4:56 PM

googlegum said:

Nice work, thank you for impressive example. Similar sample in SL1 uses just 2 identical mediaplayers. But I want to repeat a question of DarkAura above: is there any chance to reflect some generic Control (Framework element etc)?
# August 20, 2008 5:40 PM
Leave a Comment

(required) 

(required) 

(optional)

(required) 

Page view counter