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;
}
}
}