PreviewSlider.cs 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Controls.Primitives;
  5. using System.Windows.Data;
  6. using System.Windows.Documents;
  7. using System.Windows.Input;
  8. using System.Windows.Media;
  9. using HandyControl.Data;
  10. using HandyControl.Interactivity;
  11. namespace HandyControl.Controls;
  12. [TemplatePart(Name = TrackKey, Type = typeof(Track))]
  13. [TemplatePart(Name = ThumbKey, Type = typeof(FrameworkElement))]
  14. public class PreviewSlider : Slider
  15. {
  16. private AdornerContainer _adorner;
  17. private const string TrackKey = "PART_Track";
  18. private const string ThumbKey = "PART_Thumb";
  19. private FrameworkElement _previewContent;
  20. private FrameworkElement _thumb;
  21. private TranslateTransform _transform;
  22. private Track _track;
  23. /// <summary>
  24. /// 预览内容
  25. /// </summary>
  26. public static readonly DependencyProperty PreviewContentProperty = DependencyProperty.Register(
  27. nameof(PreviewContent), typeof(object), typeof(PreviewSlider), new PropertyMetadata(default(object)));
  28. /// <summary>
  29. /// 预览内容
  30. /// </summary>
  31. public object PreviewContent
  32. {
  33. get => GetValue(PreviewContentProperty);
  34. set => SetValue(PreviewContentProperty, value);
  35. }
  36. public static readonly DependencyProperty PreviewContentOffsetProperty = DependencyProperty.Register(
  37. nameof(PreviewContentOffset), typeof(double), typeof(PreviewSlider), new PropertyMetadata(9.0));
  38. public double PreviewContentOffset
  39. {
  40. get => (double) GetValue(PreviewContentOffsetProperty);
  41. set => SetValue(PreviewContentOffsetProperty, value);
  42. }
  43. public static readonly DependencyProperty PreviewPositionProperty = DependencyProperty.RegisterAttached(
  44. "PreviewPosition", typeof(double), typeof(PreviewSlider), new FrameworkPropertyMetadata(ValueBoxes.Double0Box, FrameworkPropertyMetadataOptions.Inherits));
  45. public static void SetPreviewPosition(DependencyObject element, double value)
  46. => element.SetValue(PreviewPositionProperty, value);
  47. public static double GetPreviewPosition(DependencyObject element)
  48. => (double) element.GetValue(PreviewPositionProperty);
  49. public double PreviewPosition
  50. {
  51. get => GetPreviewPosition(_previewContent);
  52. set => SetPreviewPosition(_previewContent, value);
  53. }
  54. /// <summary>
  55. /// 值改变事件
  56. /// </summary>
  57. public static readonly RoutedEvent PreviewPositionChangedEvent =
  58. EventManager.RegisterRoutedEvent("PreviewPositionChanged", RoutingStrategy.Bubble,
  59. typeof(EventHandler<FunctionEventArgs<double>>), typeof(PreviewSlider));
  60. /// <summary>
  61. /// 值改变事件
  62. /// </summary>
  63. public event EventHandler<FunctionEventArgs<double>> PreviewPositionChanged
  64. {
  65. add => AddHandler(PreviewPositionChangedEvent, value);
  66. remove => RemoveHandler(PreviewPositionChangedEvent, value);
  67. }
  68. protected override void OnMouseMove(MouseEventArgs e)
  69. {
  70. base.OnMouseMove(e);
  71. if (_previewContent == null) return;
  72. var p = e.GetPosition(_adorner);
  73. var maximum = Maximum;
  74. var minimum = Minimum;
  75. if (Orientation == Orientation.Horizontal)
  76. {
  77. var pos = !IsDirectionReversed
  78. ? (e.GetPosition(this).X - _thumb.ActualWidth * 0.5) / _track.ActualWidth * (maximum - minimum) + minimum
  79. : (1 - (e.GetPosition(this).X - _thumb.ActualWidth * 0.5) / _track.ActualWidth) * (maximum - minimum) + minimum;
  80. if (pos > maximum || pos < 0)
  81. {
  82. if (_thumb.IsMouseCaptureWithin)
  83. {
  84. PreviewPosition = Value;
  85. }
  86. return;
  87. }
  88. _transform.X = p.X - _previewContent.ActualWidth * 0.5;
  89. _transform.Y = _thumb.TranslatePoint(new Point(), _adorner).Y - _previewContent.ActualHeight - PreviewContentOffset;
  90. PreviewPosition = _thumb.IsMouseCaptureWithin ? Value : pos;
  91. }
  92. else
  93. {
  94. var pos = !IsDirectionReversed
  95. ? (1 - (e.GetPosition(this).Y - _thumb.ActualHeight * 0.5) / _track.ActualHeight) * (maximum - minimum) + minimum
  96. : (e.GetPosition(this).Y - _thumb.ActualHeight * 0.5) / _track.ActualHeight * (maximum - minimum) + minimum;
  97. if (pos > maximum || pos < 0)
  98. {
  99. if (_thumb.IsMouseCaptureWithin)
  100. {
  101. PreviewPosition = Value;
  102. }
  103. return;
  104. }
  105. _transform.X = _thumb.TranslatePoint(new Point(), _adorner).X - _previewContent.ActualWidth - PreviewContentOffset;
  106. _transform.Y = p.Y - _previewContent.ActualHeight * 0.5;
  107. PreviewPosition = _thumb.IsMouseCaptureWithin ? Value : pos;
  108. }
  109. RaiseEvent(new FunctionEventArgs<double>(PreviewPositionChangedEvent, this)
  110. {
  111. Info = PreviewPosition
  112. });
  113. }
  114. protected override void OnMouseEnter(MouseEventArgs e)
  115. {
  116. base.OnMouseEnter(e);
  117. if (_adorner == null)
  118. {
  119. var layer = AdornerLayer.GetAdornerLayer(this);
  120. if (layer == null) return;
  121. _adorner = new AdornerContainer(layer)
  122. {
  123. Child = _previewContent
  124. };
  125. layer.Add(_adorner);
  126. }
  127. }
  128. protected override void OnMouseLeave(MouseEventArgs e)
  129. {
  130. base.OnMouseLeave(e);
  131. var layer = AdornerLayer.GetAdornerLayer(this);
  132. if (layer != null)
  133. {
  134. layer.Remove(_adorner);
  135. }
  136. else if (_adorner is { Parent: AdornerLayer parent })
  137. {
  138. parent.Remove(_adorner);
  139. }
  140. if (_adorner != null)
  141. {
  142. _adorner.Child = null;
  143. _adorner = null;
  144. }
  145. }
  146. public override void OnApplyTemplate()
  147. {
  148. base.OnApplyTemplate();
  149. var contentControl = new ContentControl
  150. {
  151. DataContext = this
  152. };
  153. contentControl.SetBinding(ContentControl.ContentProperty, new Binding(PreviewContentProperty.Name) { Source = this });
  154. _previewContent = contentControl;
  155. _track = Template.FindName(TrackKey, this) as Track;
  156. _thumb = Template.FindName(ThumbKey, this) as FrameworkElement;
  157. if (_previewContent != null)
  158. {
  159. _transform = new TranslateTransform();
  160. _previewContent.HorizontalAlignment = HorizontalAlignment.Left;
  161. _previewContent.VerticalAlignment = VerticalAlignment.Top;
  162. _previewContent.RenderTransform = _transform;
  163. }
  164. }
  165. }