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

Faisal's Blog

Sponsors





  • advertise here

Articles

Blogroll

Reflecting the entire layout panel in Silverlight 2 Beta 2

Introduction :

After my post on creating reflection with Silverlight 2 Beta . I was asked several times by couple of Silverlight enthusiasts questions like this : is there any way i can reflect an entire grid?, is it possible to make a reflection of lets say a grid with multiple buttons since there is no VisualBrush in Silverlight?, is there any chance to reflect some generic Control(Framework element etc)?. So I started to think about how entire Layout Panels like Grid,Canvas,Border etc. can be reflected. In WPF I did this stuff so easily. But in Silverlight I didn't find any any way till last night. The idea behind Layout reflection is , creating a mirror effect of a Container Control, which means child controls placed inside the container will also be reflected. Here's an example :

LayoutPanelReflection

Let's delve into this demonstration of Layout reflection.

My Thinking Behind Layout Reflection :

As I mentioned, the idea behind this Layout Reflection is reflecting a Container control which has some child controls in it, you need to create a UserControl to get the job done. Cause I didn't find any way to reflect this in the root page by nesting a Layout Controls Grid,Border etc. In my previous post on reflection I added a MediaElement inside Border and just below the Border I placed a Rectangle and set the Rectangle's Fill to VideoBrush and adjusted Opacity and then transformed the Rectangle. But here it's the complete different story. If you try to add two grids inside StackPanel and set the second Grid's Background to ImageBrush and set the ImageSource property to first Grid's Name. You won't see anything in your page. You'll feel a little strange also that after debugging you'll get no exception message whereas It's not the logical way. In Silverlight 2 Beta 2 documentation it is mentioned that ImageBrush property uses an underlying ImageSource instance actually and this is usually a BitmapImage,which is a derived class. When we set this property in Xaml it is set as URI. This behavior relies on underlying type conversion that processes the string as a URI, and calls the BitmapImage(Uri) constructor. ImageSource object is returned by requesting a stream from that URI. So I try some different things to reach my goal.

Creating The Layout Reflection :

Let's delve into my idea. In this demonstration of Layout reflection, I'll show you how I created my custom UserControl and got the reflection effect. Open Expression Expression Blend 2.5 June Preview. Before diving deep into this project let me see you the the final output of my application.

MyLayoutReflection

Open Expression Blend 2.5 June Preview. From the File menu select New and then select Silverlight 2.0 application from the project template dialog box. Name the project Layout Reflection.

Creating LayoutReflection Project

Now go to the Xaml view. You'll see that Xaml like this <Grid x:Name="LayoutRoot" Background="White" /> has been generated automatically. Delete the Xaml which has been selected in the picture below :

Automatically generated Xaml section

Add a Border as the LayoutRoot. This will be the main container of our UI or parent element, that's why it is named LayoutRoot. All the other elements will be nested inside this element. So from the Toolbox select Border like the picture below :

Selecting Border In The Toolbox

After Border is in selected mode in the Toolbox, double click over the Border. Border will be added inside your UserControl. Now select the Border and select the Properties panel. You'll be able to see all the properties relating to this Border.

Setting Borders Properties

In the Name section of the Properties panel, set the name of the Border to LayoutRoot. Set the Width of the Border to 800 and Height to 800 . From the Toolbox select StackPanel. You can find the StackPanel by right clicking over the selected Border in the Toolbox. Select the StackPanel. Set the Orientation Property of the StackPanel to Vertical. Add a Grid Inside the StackPanel.

Name the Grid grdmain. Set the Width of the Grid to 800 and Height of the 400. Set the Background of the Grid LinearGradientBrush and add two GradientStops for the LinearGradientBrush with the Color and Offset value fixed like the Xaml shown below:

<Grid.Background>
 <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
       <GradientStop Color="#FF000000"/>
       <GradientStop Color="#FFFFFFFF" Offset="1"/>
       </LinearGradientBrush>
</Grid.Background>

Switch to the design view, you'll have UI with the Background color shown in the picture  below.

Setting Grid grdMains Background

