completed the branch

This commit is contained in:
NaBian committed 2019-11-14 00:01:57 +08:00
1 parent ff7f88c486
commit 8b144a90de
22 files changed
+321 -364

No files matched your search

@@ -1,285 +1,76 @@
using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Windows;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Markup;
using System.Windows.Media;
using System.Windows.Media.Animation;
using HandyControl.Data;
using HandyControl.Tools;
namespace HandyControl.Controls
{
[TemplateVisualState(GroupName = PresentationGroup, Name = NormalState)]
[TemplateVisualState(GroupName = PresentationGroup, Name = DefaultTransitionState)]
[TemplatePart(Name = PreviousContentPresentationSitePartName, Type = typeof(ContentControl))]
[TemplatePart(Name = CurrentContentPresentationSitePartName, Type = typeof(ContentControl))]
[ContentProperty("Content")]
public class TransitioningContentControl : Control
public class TransitioningContentControl : ContentControl
{
private Storyboard _currentTransition;
private FrameworkElement _contentPresenter;
public TransitioningContentControl()
{
if (!DesignerProperties.GetIsInDesignMode(this))
{
DefaultStyleKey = typeof(TransitioningContentControl);
}
Loaded += TransitioningContentControl_Loaded;
IsVisibleChanged += TransitioningContentControl_IsVisibleChanged;
}
private Storyboard CurrentTransition
public static readonly DependencyProperty TransitionModeProperty = DependencyProperty.Register(
"TransitionMode", typeof(TransitionMode), typeof(TransitioningContentControl), new PropertyMetadata(default(TransitionMode), OnTransitionModeChanged));
private static void OnTransitionModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
set
{
if (_currentTransition != null)
_currentTransition.Completed -= OnTransitionCompleted;
_currentTransition = value;
if (_currentTransition != null)
_currentTransition.Completed += OnTransitionCompleted;
}
var ctl = (TransitioningContentControl) d;
ctl.StartTransition();
}
#region Events
public TransitionMode TransitionMode
{
get => (TransitionMode) GetValue(TransitionModeProperty);
set => SetValue(TransitionModeProperty, value);
}
public event RoutedEventHandler TransitionCompleted;
public static readonly DependencyProperty TransitionStoryboardProperty = DependencyProperty.Register(
"TransitionStoryboard", typeof(Storyboard), typeof(TransitioningContentControl), new PropertyMetadata(default(Storyboard)));
#endregion Events
public Storyboard TransitionStoryboard
{
get => (Storyboard) GetValue(TransitionStoryboardProperty);
set => SetValue(TransitionStoryboardProperty, value);
}
private void TransitioningContentControl_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e) => StartTransition();
private void TransitioningContentControl_Loaded(object sender, RoutedEventArgs e) => StartTransition();
private void StartTransition()
{
if (Visibility != Visibility.Visible || _contentPresenter == null) return;
(TransitionStoryboard ?? ResourceHelper.GetResource<Storyboard>($"{TransitionMode.ToString()}Transition"))?.Begin(_contentPresenter);
}
public override void OnApplyTemplate()
{
if (DesignerProperties.GetIsInDesignMode(this)) return;
if (IsTransitioning)
AbortTransition();
base.OnApplyTemplate();
PreviousContentPresentationSite =
GetTemplateChild(PreviousContentPresentationSitePartName) as ContentPresenter;
CurrentContentPresentationSite =
GetTemplateChild(CurrentContentPresentationSitePartName) as ContentPresenter;
if (CurrentContentPresentationSite != null)
CurrentContentPresentationSite.Content = Content;
var transition = GetStoryboard(Transition);
CurrentTransition = transition;
if (transition == null)
_contentPresenter = VisualTreeHelper.GetChild(this, 0) as FrameworkElement;
if (_contentPresenter != null)
{
Transition = DefaultTransitionState;
throw new ArgumentException("TransitioningContentControl_TransitionNotFound");
}
VisualStateManager.GoToState(this, NormalState, false);
VisualStateManager.GoToState(this, Transition, true);
}
public static readonly DependencyProperty ContentProperty = DependencyProperty.Register(
"Content", typeof(object), typeof(TransitioningContentControl), new PropertyMetadata(default(object), OnContentChanged));
private static void OnContentChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var ctl = (TransitioningContentControl) d;
ctl.StartTransition(e.OldValue, e.NewValue);
}
public static readonly DependencyProperty ContentTemplateProperty = DependencyProperty.Register(
"ContentTemplate", typeof(DataTemplate), typeof(TransitioningContentControl), new PropertyMetadata(default(DataTemplate)));
public DataTemplate ContentTemplate
{
get => (DataTemplate) GetValue(ContentTemplateProperty);
set => SetValue(ContentTemplateProperty, value);
}
public object Content
{
get => GetValue(ContentProperty);
set => SetValue(ContentProperty, value);
}
[SuppressMessage("Microsoft.Usage", "CA1801:ReviewUnusedParameters", MessageId = "newContent", Justification = "Should be used in the future.")]
private void StartTransition(object oldContent, object newContent)
{
if (CurrentContentPresentationSite != null && PreviousContentPresentationSite != null)
{
CurrentContentPresentationSite.Content = newContent;
PreviousContentPresentationSite.Content = oldContent;
if (!IsTransitioning || RestartTransitionOnContentChange)
_contentPresenter.RenderTransformOrigin = new Point(0.5, 0.5);
_contentPresenter.RenderTransform = new TransformGroup
{
IsTransitioning = true;
VisualStateManager.GoToState(this, NormalState, false);
VisualStateManager.GoToState(this, Transition, true);
}
Children =
{
new ScaleTransform(),
new SkewTransform(),
new RotateTransform(),
new TranslateTransform()
}
};
}
}
private void OnTransitionCompleted(object sender, EventArgs e)
{
AbortTransition();
var handler = TransitionCompleted;
handler?.Invoke(this, new RoutedEventArgs());
}
public void AbortTransition()
{
VisualStateManager.GoToState(this, NormalState, false);
IsTransitioning = false;
if (PreviousContentPresentationSite != null)
PreviousContentPresentationSite.Content = null;
}
private Storyboard GetStoryboard(string newTransition)
{
var presentationGroup = VisualHelper.TryGetVisualStateGroup(this, PresentationGroup);
Storyboard newStoryboard = null;
if (presentationGroup != null)
newStoryboard = presentationGroup.States
.OfType<VisualState>()
.Where(state => state.Name == newTransition)
.Select(state => state.Storyboard)
.FirstOrDefault();
return newStoryboard;
}
#region Visual state names
private const string PresentationGroup = "PresentationStates";
private const string NormalState = "Normal";
public const string DefaultTransitionState = "DefaultTransition";
#endregion Visual state names
#region Template part names
internal const string PreviousContentPresentationSitePartName = "PreviousContentPresentationSite";
internal const string CurrentContentPresentationSitePartName = "CurrentContentPresentationSite";
#endregion Template part names
#region TemplateParts
private ContentPresenter CurrentContentPresentationSite { get; set; }
private ContentPresenter PreviousContentPresentationSite { get; set; }
#endregion TemplateParts
#region public bool IsTransitioning
private bool _allowIsTransitioningWrite;
public bool IsTransitioning
{
get => (bool)GetValue(IsTransitioningProperty);
private set
{
_allowIsTransitioningWrite = true;
SetValue(IsTransitioningProperty, value);
_allowIsTransitioningWrite = false;
}
}
public static readonly DependencyProperty IsTransitioningProperty =
DependencyProperty.Register(
"IsTransitioning",
typeof(bool),
typeof(TransitioningContentControl),
new PropertyMetadata(OnIsTransitioningPropertyChanged));
private static void OnIsTransitioningPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source = (TransitioningContentControl)d;
if (!source._allowIsTransitioningWrite)
{
source.IsTransitioning = (bool)e.OldValue;
throw new InvalidOperationException("TransitiotioningContentControl_IsTransitioningReadOnly");
}
}
#endregion public bool IsTransitioning
#region public string Transition
public string Transition
{
get => GetValue(TransitionProperty) as string;
set => SetValue(TransitionProperty, value);
}
public static readonly DependencyProperty TransitionProperty =
DependencyProperty.Register(
"Transition",
typeof(string),
typeof(TransitioningContentControl),
new PropertyMetadata(DefaultTransitionState, OnTransitionPropertyChanged));
private static void OnTransitionPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var source = (TransitioningContentControl)d;
var oldTransition = e.OldValue as string;
var newTransition = e.NewValue as string;
if (source.IsTransitioning)
source.AbortTransition();
var newStoryboard = source.GetStoryboard(newTransition);
if (newStoryboard == null)
if (VisualHelper.TryGetVisualStateGroup(source, PresentationGroup) == null)
{
source.CurrentTransition = null;
}
else
{
source.SetValue(TransitionProperty, oldTransition);
throw new ArgumentException(
"TransitioningContentControl_TransitionNotFound");
}
else
source.CurrentTransition = newStoryboard;
}
#endregion public string Transition
#region public bool RestartTransitionOnContentChange
public bool RestartTransitionOnContentChange
{
get => (bool)GetValue(RestartTransitionOnContentChangeProperty);
set => SetValue(RestartTransitionOnContentChangeProperty, value);
}
public static readonly DependencyProperty RestartTransitionOnContentChangeProperty =
DependencyProperty.Register(
"RestartTransitionOnContentChange",
typeof(bool),
typeof(TransitioningContentControl),
new PropertyMetadata(ValueBoxes.FalseBox, OnRestartTransitionOnContentChangePropertyChanged));
private static void OnRestartTransitionOnContentChangePropertyChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
((TransitioningContentControl)d).OnRestartTransitionOnContentChangeChanged((bool)e.OldValue,
(bool)e.NewValue);
}
protected virtual void OnRestartTransitionOnContentChangeChanged(bool oldValue, bool newValue)
{
}
#endregion public bool RestartTransitionOnContentChange
}
}
@@ -0,0 +1,16 @@
namespace HandyControl.Data
{
public enum TransitionMode
{
Right2Left,
Left2Right,
Bottom2Top,
Top2Bottom,
Right2LeftWithFade,
Left2RightWithFade,
Bottom2TopWithFade,
Top2BottomWithFade,
Fade,
Custom
}
}
@@ -41,6 +41,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\HitMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\ShowAnimation.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\NotifyIconInfoType.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Data\Enum\TransitionMode.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\CloseWindowCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Interactivity\Commands\OpenLinkCommand.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Media\Animation\DiscreteGeometryKeyFrame.cs" />
@@ -1,105 +1,76 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:HandyControl.Controls">
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Style TargetType="controls:TransitioningContentControl">
<Setter Property="IsTabStop" Value="False" />
<Setter Property="Focusable" Value="False"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="Transition" Value="DefaultTransition" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:TransitioningContentControl">
<controls:SimplePanel>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="PresentationStates">
<VisualState x:Name="DefaultTransition">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimation BeginTime="00:00:00" Duration="00:00:00.500" Storyboard.TargetName="CurrentContentPresentationSite" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)" From="50" To="0">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut" />
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.100" Value="0" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Normal">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="UpTransition">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CurrentContentPresentationSite" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="30" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="-30" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="DownTransition">
<Storyboard>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="CurrentContentPresentationSite" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="-40" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="1" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="0" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="PreviousContentPresentationSite" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0" />
<SplineDoubleKeyFrame KeyTime="00:00:00.300" Value="40" />
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<ContentPresenter x:Name="PreviousContentPresentationSite" Content="{x:Null}" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
<ContentPresenter x:Name="CurrentContentPresentationSite" ContentTemplate="{TemplateBinding ContentTemplate}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}">
<ContentPresenter.RenderTransform>
<TransformGroup>
<ScaleTransform />
<SkewTransform />
<RotateTransform />
<TranslateTransform />
</TransformGroup>
</ContentPresenter.RenderTransform>
</ContentPresenter>
</controls:SimplePanel>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Storyboard x:Key="Right2LeftTransition" x:Shared="False">
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Left2RightTransition" x:Shared="False">
<DoubleAnimation From="-50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Bottom2TopTransition" x:Shared="False">
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Top2BottomTransition" x:Shared="False">
<DoubleAnimation From="-50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Right2LeftWithFadeTransition" x:Shared="False">
<DoubleAnimation From="0" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.Opacity)"/>
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Left2RightWithFadeTransition" x:Shared="False">
<DoubleAnimation From="0" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.Opacity)"/>
<DoubleAnimation From="-50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Bottom2TopWithFadeTransition" x:Shared="False">
<DoubleAnimation From="0" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.Opacity)"/>
<DoubleAnimation From="50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="Top2BottomWithFadeTransition" x:Shared="False">
<DoubleAnimation From="0" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.Opacity)"/>
<DoubleAnimation From="-50" To="0" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.Y)">
<DoubleAnimation.EasingFunction>
<CubicEase EasingMode="EaseOut"/>
</DoubleAnimation.EasingFunction>
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="FadeTransition" x:Shared="False">
<DoubleAnimation From="0" To="1" Duration="0:0:0.4" Storyboard.TargetProperty="(UIElement.Opacity)"/>
</Storyboard>
</ResourceDictionary>