SlidingTabContainer.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. using System.Windows;
  2. using System.Windows.Controls;
  3. using System.Windows.Media;
  4. using System.Windows.Media.Animation;
  5. using HandyControl.Tools;
  6. namespace HandyControl.Controls;
  7. [TemplatePart(Name = ElementSliding, Type = typeof(FrameworkElement))]
  8. public class SlidingTabContainer : ContentControl
  9. {
  10. private const string ElementSliding = "PART_Sliding";
  11. private FrameworkElement _sliding = new();
  12. private System.Windows.Controls.TabControl _tabControl;
  13. public SlidingTabContainer()
  14. {
  15. Loaded += OnLoaded;
  16. }
  17. private void OnLoaded(object sender, RoutedEventArgs e)
  18. {
  19. Loaded -= OnLoaded;
  20. OnSelectionChanged(null, null);
  21. }
  22. public override void OnApplyTemplate()
  23. {
  24. if (_tabControl is not null)
  25. {
  26. _tabControl.SelectionChanged -= OnSelectionChanged;
  27. }
  28. base.OnApplyTemplate();
  29. _tabControl = VisualHelper.GetParent<System.Windows.Controls.TabControl>(this);
  30. _sliding = GetTemplateChild(ElementSliding) as FrameworkElement;
  31. if (_tabControl is not null)
  32. {
  33. _tabControl.SelectionChanged += OnSelectionChanged;
  34. if (IsLoaded)
  35. {
  36. OnSelectionChanged(null, null);
  37. }
  38. }
  39. }
  40. protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
  41. {
  42. base.OnRenderSizeChanged(sizeInfo);
  43. if (_tabControl is null)
  44. {
  45. return;
  46. }
  47. OnSelectionChanged(null, null);
  48. }
  49. private void OnSelectionChanged(object sender, SelectionChangedEventArgs e)
  50. {
  51. if (_sliding is null || !IsLoaded)
  52. {
  53. return;
  54. }
  55. if (_tabControl.ItemContainerGenerator.ContainerFromItem(_tabControl.SelectedItem) is not System.Windows.Controls.TabItem tabItem)
  56. {
  57. return;
  58. }
  59. var offset = VisualTreeHelper.GetOffset(tabItem);
  60. var tabWidth = tabItem.ActualWidth;
  61. var tabHeight = tabItem.ActualHeight;
  62. var useAnimation = _sliding.Width > 0 && _sliding.Height > 0;
  63. if (useAnimation)
  64. {
  65. var storyboard = new Storyboard();
  66. var easingFuction = new PowerEase
  67. {
  68. EasingMode = EasingMode.EaseOut,
  69. };
  70. var widthAnimation = AnimationHelper.CreateAnimation(tabWidth);
  71. widthAnimation.EasingFunction = easingFuction;
  72. Storyboard.SetTarget(widthAnimation, _sliding);
  73. Storyboard.SetTargetProperty(widthAnimation, new PropertyPath(WidthProperty.Name));
  74. storyboard.Children.Add(widthAnimation);
  75. var heightAnimation = AnimationHelper.CreateAnimation(tabHeight);
  76. heightAnimation.EasingFunction = easingFuction;
  77. Storyboard.SetTarget(heightAnimation, _sliding);
  78. Storyboard.SetTargetProperty(heightAnimation, new PropertyPath(HeightProperty.Name));
  79. storyboard.Children.Add(heightAnimation);
  80. var xAnimation = AnimationHelper.CreateAnimation(offset.X);
  81. xAnimation.EasingFunction = easingFuction;
  82. Storyboard.SetTarget(xAnimation, _sliding);
  83. Storyboard.SetTargetProperty(xAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.X)"));
  84. storyboard.Children.Add(xAnimation);
  85. var yAnimation = AnimationHelper.CreateAnimation(offset.Y);
  86. yAnimation.EasingFunction = easingFuction;
  87. Storyboard.SetTarget(yAnimation, _sliding);
  88. Storyboard.SetTargetProperty(yAnimation, new PropertyPath("(UIElement.RenderTransform).(TranslateTransform.Y)"));
  89. storyboard.Children.Add(yAnimation);
  90. storyboard.Begin();
  91. }
  92. else
  93. {
  94. _sliding.Width = tabItem.ActualWidth;
  95. _sliding.Height = tabItem.ActualHeight;
  96. _sliding.RenderTransform = new TranslateTransform(offset.X, offset.Y);
  97. }
  98. }
  99. }