Add another Grid just after the closing tag of the Grid named grdMain. Name the Grid grdReflected. Set the Width of the Grid to 800 and Height to 400. Set the Grid's Background to LinearGradientBrush with the Color and offset Values of the GradientStops setting like the Xaml below:

<Grid.Background>
     <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
             <GradientStop Color="#FF000000"/>
             <GradientStop Color="#FFFFFFFF" Offset="1"/>
       </LinearGradientBrush>
</Grid.Background>

Now Go to the Design view again to check the UI. You'll be able to see something link this :

After Adding The Second Grid

If you look carefully at the UI, you'll see that second Grid or the Grid named grdReflected is not showing correctly. It's because of the default setting of  Height property of the UserControl. The Height of UserControl Is set to 480 whereas, you've set the grdReflected's Height to 400. To the the grdReflected, you need to delete the Height Property of the UserControl from this section :

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="LayoutReflection.Page"
    xmlns:LayoutReflection="clr-namespace:LayoutReflection" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d"
    Width="640" Height="480">

Delete the Height property of the UserControl and also delete the Width and get back to the Design view to see your grdReflected in full shape :

grdReflected in Full Form

This grid is a very important part of our UI cause the reflection will be seen inside this grid and that's why it has been named grdReflected. At this point you've completed designing the core UI for your LayoutReflection. One more crucial thing you need to do regarding grdReflected's Background If you look at the picture above, you'll see that it is easily understandable that we've added to grid's and set the Background for both of them and the Background each Grid is indicating that they're different Layout. We need to confirm here to give our UI a look as if it's a Single Layout. To do this select the grdReflected in the Objects and Timeline panel and then select the Background property of the grdReflected in the Properties panel. Select Brush Transform tool in the ToolBox. This will give you and option to transform the gradient look you've given to your Grid's Background. For your clarification here's the Brush Transform icon :

Brush Transform Icon

You just need to select this icon in the ToolBox to transform the gradient of your control's Background and this will produce an arrow over the grdReflected. Since we're trying to reflect the Background of this Grid. Here's the screen shot:

BrushTransform In Action

The endpoints of the transform arrow correspond to the gradient stops at either end of the color bar. If you take your mouse cursor just beneath the you'll see a curve will appear to transform the gradient easily. If you want to know more about Brush Transform, for your convenience, I would like to mention that, You can change the behavior of the brush transform tool in the following ways:

1. Hold the SHIFT key while dragging an endpoint to constrain the movement along the straight line between the endpoints.

2. Hold the SHIFT key while moving the entire arrow to constrain the movement to the X or the Y plane.

3. Hold the SHIFT key while rotating an endpoint to snap every 15 degrees.

4. Hold the ALT key while dragging an endpoint to move both endpoints at the same time, maintaining the position of the center point.

Transform the gradient to make users feel that only one Layout Control has been used in this demonstration of Layout reflection. Try to transform your gradient and get the look of your UI like the following picture :

AfterTransforming The Gradient 

Don't you think now it's tough to find out that two Layout controls has been used to designed this UI? At this point we're done with designing the main page's entire layout and give it a desired look and feel.

Now add a UserControl to your project by selecting the Project panel and right clicking the project template and then select Add New Item.

Adding user Control

This will bring up a dialog box which will show you the installed template and it is UserControl. Change the name of the UserControl from UserControl1 to StyledButton. Double click the App.Xaml and switch to the Xaml view in the Application.Resources section Add these Bushes as a resource :

