FlipPanel Control

FlipPanel Control is a double-sided panel, which when flipped displays content on the "back", and displays different content on the "front" when not flipped using Silverlight for Windows Phone 7.

www.cespage.com/silverlight/wp7tut25.html

Step 1

Start Microsoft Visual Studio 2010 Express for Windows Phone, then Select File then New Project... Select "Visual C#" then "Silverlight for Windows Phone" and then "Windows Phone Application" from Templates, select a Location if you wish, then enter a name for the Project and then click OK, see below:

New Project

Step 2

A Windows Phone application Page named MainPage.xaml should then appear, see below:

MainPage.xaml

Step 3

Select from the Main Menu "File" then "Add", then "New Project...", and select the "Windows Phone Class Library" Template, then change the "Name" to FlipPanel see below:

Add FlipPanel Class Library Project

Step 4

Add the New Class Library Project by Clicking on Add, then in the Solution Explorer for "FlipPanel", click on the "Class1.cs" entry, then goto Properties and change the File Name property to "FlipPanel.cs" (without the quotes), see below:

FlipPanel Class Properties

Step 5

In the "You are renaming a file. Would you also like to perform a rename in this project of all references to the code element 'Class1'?" choose Yes.
Right Click on the Entry for the "FlipPanel" Project (not FlipPanel.cs) in Solution Explorer and choose "Add" then "New Folder", and give it the Name "Themes" (again without quotes), see below:

FlipPanel Project Themes Folder

Step 6

Right Click on the Entry for the "Themes" Folder for the FlipPanel Project, and choose "Add", then "New Item...", select the "Text File" Template and change the name to "Generic.xaml", (without the quotes), see below:

Generic.xaml Resource Dictionary Text File

Step 7

Add the Text File for the ResourceDictionary by Clicking on Add.
In the XAML Pane for the Generic.xaml type the following Resource Dictionary XAML:


<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:FlipPanel">
  <Style TargetType="local:FlipPanel">
    <Setter Property="Template">
      <Setter.Value>
        <ControlTemplate TargetType="local:FlipPanel">
          <Grid>
            <VisualStateManager.VisualStateGroups>
              <VisualStateGroup x:Name="ViewStates">
                <VisualStateGroup.Transitions>
                  <VisualTransition To="Normal" From="Flipped" GeneratedDuration="0:0:0.7">
                    <Storyboard>
                      <DoubleAnimation Storyboard.TargetName="BackContentProjection"
                         Storyboard.TargetProperty="RotationY" To="-90" Duration="0:0:0.5"/>
                      <DoubleAnimation Storyboard.TargetName="FrontContentProjection"
                         Storyboard.TargetProperty="RotationY" To="0" BeginTime="0:0:0.5" Duration="0:0:0.5"/>
                    </Storyboard>
                  </VisualTransition>
                  <VisualTransition To="Flipped" From="Normal" GeneratedDuration="0:0:0.7">
                    <Storyboard>
                      <DoubleAnimation Storyboard.TargetName="FrontContentProjection"
                          Storyboard.TargetProperty="RotationY" To="90" Duration="0:0:0.5"/>
                      <DoubleAnimation Storyboard.TargetName="BackContentProjection"
                          Storyboard.TargetProperty="RotationY" To="0" BeginTime="0:0:0.5" Duration="0:0:0.5"/>
                    </Storyboard>
                  </VisualTransition>
                </VisualStateGroup.Transitions>
                <VisualState x:Name="Normal">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="BackContentProjection"
                        Storyboard.TargetProperty="RotationY" To="-90" Duration="0"/>
                  </Storyboard>
                </VisualState>
                <VisualState x:Name="Flipped">
                  <Storyboard>
                    <DoubleAnimation Storyboard.TargetName="FrontContentProjection" 
                        Storyboard.TargetProperty="RotationY" To="90" Duration="0"/>
                    <DoubleAnimation Storyboard.TargetName="FlipButtonTransform" 
                        Storyboard.TargetProperty="Angle" To="90" Duration="0"/>
                  </Storyboard>
                </VisualState>
              </VisualStateGroup>
            </VisualStateManager.VisualStateGroups>
            <Grid.RowDefinitions>
              <RowDefinition Height="Auto"/>
              <RowDefinition Height="Auto"/>
            </Grid.RowDefinitions>
            <Border BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="{TemplateBinding CornerRadius}"
                Background="{TemplateBinding Background}">
              <ContentPresenter Content="{TemplateBinding FrontContent}"/>
              <Border.Projection>
                <PlaneProjection x:Name="FrontContentProjection"/>
              </Border.Projection>
            </Border>
            <Border BorderBrush="{TemplateBinding BorderBrush}"
                BorderThickness="{TemplateBinding BorderThickness}"
                CornerRadius="{TemplateBinding CornerRadius}"
                Background="{TemplateBinding Background}">
              <ContentPresenter Content="{TemplateBinding BackContent}"/>
              <Border.Projection>
                <PlaneProjection x:Name="BackContentProjection"/>
              </Border.Projection>
            </Border>
            <ToggleButton Grid.Row="1" RenderTransformOrigin="0.5,0.5" Margin="0,10,0,0" x:Name="FlipButton">
              <ToggleButton.Template>
                <ControlTemplate>
                  <Grid>
                    <Ellipse Width="50" Height="50" Fill="{StaticResource PhoneAccentBrush}"/>
                    <Path RenderTransformOrigin="0.5,0.5" HorizontalAlignment="Center" VerticalAlignment="Center" 
                      Data="M2,3L9,10 16,3" Stroke="{StaticResource PhoneForegroundBrush}" StrokeThickness="4"/>
                  </Grid>
                </ControlTemplate>
              </ToggleButton.Template>
              <ToggleButton.RenderTransform>
                <RotateTransform Angle="-90" x:Name="FlipButtonTransform"/>
              </ToggleButton.RenderTransform>
            </ToggleButton>
          </Grid>
        </ControlTemplate>
      </Setter.Value>
    </Setter>
  </Style>
