Skip to content

Commit

Permalink
Merge pull request #472 from Amrykid/flipview
Browse files Browse the repository at this point in the history
Implemented a FlipView control.
  • Loading branch information
AzureKitsune committed May 25, 2013
2 parents 258f462 + b8eaa32 commit 9453540
Show file tree
Hide file tree
Showing 6 changed files with 402 additions and 1 deletion.
269 changes: 269 additions & 0 deletions MahApps.Metro/Controls/FlipView.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,269 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace MahApps.Metro.Controls
{
[TemplatePart(Name = "PART_Presenter", Type = typeof(TransitioningContentControl))]
[TemplatePart(Name = "PART_BackButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_ForwardButton", Type = typeof(Button))]
[TemplatePart(Name = "PART_BannerGrid", Type = typeof(Grid))]
[TemplatePart(Name = "PART_BannerLabel", Type = typeof(Label))]
public class FlipView : Selector
{
private const string PART_Presenter = "PART_Presenter";
private const string PART_BackButton = "PART_BackButton";
private const string PART_ForwardButton = "PART_ForwardButton";
private const string PART_BannerGrid = "PART_BannerGrid";
private const string PART_BannerLabel = "PART_BannerLabel";

private TransitioningContentControl presenter = null;
private Button backButton = null;
private Button forwardButton = null;
private Grid bannerGrid = null;
private Label bannerLabel = null;

private Storyboard ShowBannerStoryboard = null;
private Storyboard HideBannerStoryboard = null;
private Storyboard HideControlStoryboard = null;
private Storyboard ShowControlStoryboard = null;

private EventHandler HideControlStoryboard_CompletedHandler = null;

static FlipView()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(FlipView), new FrameworkPropertyMetadata(typeof(FlipView)));
}
public FlipView()
{
this.Unloaded += FlipView_Unloaded;
}

void FlipView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
DetectControlButtonsStatus();
}

private void DetectControlButtonsStatus()
{
if (Items.Count > 0)
{
if (SelectedIndex == 0)
{
backButton.Visibility = System.Windows.Visibility.Hidden;
forwardButton.Visibility = System.Windows.Visibility.Visible;
}
else
if (SelectedIndex == Items.Count - 1)
{
backButton.Visibility = System.Windows.Visibility.Visible;
forwardButton.Visibility = System.Windows.Visibility.Hidden;
}
else
{
backButton.Visibility = System.Windows.Visibility.Visible;
forwardButton.Visibility = System.Windows.Visibility.Visible;
}
}
else
{
backButton.Visibility = System.Windows.Visibility.Hidden;
forwardButton.Visibility = System.Windows.Visibility.Hidden;
}
}

void FlipView_Unloaded(object sender, RoutedEventArgs e)
{
this.Unloaded -= FlipView_Unloaded;
this.SelectionChanged -= FlipView_SelectionChanged;

backButton.Click -= backButton_Click;
forwardButton.Click -= forwardButton_Click;

if (HideControlStoryboard_CompletedHandler != null)
HideControlStoryboard.Completed -= HideControlStoryboard_CompletedHandler;
}

public override void OnApplyTemplate()
{
base.OnApplyTemplate();

presenter = this.Template.FindName(PART_Presenter, this) as TransitioningContentControl;
backButton = this.Template.FindName(PART_BackButton, this) as Button;
forwardButton = this.Template.FindName(PART_ForwardButton, this) as Button;
bannerGrid = this.Template.FindName(PART_BannerGrid, this) as Grid;
bannerLabel = this.Template.FindName(PART_BannerLabel, this) as Label;

backButton.Click += backButton_Click;
forwardButton.Click += forwardButton_Click;

this.SelectionChanged += FlipView_SelectionChanged;

ShowBannerStoryboard = ((Storyboard)this.Template.Resources["ShowBannerStoryboard"]).Clone();
HideBannerStoryboard = ((Storyboard)this.Template.Resources["HideBannerStoryboard"]).Clone();

ShowControlStoryboard = ((Storyboard)this.Template.Resources["ShowControlStoryboard"]).Clone();
HideControlStoryboard = ((Storyboard)this.Template.Resources["HideControlStoryboard"]).Clone();

DetectControlButtonsStatus();


ShowBanner();
}

void forwardButton_Click(object sender, RoutedEventArgs e)
{
GoForward();
}

void backButton_Click(object sender, RoutedEventArgs e)
{
GoBack();
}

public void GoBack()
{
if (SelectedIndex > 0)
{
presenter.Transition = "RightReplaceTransition";
SelectedIndex--;
}
}