<SolidColorBrush x:Key="Color1" Color="#FF0000FF"/>
<SolidColorBrush x:Key="Color2" Color="#FF007EFD"/>
<SolidColorBrush x:Key="Color3" Color="#FF00C000"/>
<SolidColorBrush x:Key="Color4" Color="#FF00FF00"/>
<SolidColorBrush x:Key="Color5" Color="#FFCCFF33"/>
<SolidColorBrush x:Key="Color6" Color="#FFF8E748"/>
<SolidColorBrush x:Key="Color7" Color="#FFFF8000"/>
<SolidColorBrush x:Key="Color8" Color="#FFFF0000"/>
<SolidColorBrush x:Key="Color9" Color="#FFC00000"/>
<SolidColorBrush x:Key="Color10" Color="#FF800000"/>

   <LinearGradientBrush x:Key="glassyRect_Background" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FF6E6E6E" Offset="0.531"/>
        <GradientStop Color="#FFFFFFFF" Offset="0"/>
        <GradientStop Color="#FFE2E2E2" Offset="1"/>
        <GradientStop Color="#E52D2D2D" Offset="0.54"/>
    </LinearGradientBrush>
    
    <LinearGradientBrush x:Key="Stroke_glassyBackgroundRect" EndPoint="0.5,1" StartPoint="0.5,0">
        <GradientStop Color="#FF1D1D1D" Offset="0"/>
        <GradientStop Color="#FE333333" Offset="1"/>
        <GradientStop Color="#FFFFFFFF" Offset="0.444"/>
        <GradientStop Color="#FFF4F4F4" Offset="0.628"/>
    </LinearGradientBrush>

    <LinearGradientBrush x:Key="Brush1" EndPoint="0.5,1" StartPoint="0.5,0">
       <GradientStop Color="#FF000000"/>
       <GradientStop Color="#FF646464" Offset="1"/>
    </LinearGradientBrush>

These Brushes will be your application level resource and you can use them everywhere of your project. Double Click the Layout Root of the UserControl named Styled Button to activate it. You should see a blue bar around the page. Set the margins in the properties panel to 8 on every side.

Setting The margins of The StyledButtons

Click in the blue bar to divide your page in 4 different parts, just like in the screenshot. Don’t forget to close the lockers so that the grid will resize properly. Select The Border from the ToolBox and draw it in the Upper part of the Grid. Set the margins of the Border to 0,0,0,0 and CornerRadius to 16,16,16,16. Add another layout control inside Border, cause Border only accepts one child. You can add the StackPanel inside the Border in Expression Blend by Double clicking the Border to make it active and then drag StackPanel in the Border. Set margins of the StackPanel to 0,0,0,0 and Orientation to Horizontal. Add Five buttons inside StackPanel and name the Buttons to your liking I've named the Button MyStyled1,MyStyled2 etc. Now Select All the Buttons and set the Width to Auto, Height to 37.11 , HorizontalAlignment to Stretch, VerticalAlignment to Center and margins to 44,44,0,0.

StyledButtons UI

Name all the buttons according to your liking. Now change the background of the Border. We will use the Brush resources we've created in the App.Xaml. Cause these Brushes are our application level resources. The advantage of creating these resources is, with a resource, you give something eg. a Color, unique name and refer to it with this name. If you like to change the color later, you only have to change the resource once. There are two ways to create a resource. You can Write the Xaml in the <Application.Resources> section, which I've shown in this example and the other way is, select the Brushes section in the Properties panel and click the +Brush button. You can insert a name and a location for the brush. Blend will write the XAML code for you. To change the Background of the Border, Select the border element in the Objects and Timeline panel and select the property Background and then select Brush resources to see the available resources you've created earlier. Select any one of them. I've selected Brush1 here. Here's the Screen shot :

Selecting BrushResources

Set The OpacityMask of the Border to GradientBrush and reduce the Alpha value to 45% . You can select the Brush transform tool from the Toolbox if you want to change the length and direction of the gradient. Open StyledButtons.Xaml and switch to the Xaml view to add <UserControl.Reources> section like the following Screen Shot :

UserCotrols Resources Section

I'm not going to add any style to the buttons cause it only changes the small portions of the Buttons. If you add a Style, eg with the Xaml below :

<Style x:Key="myButtonStyle" TargetType="Button">
    <Setter Property="Background" Value="{StaticResource glassybackground}"/>
    <Setter Property="Foreground" Value="{StaticResource GlassyLightBlue}"/>
    <Setter Property="Padding" Value="1"/>
    <Setter Property="OpacityMask">
        <Setter.Value>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="Silver" Offset="0"/>
                <GradientStop Color="Gray" Offset="1"/>
            </LinearGradientBrush>
        </Setter.Value>
    </Setter>
</Style>

You'll be able to see very little difference after running your application. I need to change the entire look of the Buttons so I'm going to use templates. ControlTemplate property contains the look and structure of the every control. Now instead of writing the Style section above add something like the xaml below inside the <UserControl.Resources> section :

