RopeEquipmentControl.xaml.cs 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. using System;
  2. using System.Windows;
  3. using System.Windows.Controls;
  4. using System.Windows.Media;
  5. using System.Windows.Media.Animation;
  6. namespace SWRIS.Controls
  7. {
  8. /// <summary>
  9. /// RopeControl.xaml 的交互逻辑
  10. /// </summary>
  11. public partial class RopeEquipmentControl : UserControl
  12. {
  13. private Canvas _ropeCanvas; // 添加Canvas引用
  14. private readonly Storyboard _animationStoryboard;
  15. public RopeEquipmentControl()
  16. {
  17. InitializeComponent();
  18. // 初始化动画
  19. _animationStoryboard = (Storyboard)Resources["RopeAnimation"];
  20. // 设置初始动画值
  21. UpdateAnimationValues();
  22. // 订阅SizeChanged事件
  23. SizeChanged += RopeEquipmentControl_SizeChanged;
  24. // 订阅Loaded事件,确保控件加载完成后获取正确的尺寸
  25. Loaded += RopeEquipmentControl_Loaded;
  26. }
  27. #region 依赖属性
  28. // 绳索高度
  29. public static readonly DependencyProperty RopeHeightProperty =
  30. DependencyProperty.Register("RopeHeight", typeof(double), typeof(RopeEquipmentControl),
  31. new PropertyMetadata(900.0));
  32. // 绳索图片
  33. public static readonly DependencyProperty RopeImageSourceProperty =
  34. DependencyProperty.Register("RopeImageSource", typeof(ImageSource), typeof(RopeEquipmentControl));
  35. // 设备图片
  36. public static readonly DependencyProperty EquipmentImageSourceProperty =
  37. DependencyProperty.Register("EquipmentImageSource", typeof(ImageSource), typeof(RopeEquipmentControl));
  38. // 是否运行动画
  39. public static readonly DependencyProperty IsAnimationRunningProperty =
  40. DependencyProperty.Register("IsAnimationRunning", typeof(bool), typeof(RopeEquipmentControl),
  41. new PropertyMetadata(false, OnIsAnimationRunningChanged));
  42. // 动画方向(正向/反向)
  43. public static readonly DependencyProperty IsAnimationReversedProperty =
  44. DependencyProperty.Register("IsAnimationReversed", typeof(bool), typeof(RopeEquipmentControl),
  45. new PropertyMetadata(false, OnAnimationDirectionChanged));
  46. // 动画速度(秒)
  47. public static readonly DependencyProperty AnimationDurationProperty =
  48. DependencyProperty.Register("AnimationDuration", typeof(double), typeof(RopeEquipmentControl),
  49. new PropertyMetadata(0.5, OnAnimationDurationChanged));
  50. // 数据面板位置
  51. public static readonly DependencyProperty PanelMarginProperty =
  52. DependencyProperty.Register("PanelMargin", typeof(Thickness), typeof(RopeEquipmentControl));
  53. // 数据面板文字大小
  54. public static readonly DependencyProperty PanelNameFontSizeProperty =
  55. DependencyProperty.Register("PanelNameFontSize", typeof(double), typeof(RopeEquipmentControl),
  56. new PropertyMetadata(28d));
  57. // 数据面板文字大小
  58. public static readonly DependencyProperty PanelValueFontSizeProperty =
  59. DependencyProperty.Register("PanelValueFontSize", typeof(double), typeof(RopeEquipmentControl),
  60. new PropertyMetadata(28d));
  61. // 设备图片位置
  62. public static readonly DependencyProperty EquipmentTopPositionProperty =
  63. DependencyProperty.Register("EquipmentTopPosition", typeof(double), typeof(RopeEquipmentControl));
  64. #endregion
  65. #region 属性包装器
  66. public double RopeHeight
  67. {
  68. get => (double)GetValue(RopeHeightProperty);
  69. set => SetValue(RopeHeightProperty, value);
  70. }
  71. public ImageSource RopeImageSource
  72. {
  73. get => (ImageSource)GetValue(RopeImageSourceProperty);
  74. set => SetValue(RopeImageSourceProperty, value);
  75. }
  76. public ImageSource EquipmentImageSource
  77. {
  78. get => (ImageSource)GetValue(EquipmentImageSourceProperty);
  79. set => SetValue(EquipmentImageSourceProperty, value);
  80. }
  81. public bool IsAnimationRunning
  82. {
  83. get => (bool)GetValue(IsAnimationRunningProperty);
  84. set => SetValue(IsAnimationRunningProperty, value);
  85. }
  86. public bool IsAnimationReversed
  87. {
  88. get => (bool)GetValue(IsAnimationReversedProperty);
  89. set => SetValue(IsAnimationReversedProperty, value);
  90. }
  91. public double AnimationDuration
  92. {
  93. get => (double)GetValue(AnimationDurationProperty);
  94. set => SetValue(AnimationDurationProperty, value);
  95. }
  96. public Thickness PanelMargin
  97. {
  98. get => (Thickness)GetValue(PanelMarginProperty);
  99. set => SetValue(PanelMarginProperty, value);
  100. }
  101. public double PanelNameFontSize
  102. {
  103. get => (double)GetValue(PanelNameFontSizeProperty);
  104. set => SetValue(PanelNameFontSizeProperty, value);
  105. }
  106. public double PanelValueFontSize
  107. {
  108. get => (double)GetValue(PanelValueFontSizeProperty);
  109. set => SetValue(PanelValueFontSizeProperty, value);
  110. }
  111. public double EquipmentTopPosition
  112. {
  113. get => (double)GetValue(EquipmentTopPositionProperty);
  114. set => SetValue(EquipmentTopPositionProperty, value);
  115. }
  116. #endregion
  117. #region 事件处理
  118. private void RopeEquipmentControl_Loaded(object sender, RoutedEventArgs e)
  119. {
  120. // 控件加载完成后更新RopeHeight
  121. UpdateRopeHeight();
  122. }
  123. private void RopeEquipmentControl_SizeChanged(object sender, SizeChangedEventArgs e)
  124. {
  125. // 当控件大小改变时更新RopeHeight
  126. UpdateRopeHeight();
  127. }
  128. /// <summary>
  129. /// 更新绳索高度以适应容器大小
  130. /// </summary>
  131. private void UpdateRopeHeight()
  132. {
  133. try
  134. {
  135. // 获取Canvas引用
  136. if (_ropeCanvas == null)
  137. {
  138. _ropeCanvas = FindName("RopeCanvas") as Canvas;
  139. if (_ropeCanvas == null)
  140. {
  141. // 如果找不到Canvas,使用控件自身高度
  142. RopeHeight = Math.Max(0, ActualHeight);
  143. return;
  144. }
  145. }
  146. // 使用Canvas的实际高度减去上下边距
  147. double newHeight = _ropeCanvas.ActualHeight;
  148. // 确保高度不为负数
  149. if (newHeight < 0)
  150. {
  151. newHeight = 0;
  152. }
  153. // 只有当高度变化时才更新,避免不必要的重新渲染
  154. if (Math.Abs(RopeHeight - newHeight) > 0.1)
  155. {
  156. RopeHeight = newHeight;
  157. }
  158. }
  159. catch (Exception)
  160. {
  161. // 出错时使用备用方案:使用控件自身高度
  162. try
  163. {
  164. RopeHeight = Math.Max(0, ActualHeight);
  165. }
  166. catch
  167. {
  168. // 如果还出错,使用默认值
  169. RopeHeight = 900.0;
  170. }
  171. }
  172. }
  173. #endregion
  174. #region 动画控制
  175. private static void OnIsAnimationRunningChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  176. {
  177. var control = (RopeEquipmentControl)d;
  178. control.UpdateAnimationState();
  179. }
  180. private static void OnAnimationDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  181. {
  182. var control = (RopeEquipmentControl)d;
  183. control.UpdateAnimationValues();
  184. }
  185. private static void OnAnimationDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
  186. {
  187. var control = (RopeEquipmentControl)d;
  188. control.UpdateAnimationValues();
  189. }
  190. private void UpdateAnimationValues()
  191. {
  192. var rectAnimation = (RectAnimation)_animationStoryboard.Children[0];
  193. rectAnimation.Duration = TimeSpan.FromSeconds(AnimationDuration);
  194. if (IsAnimationReversed)
  195. {
  196. rectAnimation.From = new Rect(0, -22, 26, 22);
  197. rectAnimation.To = new Rect(0, 0, 26, 22);
  198. }
  199. else
  200. {
  201. rectAnimation.From = new Rect(0, 0, 26, 22);
  202. rectAnimation.To = new Rect(0, -22, 26, 22);
  203. }
  204. if (IsAnimationRunning)
  205. {
  206. _animationStoryboard.Begin(this, true);
  207. }
  208. }
  209. private void UpdateAnimationState()
  210. {
  211. if (IsAnimationRunning)
  212. {
  213. _animationStoryboard.Begin(this, true);
  214. }
  215. else
  216. {
  217. _animationStoryboard.Stop(this);
  218. }
  219. }
  220. #endregion
  221. #region 公共方法
  222. public void StartAnimation(bool reversed = false)
  223. {
  224. IsAnimationReversed = reversed;
  225. IsAnimationRunning = true;
  226. }
  227. public void StopAnimation()
  228. {
  229. IsAnimationRunning = false;
  230. }
  231. public void ReverseAnimation()
  232. {
  233. IsAnimationReversed = !IsAnimationReversed;
  234. }
  235. #endregion
  236. }
  237. }