public void GoForward()
{
if (SelectedIndex < Items.Count - 1)
{
presenter.Transition = "LeftReplaceTransition";
SelectedIndex++;
}
}

private void ShowBanner()
{
if (IsBannerEnabled)
bannerGrid.BeginStoryboard(ShowBannerStoryboard);
bannerLabel.Content = BannerText;
}

private void HideBanner()
{
if (this.Height > 0.0)
bannerGrid.BeginStoryboard(HideBannerStoryboard);
}

private string _lastBannerText = null;
public static readonly DependencyProperty BannerTextProperty =
DependencyProperty.Register("BannerText", typeof(string), typeof(FlipView), new PropertyMetadata("Banner", new PropertyChangedCallback((d, e) =>
{
if (e.OldValue != e.NewValue)
ExecuteWhenLoaded(((FlipView)d), () =>
((FlipView)d).ChangeBannerText());
})));

public string BannerText
{
get { return (string)GetValue(BannerTextProperty); }
set
{
//SetValue(BannerTextProperty, value);
ChangeBannerText(value);
}
}

private void ChangeBannerText(string value = null)
{
if (IsBannerEnabled)
{
if (HideControlStoryboard_CompletedHandler != null)
HideControlStoryboard.Completed -= HideControlStoryboard_CompletedHandler;

HideControlStoryboard_CompletedHandler = new EventHandler((sender, e) =>
{
SetValue(BannerTextProperty, value);
HideControlStoryboard.Completed -= HideControlStoryboard_CompletedHandler;
bannerLabel.Content = value != null ? value : BannerText;
bannerLabel.BeginStoryboard(ShowControlStoryboard, HandoffBehavior.SnapshotAndReplace);
});


HideControlStoryboard.Completed += HideControlStoryboard_CompletedHandler;

bannerLabel.BeginStoryboard(HideControlStoryboard, HandoffBehavior.SnapshotAndReplace);
}
else
ExecuteWhenLoaded(this, () =>
{
bannerLabel.Content = value != null ? value : BannerText;
});
}

public static readonly DependencyProperty IsBannerEnabledProperty =
DependencyProperty.Register("IsBannerEnabled", typeof(bool), typeof(FlipView), new UIPropertyMetadata(true, new PropertyChangedCallback((d, e) =>
{
var flipview = ((FlipView)d);
if (!flipview.IsLoaded)
{
//wait to be loaded?
ExecuteWhenLoaded(flipview, () =>
{
flipview.ApplyTemplate();
if ((bool)e.NewValue)
flipview.ShowBanner();
else
flipview.HideBanner();
});
}
else
{
if ((bool)e.NewValue)
flipview.ShowBanner();
else
flipview.HideBanner();
}
})));

public bool IsBannerEnabled
{
get { return (bool)GetValue(IsBannerEnabledProperty); }
set
{
SetValue(IsBannerEnabledProperty, value);
}
}

private static void ExecuteWhenLoaded(FlipView flipview, Action body)
{
if (flipview.IsLoaded)
body();
else
{
RoutedEventHandler handler = null;
handler = new RoutedEventHandler((o, a) =>
{
flipview.Loaded -= handler;
body();
});

flipview.Loaded += handler;
}
}
}
}
5 changes: 5 additions & 0 deletions MahApps.Metro/MahApps.Metro.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@
<Compile Include="Behaviours\StylizedBehaviorCollection.cs" />
<Compile Include="Behaviours\WindowsSettingBehaviour.cs" />
<Compile Include="Controls\ClosingWindowEventHandlerArgs.cs" />
<Compile Include="Controls\FlipView.cs" />
<Compile Include="Controls\Flyout.cs" />
<Compile Include="Controls\Glow.cs" />
<Compile Include="Controls\GlowDirection.cs" />
Expand Down Expand Up @@ -268,6 +269,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\FlipView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Themes\Flyout.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
Expand Down
89 changes: 89 additions & 0 deletions MahApps.Metro/Themes/FlipView.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Controls="clr-namespace:MahApps.Metro.Controls">