<Style x:Key="MyGlassyStyle" TargetType="Button">
          <Setter Property="Template">
              <Setter.Value>
                  <ControlTemplate TargetType="Button">

                  </ControlTemplate>
              </Setter.Value>
          </Setter>
      </Style>

 

Now go to the Design view and draw a border outside the design area, for example:

Drawing Outside The Design Area

Look carefully at the above picture, here I've tried to draw a Border just outside my design area to show you an example. This is the coolest way to define templates in Expression Blend and I've learnt this trick from Multimania Silverlight Workshop by Frederick Duchi and Dieter De Preester. This example is also based on that Workshop. I've just Improvised a little to have my desired effects on the Controls.  After drawing the Border adjust the properties of the Border according to your liking. I have set the  Width of the Border to 100 and Height to 35. Set the Border's CornerRadius of 8 on each side, BorderThickness to 3 on each side, Background to "{StaticResource glassyRect_Background}" Which has been defined as a Brush resource earlier in our <Application.Resources> section and BorderBrush to "{StaticResource Stroke_glassyBackgroundRect}" which as also been defined as a Brush resource in our <Application.Resources> section. Remember these are the application level resources and that's why this is applicable in this StyledButton UserControl. Add an Opacity mask to the Border and reduce the alpha from 100 to 75. Double click the border and put a grid in the border by double clicking the grid control in the Toolbox. Activate the grid and draw a little ellipse. Hold shift to draw a perfect circle in the left corner. Remove the stroke of the ellipse by setting Stoke Brush to none. Here's an example of setting stroke to none :

Setting Stroke Brush to None

In the above picture you can see that I've tried to draw an ellipse to show you how to set stroke to no Brush in the properties panel. You Just need to select the stroke option and then select the No brush(Which is shown in the picture above).  Draw a bigger ellipse above the first one. Select the first ellipse and the second ellipse. Go to the object Menu select Combine and then select sub menu subtract the second ellipse from the first one. Set the alpha value of the white fill to 15, the HorizontalAlignment to the left, VerticalAlignment to stretch, the margins to 4 on each side except the right side which should be 0. Set the the Width to 10 and the Height to Auto. Now Copy and Paste the Path.

Set the HorizontalAlignment of the path you just copied to Right and the Margins to 4 on each side except the Left side which should be 0. Go to the Transform section in the Properties panel and select the flip option. Select the first button and flips X axis. At last add a Content Presenter to the Grid. This Control can contain anything, here I will just add text for our Buttons.  Set the Horizontal and VerticalAlignment to Center and the Foreground to "{StaticResource Stroke_glassyBackgroundRect}" this is the Brush resource we've  defined earlier. In the Properties panel type some text in the content property of ContentPresenter. Set the FontFamily to Trebuchet MS, FontSize to 12 and FontWeight to Bold. After completing this step, you'll have button look like the Button shown below :Styled Button After Templating

Go to the Xaml view in and cut the selected Xaml which has been shown in the following picture :

Cut and Paste Xaml for Templating

In the above picture I've cut all the Xaml I've written by drawing a Border outside the design area of my UI. Now paste this Xaml inside <ControlTemplate> element of the style. You have to remove every attribute in the Border that has to do something with Alignment, Margins, Height and Hidth and you Xaml should look like the following :

