using System; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; namespace SWRIS.Controls { /// /// RopeControl.xaml 的交互逻辑 /// public partial class RopeEquipmentControl : UserControl { private Canvas _ropeCanvas; // 添加Canvas引用 private readonly Storyboard _animationStoryboard; public RopeEquipmentControl() { InitializeComponent(); // 初始化动画 _animationStoryboard = (Storyboard)Resources["RopeAnimation"]; // 设置初始动画值 UpdateAnimationValues(); // 订阅SizeChanged事件 SizeChanged += RopeEquipmentControl_SizeChanged; // 订阅Loaded事件,确保控件加载完成后获取正确的尺寸 Loaded += RopeEquipmentControl_Loaded; } #region 依赖属性 // 绳索高度 public static readonly DependencyProperty RopeHeightProperty = DependencyProperty.Register("RopeHeight", typeof(double), typeof(RopeEquipmentControl), new PropertyMetadata(900.0)); // 绳索图片 public static readonly DependencyProperty RopeImageSourceProperty = DependencyProperty.Register("RopeImageSource", typeof(ImageSource), typeof(RopeEquipmentControl)); // 设备图片 public static readonly DependencyProperty EquipmentImageSourceProperty = DependencyProperty.Register("EquipmentImageSource", typeof(ImageSource), typeof(RopeEquipmentControl)); // 是否运行动画 public static readonly DependencyProperty IsAnimationRunningProperty = DependencyProperty.Register("IsAnimationRunning", typeof(bool), typeof(RopeEquipmentControl), new PropertyMetadata(false, OnIsAnimationRunningChanged)); // 动画方向(正向/反向) public static readonly DependencyProperty IsAnimationReversedProperty = DependencyProperty.Register("IsAnimationReversed", typeof(bool), typeof(RopeEquipmentControl), new PropertyMetadata(false, OnAnimationDirectionChanged)); // 动画速度(秒) public static readonly DependencyProperty AnimationDurationProperty = DependencyProperty.Register("AnimationDuration", typeof(double), typeof(RopeEquipmentControl), new PropertyMetadata(0.5, OnAnimationDurationChanged)); // 数据面板位置 public static readonly DependencyProperty PanelMarginProperty = DependencyProperty.Register("PanelMargin", typeof(Thickness), typeof(RopeEquipmentControl)); // 数据面板文字大小 public static readonly DependencyProperty PanelNameFontSizeProperty = DependencyProperty.Register("PanelNameFontSize", typeof(double), typeof(RopeEquipmentControl), new PropertyMetadata(28d)); // 数据面板文字大小 public static readonly DependencyProperty PanelValueFontSizeProperty = DependencyProperty.Register("PanelValueFontSize", typeof(double), typeof(RopeEquipmentControl), new PropertyMetadata(28d)); // 设备图片位置 public static readonly DependencyProperty EquipmentTopPositionProperty = DependencyProperty.Register("EquipmentTopPosition", typeof(double), typeof(RopeEquipmentControl)); #endregion #region 属性包装器 public double RopeHeight { get => (double)GetValue(RopeHeightProperty); set => SetValue(RopeHeightProperty, value); } public ImageSource RopeImageSource { get => (ImageSource)GetValue(RopeImageSourceProperty); set => SetValue(RopeImageSourceProperty, value); } public ImageSource EquipmentImageSource { get => (ImageSource)GetValue(EquipmentImageSourceProperty); set => SetValue(EquipmentImageSourceProperty, value); } public bool IsAnimationRunning { get => (bool)GetValue(IsAnimationRunningProperty); set => SetValue(IsAnimationRunningProperty, value); } public bool IsAnimationReversed { get => (bool)GetValue(IsAnimationReversedProperty); set => SetValue(IsAnimationReversedProperty, value); } public double AnimationDuration { get => (double)GetValue(AnimationDurationProperty); set => SetValue(AnimationDurationProperty, value); } public Thickness PanelMargin { get => (Thickness)GetValue(PanelMarginProperty); set => SetValue(PanelMarginProperty, value); } public double PanelNameFontSize { get => (double)GetValue(PanelNameFontSizeProperty); set => SetValue(PanelNameFontSizeProperty, value); } public double PanelValueFontSize { get => (double)GetValue(PanelValueFontSizeProperty); set => SetValue(PanelValueFontSizeProperty, value); } public double EquipmentTopPosition { get => (double)GetValue(EquipmentTopPositionProperty); set => SetValue(EquipmentTopPositionProperty, value); } #endregion #region 事件处理 private void RopeEquipmentControl_Loaded(object sender, RoutedEventArgs e) { // 控件加载完成后更新RopeHeight UpdateRopeHeight(); } private void RopeEquipmentControl_SizeChanged(object sender, SizeChangedEventArgs e) { // 当控件大小改变时更新RopeHeight UpdateRopeHeight(); } /// /// 更新绳索高度以适应容器大小 /// private void UpdateRopeHeight() { try { // 获取Canvas引用 if (_ropeCanvas == null) { _ropeCanvas = FindName("RopeCanvas") as Canvas; if (_ropeCanvas == null) { // 如果找不到Canvas,使用控件自身高度 RopeHeight = Math.Max(0, ActualHeight); return; } } // 使用Canvas的实际高度减去上下边距 double newHeight = _ropeCanvas.ActualHeight; // 确保高度不为负数 if (newHeight < 0) { newHeight = 0; } // 只有当高度变化时才更新,避免不必要的重新渲染 if (Math.Abs(RopeHeight - newHeight) > 0.1) { RopeHeight = newHeight; } } catch (Exception) { // 出错时使用备用方案:使用控件自身高度 try { RopeHeight = Math.Max(0, ActualHeight); } catch { // 如果还出错,使用默认值 RopeHeight = 900.0; } } } #endregion #region 动画控制 private static void OnIsAnimationRunningChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (RopeEquipmentControl)d; control.UpdateAnimationState(); } private static void OnAnimationDirectionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (RopeEquipmentControl)d; control.UpdateAnimationValues(); } private static void OnAnimationDurationChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) { var control = (RopeEquipmentControl)d; control.UpdateAnimationValues(); } private void UpdateAnimationValues() { var rectAnimation = (RectAnimation)_animationStoryboard.Children[0]; rectAnimation.Duration = TimeSpan.FromSeconds(AnimationDuration); if (IsAnimationReversed) { rectAnimation.From = new Rect(0, -22, 26, 22); rectAnimation.To = new Rect(0, 0, 26, 22); } else { rectAnimation.From = new Rect(0, 0, 26, 22); rectAnimation.To = new Rect(0, -22, 26, 22); } if (IsAnimationRunning) { _animationStoryboard.Begin(this, true); } } private void UpdateAnimationState() { if (IsAnimationRunning) { _animationStoryboard.Begin(this, true); } else { _animationStoryboard.Stop(this); } } #endregion #region 公共方法 public void StartAnimation(bool reversed = false) { IsAnimationReversed = reversed; IsAnimationRunning = true; } public void StopAnimation() { IsAnimationRunning = false; } public void ReverseAnimation() { IsAnimationReversed = !IsAnimationReversed; } #endregion } }