using System; using System.Collections.ObjectModel; using System.ComponentModel; using System.Linq; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace MaterialDesignThemes.Wpf.Transitions { public class TransitioningContentBase : ContentControl, ITransitionEffectSubject { public const string MatrixTransformPartName = "PART_MatrixTransform"; public const string RotateTransformPartName = "PART_RotateTransform"; public const string ScaleTransformPartName = "PART_ScaleTransform"; public const string SkewTransformPartName = "PART_SkewTransform"; public const string TranslateTransformPartName = "PART_TranslateTransform"; private MatrixTransform _matrixTransform; private RotateTransform _rotateTransform; private ScaleTransform _scaleTransform; private SkewTransform _skewTransform; private TranslateTransform _translateTransform; private bool _isOpeningEffectPending = false; static TransitioningContentBase() { DefaultStyleKeyProperty.OverrideMetadata(typeof (TransitioningContentBase), new FrameworkPropertyMetadata(typeof (TransitioningContentBase))); } public TransitioningContentBase() { NameScope.SetNameScope(this, new NameScope()); } public override void OnApplyTemplate() { _matrixTransform = GetTemplateChild(MatrixTransformPartName) as MatrixTransform; _rotateTransform = GetTemplateChild(RotateTransformPartName) as RotateTransform; _scaleTransform = GetTemplateChild(ScaleTransformPartName) as ScaleTransform; _skewTransform = GetTemplateChild(SkewTransformPartName) as SkewTransform; _translateTransform = GetTemplateChild(TranslateTransformPartName) as TranslateTransform; UnregisterNames(MatrixTransformPartName, RotateTransformPartName, ScaleTransformPartName, SkewTransformPartName, TranslateTransformPartName); if (_matrixTransform != null) RegisterName(MatrixTransformPartName, _matrixTransform); if (_rotateTransform != null) RegisterName(RotateTransformPartName, _rotateTransform); if (_scaleTransform != null) RegisterName(ScaleTransformPartName, _scaleTransform); if (_skewTransform != null) RegisterName(SkewTransformPartName, _skewTransform); if (_translateTransform != null) RegisterName(TranslateTransformPartName, _translateTransform); base.OnApplyTemplate(); RunOpeningEffects(); } private void UnregisterNames(params string[] names) { foreach (var name in names.Where(n => FindName(n) != null)) { UnregisterName(name); } } public static readonly DependencyProperty OpeningEffectProperty = DependencyProperty.Register("OpeningEffect", typeof (TransitionEffectBase), typeof (TransitioningContentBase), new PropertyMetadata(default(TransitionEffectBase))); /// /// Gets or sets the transition to run when the content is loaded and made visible. /// [TypeConverter(typeof(TransitionEffectTypeConverter))] public TransitionEffectBase OpeningEffect { get { return (TransitionEffectBase) GetValue(OpeningEffectProperty); } set { SetValue(OpeningEffectProperty, value); } } public static readonly DependencyProperty OpeningEffectsOffsetProperty = DependencyProperty.Register( "OpeningEffectsOffset", typeof (TimeSpan), typeof (TransitioningContentBase), new PropertyMetadata(default(TimeSpan))); /// /// Delay offset to be applied to all opening effect transitions. /// public TimeSpan OpeningEffectsOffset { get { return (TimeSpan) GetValue(OpeningEffectsOffsetProperty); } set { SetValue(OpeningEffectsOffsetProperty, value); } } /// /// Allows multiple transition effects to be combined and run upon the content loading or being made visible. /// public ObservableCollection OpeningEffects { get; } = new ObservableCollection(); string ITransitionEffectSubject.MatrixTransformName => MatrixTransformPartName; string ITransitionEffectSubject.RotateTransformName => RotateTransformPartName; string ITransitionEffectSubject.ScaleTransformName => ScaleTransformPartName; string ITransitionEffectSubject.SkewTransformName => SkewTransformPartName; string ITransitionEffectSubject.TranslateTransformName => TranslateTransformPartName; TimeSpan ITransitionEffectSubject.Offset => OpeningEffectsOffset; protected virtual void RunOpeningEffects() { if (!IsLoaded || _matrixTransform == null) { _isOpeningEffectPending = true; return; } _isOpeningEffectPending = false; var storyboard = new Storyboard(); var openingEffect = OpeningEffect?.Build(this); if (openingEffect != null) storyboard.Children.Add(openingEffect); foreach (var effect in OpeningEffects.Select(e => e.Build(this)).Where(tl => tl != null)) { storyboard.Children.Add(effect); } storyboard.Begin(this); } } }