<Border  BorderThickness="3,3,3,3" CornerRadius="8,8,8,8" Background="{StaticResource glassyRect_Background}"
 BorderBrush="{StaticResource Stroke_glassyBackgroundRect}">
    <Border.OpacityMask>
        <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
            <GradientStop Color="#FF000000"/>
            <GradientStop Color="#BFFFFFFF" Offset="1"/>
        </LinearGradientBrush>
    </Border.OpacityMask>
    <Grid>
        <Path HorizontalAlignment="Left" Margin="4,4,0,4" VerticalAlignment="Stretch" Width="10" 
   Fill="#26FFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M17.728249,0.5 C30.706938,0.50000006 
   41.228249,11.021308 41.228249,24 C41.228249,36.978691 30.706938,47.5 17.728249,47.5 C10.893907,
  47.5 4.7409706,44.582565 0.5,39.876183 L1.7282476,40 C10.564803,40 17.728249,32.836555 17.728249,24 
  C17.728249,15.163444 10.564803,8 1.7282476,7.9999995 C1.3129911,8 0.90142918,
  8.0158195 0.5,8.1238174 C4.7409706,3.4174345 10.893907,0.50000006 17.728249,0.5 z" 
  RenderTransformOrigin="0.5,0.5">
            <Path.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleX="-1"/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Path.RenderTransform>
        </Path>
        <Path HorizontalAlignment="Right" Margin="4,4,0,4" VerticalAlignment="Stretch" Width="10" 
  Fill="#26FFFFFF" Stretch="Fill" Stroke="#FF000000" Data="M17.728249,0.5 C30.706938,
  0.50000006 41.228249,11.021308 41.228249,24 C41.228249,36.978691 30.706938,47.5 17.728249,
  47.5 C10.893907,47.5 4.7409706,44.582565 0.5,39.876183 L1.7282476,
  40 C10.564803,40 17.728249,32.836555 17.728249,24 C17.728249,15.163444 10.564803,8 1.7282476,
  7.9999995 C1.3129911,8 0.90142918,8.0158195 0.5,8.1238174 C4.7409706,3.4174345 10.893907,
  0.50000006 17.728249,0.5 z" RenderTransformOrigin="0.5,0.5">
            <Path.RenderTransform>
                <TransformGroup>
                    <ScaleTransform ScaleY="-1"/>
                    <SkewTransform/>
                    <RotateTransform/>
                    <TranslateTransform/>
                </TransformGroup>
            </Path.RenderTransform>
        </Path>
        <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" 
Foreground="{StaticResource Stroke_glassyBackgroundRect}" 
Content="{TemplateBinding Content}" FontFamily="Trebuchet MS" FontWeight="Bold"/>
    </Grid>
</Border>

At this point you've created a customized Template for your Buttons. Now go to the <ContentPresenter> section of your Template and change the value of the Content to "{TemplateBinding Content}". The reason behind this,  Content property of each button must checked by template and put it in the Content of the Template. If you've done everything accroding to my instruction and test your Buttons by applying Style which is in this case MyGlassyStyle, You'll be able to see the Buttons like the picture below in your UI.

Styled Buttons

Now Remove the d:DesignWidth=640 and d:DesignHeight=480 from your <UserControl> section and set The Grid named LayoutRoot's Background to "{StaticResource glassyRect_Background}" . You'll have UI Like the following :

StyledButton UI Final1

Adding Animation :

Select Button named MyStyledButton1 in the interaction panel Click the + sign just under the Objects and Timeline to add a Storyboard. Name the Storyboard whatever you want. In this case it is OverButton. Move the playhead to 0.3 seconds,set the Width of the Button to 192 and the Height to 46. You'll see that Expression Blend has automatically added a new keyframe. Click the arrow near the + button and choose Duplicate.Click the arrow near the + button a second time, choose Rename and enter outMenu as name.  Finally, click the arrow near the + button a last time and choose Reverse.You have now created an exactly reverse animation for MyStyledButton1.

The storyboards are recorded, but will not be executed until you say so. Open page.xaml with Visual Studio and take a look at the XAML code that has been generated for one of the storyboards:


<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyStyledButton1" 
Storyboard.TargetProperty="(FrameworkElement.Width)" BeginTime="00:00:00">
           <SplineDoubleKeyFrame KeyTime="00:00:00" Value="148"/>
           <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="192"/>
       </DoubleAnimationUsingKeyFrames>
       <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MyStyledButton1" 
Storyboard.TargetProperty="(FrameworkElement.Height)" BeginTime="00:00:00">
           <SplineDoubleKeyFrame KeyTime="00:00:00" Value="35"/>
           <SplineDoubleKeyFrame KeyTime="00:00:00.3000000" Value="46"/>
       </DoubleAnimationUsingKeyFrames>
   </Storyboard>

