TreeView折叠/展开根节点时误触发拖拽问题及解决
WPF TreeView折叠/展开根节点时误触发拖拽的问题解决
问题描述
在未选中任何项的情况下折叠或展开TreeView的根节点时,应用程序会误触发拖拽操作,导致droppedData始终被初始化为最后一次移动的MyItem,即使没有选中任何项。
问题代码
private void TreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var treeViewItem = GetNearestContainer(e.OriginalSource as UIElement); if (treeViewItem == null) return; MyItem clickedItem = treeViewItem.DataContext as MyItem; if (clickedItem != null && clickedItem.CanBeDragged) { _draggedItem = clickedItem; } } private void TreeView_PreviewMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && _draggedItem != null) { // 开始拖拽 DragDrop.DoDragDrop(MyTreeView, _draggedItem, DragDropEffects.Move); _draggedItem = null; // 拖拽完成后清空项 } }
解决方案
在启动拖拽操作前,检查鼠标是否移动了系统定义的最小拖拽距离。只有当鼠标水平或垂直移动距离超过阈值时,才触发拖拽逻辑,避免折叠/展开根节点时的微小鼠标移动误触发拖拽。
修正后的代码
private Point? _mouseDownPosition; private void TreeView_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e) { var treeViewItem = GetNearestContainer(e.OriginalSource as UIElement); if (treeViewItem == null) return; MyItem clickedItem = treeViewItem.DataContext as MyItem; if (clickedItem != null && clickedItem.CanBeDragged) { _draggedItem = clickedItem; } // 记录鼠标按下时的位置 _mouseDownPosition = e.GetPosition(MyTreeView); } private void TreeView_PreviewMouseMove(object sender, MouseEventArgs e) { if (e.LeftButton == MouseButtonState.Pressed && _draggedItem != null) { // 在启动拖拽前检查鼠标是否移动了足够距离 var mouseMovePosition = e.GetPosition(MyTreeView); var diff = _mouseDownPosition - mouseMovePosition; if (_mouseDownPosition.HasValue && (Math.Abs(diff.Value.X) > SystemParameters.MinimumHorizontalDragDistance || Math.Abs(diff.Value.Y) > SystemParameters.MinimumVerticalDragDistance)) { // 开始拖拽 DragDrop.DoDragDrop(MyTreeView, _draggedItem, DragDropEffects.Move); _draggedItem = null; // 拖拽完成后清空项 _mouseDownPosition = null; // 清空鼠标按下位置记录 } } }
内容的提问来源于stack exchange,提问作者user22345381
相关产品推荐
相关产品推荐

