using System; using System.Collections.Generic; using System.Diagnostics; using System.Windows; using System.Windows.Controls; using System.Windows.Input; using System.Windows.Media; using System.Windows.Shapes; using WinForms = System.Windows.Forms; namespace DrillTools { /// /// 拖放帮助类 /// public static class DragDropHelper { private static System.Windows.Point _startPoint; private static bool _isDragging; private static DragToolTipWindow? _dragToolTipWindow; private static Window? _ownerWindow; private static System.Windows.Shapes.Rectangle? _insertionIndicator; private static int _insertionIndex = -1; private static DateTime? _lastUpdateTime; /// /// 启用 ListView 的拖放功能 /// /// 数据项类型 /// ListView 控件 /// 插入位置指示器 public static void EnableDragDrop(System.Windows.Controls.ListView listView, System.Windows.Shapes.Rectangle insertionIndicator) where T : class { _insertionIndicator = insertionIndicator; _ownerWindow = Window.GetWindow(listView); listView.PreviewMouseLeftButtonDown += (sender, e) => { _startPoint = e.GetPosition(null); _isDragging = false; }; listView.PreviewMouseMove += (sender, e) => { if (e.LeftButton == MouseButtonState.Pressed && !_isDragging) { System.Windows.Point position = e.GetPosition(null); if (Math.Abs(position.X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(position.Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance) { _isDragging = true; var listViewItem = FindAncestor((DependencyObject)e.OriginalSource); if (listViewItem != null) { var item = listView.ItemContainerGenerator.ItemFromContainer(listViewItem) as T; if (item != null) { // 获取屏幕坐标 var screenPosition = listView.PointToScreen(e.GetPosition(listView)); // 创建并显示拖动提示 CreateDragToolTip(item, screenPosition); // 使用 QueryContinueDrag 事件来更新位置 System.Windows.QueryContinueDragEventHandler queryContinueHandler = null; queryContinueHandler = (sender, e) => { if (_dragToolTipWindow != null) { // 获取当前鼠标位置 var currentPos = WinForms.Control.MousePosition; _dragToolTipWindow.UpdatePosition(new System.Windows.Point(currentPos.X, currentPos.Y)); } // 如果拖放结束,移除事件处理 if (e.Action == System.Windows.DragAction.Drop || e.Action == System.Windows.DragAction.Cancel) { DragDrop.RemoveQueryContinueDragHandler(listView, queryContinueHandler); } }; DragDrop.AddQueryContinueDragHandler(listView, queryContinueHandler); System.Windows.DataObject data = new System.Windows.DataObject(typeof(T), item); DragDrop.DoDragDrop(listViewItem, data, System.Windows.DragDropEffects.Move); // 清理拖动提示 CleanupDragToolTip(); } } } } }; listView.DragOver += (sender, e) => { if (e.Data.GetDataPresent(typeof(T))) { e.Effects = System.Windows.DragDropEffects.Move; // 更新插入位置指示器 UpdateInsertionIndicator(listView, e.GetPosition(listView)); } else { e.Effects = System.Windows.DragDropEffects.None; } e.Handled = true; }; listView.DragLeave += (sender, e) => { HideInsertionIndicator(); }; listView.Drop += (sender, e) => { try { // 隐藏插入指示器 HideInsertionIndicator(); Debug.WriteLine($"[DragDrop] Drop事件触发 - OriginalSource类型: {e.OriginalSource?.GetType().Name}"); Debug.WriteLine($"[DragDrop] Drop位置: ({e.GetPosition(listView).X}, {e.GetPosition(listView).Y})"); if (e.Data.GetDataPresent(typeof(T))) { var droppedItem = e.Data.GetData(typeof(T)) as T; if (droppedItem != null) { Debug.WriteLine($"[DragDrop] 拖放项: {droppedItem}"); // 检查是否是机台码刀具,如果是则不允许移动 if (droppedItem is ToolItem toolItem && toolItem.ToolType == ToolType.MachineCode) { Debug.WriteLine("[DragDrop] 机台码刀具不允许移动"); System.Windows.MessageBox.Show("机台码刀具不允许移动位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); _isDragging = false; return; } var targetItem = FindAncestor((DependencyObject)e.OriginalSource); string ss = targetItem == null ? "NULL" : "找到"; Debug.WriteLine($"[DragDrop] 目标ListViewItem: {ss}"); if (targetItem == null) { Debug.WriteLine("[DragDrop] 警告: 目标项为空,可能是拖放到列表外部"); _isDragging = false; return; } var targetIndex = listView.ItemContainerGenerator.IndexFromContainer(targetItem); Debug.WriteLine($"[DragDrop] 目标索引: {targetIndex}"); var sourceIndex = listView.Items.IndexOf(droppedItem); Debug.WriteLine($"[DragDrop] 源索引: {sourceIndex}"); // 检查目标位置是否是机台码刀具 var viewModel = listView.DataContext as MainWindowViewModel; if (viewModel != null && viewModel.Tools.Count > targetIndex) { var targetTool = viewModel.Tools[targetIndex]; if (targetTool.ToolType == ToolType.MachineCode) { Debug.WriteLine("[DragDrop] 不能移动到机台码刀具位置"); System.Windows.MessageBox.Show("不能移动到机台码刀具位置", "提示", MessageBoxButton.OK, MessageBoxImage.Information); _isDragging = false; return; } } if (sourceIndex != -1 && targetIndex != -1 && sourceIndex != targetIndex) { viewModel?.ReorderTools(sourceIndex, targetIndex); Debug.WriteLine($"[DragDrop] 重新排序完成: {sourceIndex} -> {targetIndex}"); } else { Debug.WriteLine($"[DragDrop] 跳过重新排序 - 源索引: {sourceIndex}, 目标索引: {targetIndex}"); } } } } catch (Exception ex) { Debug.WriteLine($"[DragDrop] 异常: {ex.GetType().Name} - {ex.Message}"); Debug.WriteLine($"[DragDrop] 堆栈跟踪: {ex.StackTrace}"); System.Windows.MessageBox.Show($"拖放操作发生错误: {ex.Message}", "错误", MessageBoxButton.OK, MessageBoxImage.Error); } finally { _isDragging = false; } }; } /// /// 查找指定类型的父元素 /// /// 父元素类型 /// 当前元素 /// 找到的父元素,如果未找到则返回 null private static T? FindAncestor(DependencyObject current) where T : DependencyObject { Debug.WriteLine($"[FindAncestor] 开始查找类型 {typeof(T).Name},起始元素类型: {current?.GetType().Name ?? "NULL"}"); int depth = 0; while (current != null) { Debug.WriteLine($"[FindAncestor] 深度 {depth}: 当前类型 {current.GetType().Name}"); if (current is T ancestor) { Debug.WriteLine($"[FindAncestor] 找到匹配的祖先类型 {typeof(T).Name}"); return ancestor; } current = VisualTreeHelper.GetParent(current); depth++; if (depth > 10) // 防止无限循环 { Debug.WriteLine("[FindAncestor] 警告: 搜索深度超过10层,停止搜索"); break; } } Debug.WriteLine($"[FindAncestor] 未找到类型 {typeof(T).Name} 的祖先"); return null; } /// /// 处理主窗口鼠标移动事件,更新拖动提示位置 /// private static void OnOwnerWindowMouseMove(object sender, System.Windows.Input.MouseEventArgs e) { if (_dragToolTipWindow != null && _isDragging) { // 获取屏幕坐标 var windowPosition = e.GetPosition(_ownerWindow); var screenPosition = _ownerWindow.PointToScreen(windowPosition); _dragToolTipWindow.UpdatePosition(screenPosition); } } /// /// 创建拖动提示窗口 /// private static void CreateDragToolTip(T item, System.Windows.Point position) where T : class { if (item is ToolItem toolItem && _ownerWindow != null) { _dragToolTipWindow = new DragToolTipWindow(); _dragToolTipWindow.SetToolInfo(toolItem); _dragToolTipWindow.UpdatePosition(position); // 不设置 Owner,这样窗口可以独立定位 _dragToolTipWindow.Show(); } } /// /// 清理拖动提示窗口 /// private static void CleanupDragToolTip() { if (_dragToolTipWindow != null) { _dragToolTipWindow.Close(); _dragToolTipWindow = null; } if (_ownerWindow != null) { _ownerWindow.MouseMove -= OnOwnerWindowMouseMove; } } /// /// 更新插入位置指示器 /// private static void UpdateInsertionIndicator(System.Windows.Controls.ListView listView, System.Windows.Point position) { if (_insertionIndicator == null) return; // 使用节流机制,避免过于频繁的更新 if (_lastUpdateTime != null && DateTime.Now - _lastUpdateTime < TimeSpan.FromMilliseconds(16)) return; _lastUpdateTime = DateTime.Now; try { // 使用 VisualTreeHelper 找到鼠标下的元素 var element = listView.InputHitTest(position) as DependencyObject; var listViewItem = FindAncestor(element); if (listViewItem != null) { var index = listView.ItemContainerGenerator.IndexFromContainer(listViewItem); var itemBounds = listViewItem.TransformToAncestor(listView) .TransformBounds(new Rect(0, 0, listViewItem.ActualWidth, listViewItem.ActualHeight)); // 判断是在上半部分还是下半部分 bool insertAfter = position.Y > itemBounds.Top + itemBounds.Height / 2; int targetIndex = insertAfter ? index + 1 : index; if (targetIndex != _insertionIndex) { _insertionIndex = targetIndex; // 更新指示器位置 _insertionIndicator.Visibility = Visibility.Visible; // 计算指示器位置 double indicatorTop = insertAfter ? itemBounds.Bottom : itemBounds.Top; // 使用 VerticalAlignment 和 Margin 结合来定位指示器 _insertionIndicator.VerticalAlignment = VerticalAlignment.Top; _insertionIndicator.Margin = new Thickness(0, indicatorTop, 0, 0); } } else { // 如果没有找到目标项,检查是否在列表末尾 if (position.Y > listView.ActualHeight - 20) { _insertionIndex = listView.Items.Count; // 在列表末尾显示指示器 _insertionIndicator.Visibility = Visibility.Visible; _insertionIndicator.VerticalAlignment = VerticalAlignment.Top; _insertionIndicator.Margin = new Thickness(0, listView.ActualHeight - 2, 0, 0); } else { HideInsertionIndicator(); } } } catch (Exception ex) { Debug.WriteLine($"[DragDrop] 更新插入指示器时发生错误: {ex.Message}"); HideInsertionIndicator(); } } /// /// 隐藏插入位置指示器 /// private static void HideInsertionIndicator() { if (_insertionIndicator != null) { _insertionIndicator.Visibility = Visibility.Collapsed; } _insertionIndex = -1; } } }