Threre's no reason to create a new Storyboard for each button. You can remove the Storyboard.TargetName="MyStyledButton1" from <DoubleAnimationUsingKeyFrames>. It will be much better if you do this dynamically with C#.

Go to the StyledButtons in the Xaml File by opening VisualStudio and add an EventHandler for the MouseEnter event to MyStyledButton1. Like the following :

<Button x:Name="MyStyledButton1" Content="MyStyled1" Margin="44,0,44,0" VerticalAlignment="Center" Width="Auto" Height="37.11" Style='{StaticResource MyGlassyStyle}'  MouseEnter='overButton_MouseEnter' MouseLeave='outOfButton_MouseLeave'  />

Repeat the same process for the rest of the Buttons. Right click over the Event handler you've assigned in your Xaml. For example, MouseEnter="overButton_MouseEnter"  and select Navigate to EventHandler like the following picture :

Navigate To Event handler Of StyledButtons  

By selecting Navigate to EventHandler you'll add an event in your StyledButtons.Xaml.cs page.

EventHandler For The Buttons In C#

Add this code to inside your overButton_MouseOver EventHandler to see the MouseOver events in action :

Button btn = sender as Button;
overButton.Stop();
overButton.SetValue(Storyboard.TargetNameProperty, btn.Name);
overButton.Begin();

Repeat the same process for outOfButton_Mouseleave to see the MouseLeave events in action. Add the following code inside your outOfButton_MouseLeave EventHandler :

Button btn = sender as Button;
outOfButton.Stop();
outOfButton.SetValue(Storyboard.TargetNameProperty, btn.Name);
outOfButton.Begin();

To text this UserControl Add this to your Page.Xaml by adding Namespace like this xmlns:LayoutReflection="clr-namespace:LayoutReflection" . Double click the grdMain to activate it and add your StyledButtons UserControl with the following Xaml :

<LayoutReflection:StyledButtons Height="96" Margin="-8,-7.99599981307983,92,0" VerticalAlignment="Top" RenderTransformOrigin="0.5,0.5" Opacity="0.14">

The easiest process of adding UserControls is using Expression Blend. Right Click over the StyledButtons.Xaml and select Open In Expression Blend like the picture below :

Open StyledButtons In Expression Blend From VisualStudio

From the Toolbox select Asset Library. This is located in at the bottom of the ToolBox with double arrow icon. Select over the arrow, this will bring up the Asset library dialog box.

Asset Library

Select Custom Controls tab in the dialog box and select StyledButtons. This will add StyledButtons UserControls control in the ToolBox which is just above the AssetLibrary icon. To add the StyledButtons userControl all you need to do is just select the StyledButtons in the ToolBox and draw it over your main page. In this case you're going to add this by doubble clicking grdMain Grid to activate the Grid and  draw this UserControl inside the Grid named grdmain. We're now just adding this StyledButtons  UserControl to see it in running mode or just to test this control. Go back to the Visual Studio and press F5 to run the project. Remember if you modify your UserControl or do something else in the Expression Blend, switching to the Visual Studio might show you this message :

"The file has been modified outside the source editor. Do you want to reload it?"

Just set the button yes or yes to all if want your single file or mutiple file to reload in Visual Studio. Now see the project in the running mode.

StyledButtons In Running Mode

If you put your mouse over the Button's you'll see the effect like like pictures above. This is the animation we've defined earlier by creating Storyboards for our Buttons.

After testing the UserControl Styled Buttons delete it from the page cause we don't need this to be added in our page now. We are going to add few more UserControls.

Right click over your project name in the VisualStudio or Expression Blend and Select Add new Item. name The UserControl ColorGrid. This will add usercontrols named ColorGrid with the default xaml generated like this. Now Go to the Expression Blend and add 10 columns. Move your mouse over the blue area outside your Grid you'll have a line like this :

Adding Columns

 

Add 10 lines to add 10 columns. You can also do this by by expanding the Layout section of the Properties panel and click the button near the ColumnDefinitions property. A new window will appear.

Adding Columns In Expression Blend