<ControlTemplate x:Key="FlipViewTemplate" TargetType="{x:Type Controls:FlipView}">
<Grid x:Name="root">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<Grid x:Name="ControlGrid" Panel.ZIndex="5">
<Button x:Name="PART_BackButton" VerticalAlignment="Center" HorizontalAlignment="Left" Style="{DynamicResource ControlButton}">
<Path Width="16" Height="18" Canvas.Left="15.9063" Canvas.Top="14.75" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 22.6563,23.75L 24.6563,25.75L 31.9063,32.75L 25.4063,32.75L 15.9063,23.75L 25.4063,14.75L 31.9063,14.75L 24.6563,21.75L 22.6563,23.75 Z " />
</Button>
<Button x:Name="PART_ForwardButton" VerticalAlignment="Center" HorizontalAlignment="Right" Style="{DynamicResource ControlButton}">
<Path Width="16" Height="18" Canvas.Left="15.9063" Canvas.Top="14.75" Stretch="Fill" Fill="{DynamicResource BlackBrush}" Data="F1 M 25.1563,23.75L 23.1563,21.75L 15.9063,14.75L 22.4063,14.75L 31.9063,23.75L 22.4063,32.75L 15.9063,32.75L 23.1563,25.75L 25.1563,23.75 Z " />
</Button>

<Grid VerticalAlignment="Bottom" Height="0" x:Name="PART_BannerGrid" Panel.ZIndex="6" Opacity="0.9">
<Grid.Background>
<SolidColorBrush Color="{DynamicResource BlackColor}"/>
</Grid.Background>
<Label FontFamily="{TemplateBinding FontFamily}" FontSize="{TemplateBinding FontSize}" x:Name="PART_BannerLabel">
<Label.Foreground>
<SolidColorBrush Color="{DynamicResource WhiteColor}" />
</Label.Foreground>
</Label>
</Grid>
</Grid>
<Controls:TransitioningContentControl Content="{TemplateBinding SelectedItem}"
ContentTemplate="{TemplateBinding ItemTemplate}" x:Name="PART_Presenter" Panel.ZIndex="1"/>
</Grid>
</Border>
</Grid>
<ControlTemplate.Resources>
<Style TargetType="Button" x:Key="ControlButton">
<Setter Property="Height" Value="30"/>
<Setter Property="Width" Value="50"/>
<Setter Property="Opacity" Value="0.4"/>
<Setter Property="Panel.ZIndex" Value="5"/>
<Setter Property="Background">
<Setter.Value>
<SolidColorBrush Color="{DynamicResource WhiteColor}"/>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="{DynamicResource NormalForegroundBrush}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border BorderBrush="{TemplateBinding Background}" Padding="1" CornerRadius="4">
<Grid Background="{TemplateBinding Background}">
<Label FontFamily="Marlett" Foreground="{DynamicResource NormalForegroundBrush}" FontSize="17" HorizontalAlignment="Center" VerticalAlignment="Center">
<ContentPresenter ContentSource="Content"/>
</Label>

</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Opacity" Value="1.0"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Storyboard x:Key="ShowBannerStoryboard">
<DoubleAnimation From="0.0" To="30.0" AccelerationRatio="1.0" SpeedRatio="2.5" Storyboard.TargetProperty="Height"/>
</Storyboard>
<Storyboard x:Key="HideBannerStoryboard">
<DoubleAnimation From="30.0" To="0.0" AccelerationRatio="1.0" SpeedRatio="2.5" Storyboard.TargetProperty="Height"/>
</Storyboard>
<Storyboard x:Key="HideControlStoryboard">
<DoubleAnimation From="1.0" To="0.0" AccelerationRatio="1.0" SpeedRatio="2.5" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
<Storyboard x:Key="ShowControlStoryboard">
<DoubleAnimation From="0.0" To="1.0" AccelerationRatio="1.0" SpeedRatio="2.5" Storyboard.TargetProperty="Opacity"/>
</Storyboard>
</ControlTemplate.Resources>
</ControlTemplate>
<Style TargetType="{x:Type Controls:FlipView}">
<Setter Property="MinHeight" Value="100"/>
<Setter Property="MinWidth" Value="100"/>
<Setter Property="FontSize" Value="16"/>
<Setter Property="Selector.IsSynchronizedWithCurrentItem" Value="True"/>
<Setter Property="Template" Value="{StaticResource FlipViewTemplate}"/>
</Style>
</ResourceDictionary>
3 changes: 2 additions & 1 deletion MahApps.Metro/Themes/Generic.xaml
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" />
<ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />

<ResourceDictionary Source="/MahApps.Metro;component/Themes/AppBarButton.xaml" />
<ResourceDictionary Source="/MahApps.Metro;component/Themes/FlipView.xaml" />
<ResourceDictionary Source="/MahApps.Metro;component/Themes/Flyout.xaml" />
<ResourceDictionary Source="/MahApps.Metro;component/Themes/MetroContentControl.xaml" />
<ResourceDictionary Source="/MahApps.Metro;component/Themes/MetroImage.xaml" />
Expand Down
Loading

0 comments on commit 9453540

Please sign in to comment.