</ResourceDictionary>

See below:

FlipPanel Resource Dictionary

Step 8

Right Click on the Entry for the "FlipPanel.cs" Class in Solution Explorer in the "FlipPanel Project" and choose "View Code" or Double click on "FlipPanel.cs".
In the Code View for FlipPanel above "namespace FlipPanel" line type the following:

using System.Windows.Controls.Primitives;

Also in the CodeView above "public class FlipPanel" type the following:

[TemplateVisualState(Name = "Normal", GroupName = "ViewStates")]
[TemplateVisualState(Name = "Flipped", GroupName = "ViewStates")]
[TemplatePart(Name = "FlipButton", Type = typeof(ToggleButton))]
[TemplatePart(Name = "FlipButtonAlternative", Type = typeof(ToggleButton))]

Again in the CodeView at the end of the line "public class FlipPanel" type the following:

 : Control

And in the CodeView below the "{" of the line "public class FlipPanel : Control" type the following Dependancy Properties:

public static readonly DependencyProperty FrontContentProperty =
DependencyProperty.Register("FrontContent", typeof(object), 
typeof(FlipPanel), null);

public static readonly DependencyProperty BackContentProperty =
DependencyProperty.Register("BackContent", typeof(object), 
typeof(FlipPanel), null);
 
public static readonly DependencyProperty IsFlippedProperty =
DependencyProperty.Register("IsFlipped", typeof(bool),
typeof(FlipPanel), new PropertyMetadata(true));
 
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register("CornerRadius", typeof(CornerRadius),
typeof(FlipPanel), null);

See Below:

FlipPanel.cs Imports, Template and Dependancy Properties

Step 9

While still in the Code View below the "CornerRadiusProperty" declaration type the following Properties and Methods:

public object FrontContent
{
  get { return GetValue(FrontContentProperty); }
  set { SetValue(FrontContentProperty, value); }
}

public object BackContent
{
  get { return GetValue(BackContentProperty); }
  set { SetValue(BackContentProperty, value); }
}