Click the "Add another item" button 10 times and click ok to close the window. This will add 10 columns to your Grid. Select the Rectangle element from the toolbox and draw a rectangle in every column.  Draw a rectangle in every column. Select all the 10 Rectangles. You can do this by select the first Rectangle with mouse and then pressing Ctrl key and mouse button together. Go to the properties of the Rectangle and set the Stoke and OpacityMask to None for every Rectangles. Set Width and Height to Auto. RowSpan and ColumnSpan to 1, HorizontalAlignment and VerticalAlignment to Stretch. Now Change the Fill property of each Rectangle by applying each brush resources you created earlier. Give each Rectangle different background. Here's the Screen shot of BrushResouces you created in Properties panel :

BrushResources In Blend

Remove Height property from the UserControl ColorGrid.  add another rectangle which will indicate the selected value in the chart. Add 10 TextBlock in 10 columns. Set the Font to MS Trebuchet, the size to 36, the HorizontalAlignment and VerticalAlignment to center, Width and Height to auto, the margins to 0 and the Foreground color to white. Change the Text property of each TextBlock in a number from 1 to 10. Add another UserControl and name it ReflectableUI. Add Three rows and two columns like the screen shot below :

ReflectableUI

Add two Grid's to one in the upper row which is row number 0 and another one will be in row number 1. Which is a middle row. This grid must fill the entire rows. Add a StyledButtons in the upper row Calender in the middle or row number 1. Now add ColorGrid just after the closing section of the Second Grid. Here's the Xaml :

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    x:Class="LayoutReflection.ReflectableUI"
    d:DesignWidth="640" d:DesignHeight="400" 
    xmlns:System_Windows_Controls="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Extended" 
    xmlns:LayoutReflection="clr-namespace:LayoutReflection">

    <Grid x:Name="LayoutRoot" Height="392" >
        <Grid.Background>
            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                <GradientStop Color="#FF000000"/>
                <GradientStop Color="#FF0F5365" Offset="1"/>
            </LinearGradientBrush>
        </Grid.Background>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="0.762*"/>

            <ColumnDefinition Width="0.238*"/>

        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height="0.159*"/>
            <RowDefinition Height="0.581*"/>
            <RowDefinition Height="0.26*"/>
        </Grid.RowDefinitions>
        <Grid HorizontalAlignment="Stretch" Margin="0,0,0,-24.3999996185303" VerticalAlignment="Stretch" 
           Grid.ColumnSpan="2">
            <Grid.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF000000"/>
                    <GradientStop Color="#FF00626F" Offset="1"/>
                </LinearGradientBrush>
            </Grid.Background>
            <LayoutReflection:StyledButtons Margin="-8,-8,-8,16" d:LayoutOverrides="VerticalAlignment"/>
        </Grid>
        <Grid HorizontalAlignment="Stretch" Margin="0,72.4000015258789,0,0" VerticalAlignment="Stretch" 
          Grid.ColumnSpan="2" Grid.Row="1">
            <Grid.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="#FF000000"/>
                    <GradientStop Color="#FF0C5467" Offset="1"/>
                </LinearGradientBrush>
            </Grid.Background>
            <System_Windows_Controls:Calendar Margin="0,0,0,0" HorizontalAlignment="Left" 
            VerticalAlignment="Top"/>
        </Grid>
        <LayoutReflection:ColorGrid Margin="0,0,87.6800003051758,4" Grid.ColumnSpan="1" Grid.Row="2"/>
    </Grid>
</UserControl>

Switch to your main page and add the Xaml below to see the effect of layout reflection :

