ProductView.xaml.cs 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. using System;
  2. using System.ComponentModel;
  3. using System.Windows;
  4. using System.Windows.Controls;
  5. using System.Windows.Media.Animation;
  6. using TeamAAS.FlowEngine.Execution;
  7. using TeamAAS.ViewModels;
  8. namespace TeamAAS.Views
  9. {
  10. public partial class ProductView : UserControl
  11. {
  12. private const double ExpandedWidth = 280;
  13. private const double CollapsedWidth = 56;
  14. private const double AnimationMs = 250;
  15. private ProductViewModel _vm;
  16. public ProductView()
  17. {
  18. InitializeComponent();
  19. DataContext = new ProductViewModel();
  20. DataContextChanged += OnDataContextChanged;
  21. Loaded += OnLoaded;
  22. Unloaded += OnUnloaded;
  23. }
  24. private void OnLoaded(object sender, RoutedEventArgs e)
  25. {
  26. HookViewModel(DataContext as ProductViewModel);
  27. // 运行/停止状态变化 → 刷新"运行中锁定"遮罩与角标
  28. FlowRunner.Instance.RunStateChanged += OnRunStateChanged;
  29. // 切回产品页时立即按当前运行状态同步一次,避免在别处启停流程后画布锁定状态滞后
  30. _vm?.RefreshRunState();
  31. }
  32. private void OnUnloaded(object sender, RoutedEventArgs e)
  33. {
  34. FlowRunner.Instance.RunStateChanged -= OnRunStateChanged;
  35. }
  36. private void OnRunStateChanged()
  37. {
  38. _vm?.RefreshRunState();
  39. }
  40. private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
  41. {
  42. HookViewModel(e.NewValue as ProductViewModel);
  43. }
  44. private void HookViewModel(ProductViewModel vm)
  45. {
  46. if (_vm != null)
  47. _vm.PropertyChanged -= OnVmPropertyChanged;
  48. _vm = vm;
  49. if (_vm != null)
  50. {
  51. _vm.PropertyChanged += OnVmPropertyChanged;
  52. ApplySidebarState(_vm.IsSidebarCollapsed, animate: false);
  53. }
  54. }
  55. private void OnVmPropertyChanged(object sender, PropertyChangedEventArgs e)
  56. {
  57. if (e.PropertyName == nameof(ProductViewModel.IsSidebarCollapsed))
  58. {
  59. ApplySidebarState(_vm.IsSidebarCollapsed, animate: true);
  60. }
  61. }
  62. /// <summary>
  63. /// 产品列表右键菜单"属性":直接走 code-behind 事件(Context 弹窗在 Popup 独立可视树中,
  64. /// MenuItem 的 Command 绑定无法可靠命中 ViewModel,故不经过绑定)。
  65. /// 右键哪个产品就编辑哪个产品(PlacementTarget 的 DataContext = 产品名)。
  66. /// </summary>
  67. private void ProductProperties_Click(object sender, RoutedEventArgs e)
  68. {
  69. var vm = DataContext as ProductViewModel;
  70. if (vm == null) return;
  71. string productName = null;
  72. if (sender is MenuItem mi
  73. && mi.Parent is ContextMenu cm
  74. && cm.PlacementTarget is FrameworkElement target)
  75. {
  76. productName = target.DataContext as string;
  77. }
  78. if (string.IsNullOrEmpty(productName)) return;
  79. vm.ShowProductProperties(productName);
  80. }
  81. /// <summary>产品列表右键菜单“全局变量”:编辑该产品的 Product 作用域变量(弹窗)。</summary>
  82. private void ProductGlobalVars_Click(object sender, RoutedEventArgs e)
  83. {
  84. var vm = DataContext as ProductViewModel;
  85. if (vm == null) return;
  86. string productName = null;
  87. if (sender is MenuItem mi
  88. && mi.Parent is ContextMenu cm
  89. && cm.PlacementTarget is FrameworkElement target)
  90. {
  91. productName = target.DataContext as string;
  92. }
  93. if (string.IsNullOrEmpty(productName)) return;
  94. vm.ShowProductGlobalVars(productName);
  95. }
  96. private void ApplySidebarState(bool collapsed, bool animate)
  97. {
  98. double targetWidth = collapsed ? CollapsedWidth : ExpandedWidth;
  99. if (animate)
  100. {
  101. var widthAnim = new DoubleAnimation(targetWidth, TimeSpan.FromMilliseconds(AnimationMs))
  102. {
  103. EasingFunction = new CubicEase { EasingMode = EasingMode.EaseInOut }
  104. };
  105. SidebarPanel.BeginAnimation(FrameworkElement.WidthProperty, widthAnim);
  106. }
  107. else
  108. {
  109. SidebarPanel.Width = targetWidth;
  110. }
  111. if (collapsed)
  112. {
  113. if (animate)
  114. {
  115. var fadeOut = new DoubleAnimation(1.0, 0.0, TimeSpan.FromMilliseconds(120));
  116. fadeOut.Completed += (s, args) =>
  117. {
  118. SidebarExpanded.Visibility = Visibility.Collapsed;
  119. SidebarCollapsed.Visibility = Visibility.Visible;
  120. SidebarCollapsed.Opacity = 0;
  121. var fadeIn = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(130));
  122. SidebarCollapsed.BeginAnimation(UIElement.OpacityProperty, fadeIn);
  123. };
  124. SidebarExpanded.BeginAnimation(UIElement.OpacityProperty, fadeOut);
  125. }
  126. else
  127. {
  128. SidebarExpanded.Visibility = Visibility.Collapsed;
  129. SidebarCollapsed.Visibility = Visibility.Visible;
  130. SidebarCollapsed.Opacity = 1.0;
  131. }
  132. }
  133. else
  134. {
  135. if (animate)
  136. {
  137. var fadeOut = new DoubleAnimation(1.0, 0.0, TimeSpan.FromMilliseconds(120));
  138. fadeOut.Completed += (s, args) =>
  139. {
  140. SidebarCollapsed.Visibility = Visibility.Collapsed;
  141. SidebarExpanded.Visibility = Visibility.Visible;
  142. SidebarExpanded.Opacity = 0;
  143. var fadeIn = new DoubleAnimation(0.0, 1.0, TimeSpan.FromMilliseconds(130));
  144. SidebarExpanded.BeginAnimation(UIElement.OpacityProperty, fadeIn);
  145. };
  146. SidebarCollapsed.BeginAnimation(UIElement.OpacityProperty, fadeOut);
  147. }
  148. else
  149. {
  150. SidebarCollapsed.Visibility = Visibility.Collapsed;
  151. SidebarExpanded.Visibility = Visibility.Visible;
  152. SidebarExpanded.Opacity = 1.0;
  153. }
  154. }
  155. }
  156. }
  157. }