public bool IsFlipped
{
  get { return (bool)GetValue(IsFlippedProperty); }
  set { SetValue(IsFlippedProperty, value); }
}

public CornerRadius CornerRadius
{
  get { return (CornerRadius)GetValue(CornerRadiusProperty); }
  set { SetValue(CornerRadiusProperty, value); }
}

public FlipPanel()
{
  DefaultStyleKey = typeof(FlipPanel);
}

private void ChangeVisualState(bool useTransitions)
{
  if (IsFlipped)
  {
    VisualStateManager.GoToState(this, "Normal", useTransitions);
  }
  else
  {
    VisualStateManager.GoToState(this, "Flipped", useTransitions); 
  }
}

See Below:

FlipPanel Properties and Methods

Step 10

While still in the Code View below the "}" of the "ChangeVisualState" Method type the following Event Handlers:

private void FlipButton_Click(object sender, RoutedEventArgs e)
{
  IsFlipped = !IsFlipped;
  ChangeVisualState(true);
}

public override void OnApplyTemplate()
{
  base.OnApplyTemplate();
  ToggleButton _flipButton = (ToggleButton)GetTemplateChild("FlipButton");
  if (_flipButton != null)
  {
    _flipButton.Click += FlipButton_Click;
  }
  ToggleButton _flipButtonAlt = (ToggleButton)GetTemplateChild("FlipButtonAlternative");
  if (_flipButtonAlt != null)
  {
    _flipButtonAlt.Click += FlipButton_Click;
  }
  ChangeVisualState(false);
}

See Below:

FlipPanel Event Handlers

Step 11

Select "Build Solution" from the Debug menu, see below:

Build Solution

Step 12

When the Build completes, return to the MainPage Designer View by selecting the "MainPage.xaml" Tab.
Then from the FlipPanel Controls section in the Toolbox select the FlipPanel control:

FlipPanel User Control

Step 13

Draw a FlipPanel onto the Page by dragging a FlipPanel from the Toolbox onto the Page, then in the XAML Pane between the <Grid x:Name="ContentGrid" Grid.Row="1"> and </Grid> lines, change "flippanel1" to the following:

<my:FlipPanel>
  <my:FlipPanel.FrontContent>
    <StackPanel>
      <TextBlock Margin="4" FontWeight="Bold" Text="Front Content"/>
      <Button Margin="4" Padding="4" Content="Button One"/>
      <Button Margin="4" Padding="4" Content="Button Two"/>
      <Button Margin="4" Padding="4" Content="Button Three"/>
      <Button Margin="4" Padding="4" Content="Button Four"/>
    </StackPanel>
  </my:FlipPanel.FrontContent>
  <my:FlipPanel.BackContent>
    <StackPanel>
      <TextBlock Margin="4" FontWeight="Bold" Text="Back Content"/>
      <CheckBox Margin="4" Padding="4" Content="CheckBox One"/>
      <CheckBox Margin="4" Padding="4" Content="CheckBox Two"/>
      <CheckBox Margin="4" Padding="4" Content="CheckBox Three"/>
      <CheckBox Margin="4" Padding="4" Content="CheckBox Four"/>
    </StackPanel>
  </my:FlipPanel.BackContent>
</my:FlipPanel>

XAML:

MainPage XAML Pane

Design:

MainPage Design View

Step 14

Save the Project as you have now finished the Windows Phone Silverlight application. Select the Windows Phone Emulator option then Select Debug then Start Debugging or click on Start Debugging:

Start Debugging

After you do, the following will appear in the Windows Phone Emulator after it has been loaded:

Application Running

Step 15

Tap the Round button with the Arrow to "Flip" the FlipPanel, see below:

FlipPanel Control

Step 16

You can then Stop the application by selecting the Visual Studio 2010 application window and clicking on the Stop Debugging button:

Stop Debugging

This is a simple FlipPanel Control it could be expanded to add more Properties and functionality such as being able to flip horizontally or vertically, or adding more features - make it your own!