<UserControl
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="LayoutReflection.Page"
    xmlns:LayoutReflection="clr-namespace:LayoutReflection" 
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d">


     <Border x:Name="LayoutRoot" Width="800" Height="800">
       <StackPanel Orientation="Vertical">
           <Grid x:Name="grdMain" Width="800" Height="400" >
               <Grid.Background>
                   <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                       <GradientStop Color="#FF000000"/>
                       <GradientStop Color="#FFFFFFFF" Offset="1"/>
                   </LinearGradientBrush>
               </Grid.Background>
               <LayoutReflection:ReflectableUI Margin="0,0,0,0"/>
               
           </Grid>
           <Grid x:Name="grdReflected" Width="800" Height="400" RenderTransformOrigin="0.5,0.5" 
           Opacity="0.975">
               <Grid.OpacityMask>
                   <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                       <GradientStop Color="#FF000000"/>
                       <GradientStop Color="#FF0A7684" Offset="1"/>
                   </LinearGradientBrush>
               </Grid.OpacityMask>
               <Grid.RenderTransform>
                   <TransformGroup>
                       <ScaleTransform/>
                       <SkewTransform/>
                       <RotateTransform Angle="0.037"/>
                       <TranslateTransform/>
                   </TransformGroup>
               </Grid.RenderTransform>
                <Grid.Background>
                    <LinearGradientBrush EndPoint="0.500999987125397,0" StartPoint="0.499000012874603,1">
                        <GradientStop Color="#FF000000"/>
                        <GradientStop Color="#FFFFFFFF" Offset="1"/>
                    </LinearGradientBrush>
                </Grid.Background>
               <LayoutReflection:ReflectableUI Margin="-0.898000001907349,-18.5930004119873,
 -0.907999992370605,1.2059999704361" RenderTransformOrigin="0.5,0.5" Opacity="0.095">
                   <LayoutReflection:ReflectableUI.RenderTransform>
                       <TransformGroup>
                           <ScaleTransform/>
                           <SkewTransform/>
                           <RotateTransform Angle="180.03"/>
                           <TranslateTransform/>
                       </TransformGroup>
                   </LayoutReflection:ReflectableUI.RenderTransform>
               </LayoutReflection:ReflectableUI>

            </Grid>
       </StackPanel>
     </Border>

    
</UserControl>

In the above Xaml, at first I have added the Reflectable UserControl inside the Grid named grdMain and then added another Reflectable UserControl and transform the control and reduce the opacity of the control to get the reflected effect.

LayoutReflection Final Output

This my idea behind reflecting the entire layout in Silverlight. If anyone has the better idea  on reflecting the entire layout. I would love to here from them.

kick it on DotNetKicks.com
Posted: Sep 04 2008, 01:49 AM by ilves | with 12 comment(s)
Filed under:

Comments

DotNetKicks.com said:

You've been kicked (a good thing) - Trackback from DotNetKicks.com

# September 12, 2008 10:56 PM

Don Baechtel said:

Good technique. Do you have a complete SL 2.0 B2 example that we could download and work from?
# September 13, 2008 4:34 PM

Don Baechtel said:

Do you have a project download?
# September 13, 2008 4:36 PM

Mirrored Blogs said:

Post: Approved at: Sep-13-2008 Reflecting the entire layout panel in SL This is a cool effect to add
# September 14, 2008 2:59 AM

2008 September 14 - Links for today « My (almost) Daily Links said:

Pingback from 2008 September 14 - Links for today « My (almost) Daily Links
# September 14, 2008 6:44 AM

Kigg.com said:

Your Story is Submitted - Trackback from Kigg.com
# September 15, 2008 9:23 AM

DotNetShoutout said:

Your Story is Submitted - Trackback from DotNetShoutout

# November 15, 2008 3:36 PM

... said:

Lovely. Great site.

# January 31, 2009 1:17 AM

Dave said:

Hey really great stuff!

I think there's a quicker way to achieve a little less complex reflection.

Once you have all layed out onto grid1, let's say, copy and paste in the same place the entire grid. Then go to transform --> scale and put the Y-value to -1. Now you have the exact grid reflected. Move the Y-position down as needed and there you go!

To have a better looking reflection you can give an opacity mask to the reflected grid, with a gradient color and make the bottom gradient completely transparent. Just work with opacity.

Hopefully I can post within few days this example on my blog so we'll have a comparison!

Regards

Dave

# April 15, 2009 5:01 PM

ilves said:

Hi Dave, Thanks for your comments. I would love to see something on this in your blog. You can have a look at the project at codeplex. http://layoutreflection.codeplex.com
# April 18, 2009 9:43 PM

Bill Bartmann said:

Cool site, love the info.
# September 1, 2009 6:18 PM

Bill Bartmann said:

Excellent site, keep up the good work
# September 7, 2009 10:03 AM
Leave a Comment

(required) 

(required) 

(optional)

(required)