Procházet zdrojové kódy

修改 ItemsDraggable 通过 HitTest 获取拖动子元素, 防止拖动滚动条时, 意外触发拖动

lintx před 1 měsícem
rodič
revize
2163d9356a
1 změnil soubory, kde provedl 63 přidání a 10 odebrání
  1. 63 10
      Waaagh/Behaviors/ItemsDraggable.cs

+ 63 - 10
Waaagh/Behaviors/ItemsDraggable.cs

@@ -2,6 +2,7 @@
 using System.Windows;
 using System.Windows.Controls;
 using System.Windows.Input;
+using System.Windows.Media;
 
 namespace Waaagh.Behaviors {
     sealed public class ItemsDraggable {
@@ -64,15 +65,19 @@ namespace Waaagh.Behaviors {
             if (args.LeftButton != MouseButtonState.Pressed) {
                 return;
             }
-            if (sender is ItemsControl sourceItemsControl == false) {
+            if (sender is ItemsControl source == false) {
                 return;
             }
-            if (sourceItemsControl.ItemsSource is IList == false) {
+            if (source.ItemsSource is IList == false) {
                 return;
             }
-            if (GetDragDropEventSource(ref sourceItemsControl, out Control sourceControl, args.GetPosition) == false) {
+            if (GetElement(source, args.GetPosition(source)) is Control sourceControl == false) {
                 return;
             }
+            if (GetParent(sourceControl) is ItemsControl sourceItemsControl == false) {
+                return;
+            }
+
             DataObject data = new DataObject();
             data.SetData(DraggableDataFormat, sourceControl.DataContext);
             data.SetData(DraggableCollectionFormat, sourceItemsControl.ItemsSource);
@@ -95,22 +100,25 @@ namespace Waaagh.Behaviors {
             if (args.Effects == DragDropEffects.None) {
                 return;
             }
-            if (sender is ItemsControl targetItemsControl == false) {
+            if (sender is ItemsControl target == false) {
                 return;
             }
-            // 获取 拖拽源
-            object? sourceData = args.Data.GetData(DraggableDataFormat) as object;
-            IList? sourceCollection = args.Data.GetData(DraggableCollectionFormat) as IList;
-            if (sourceData == null || sourceCollection == null) {
+            // 获取 放置目标
+            if (GetElement(target, args.GetPosition(target)) is Control targetControl == false) {
                 return;
             }
-            // 获取 放置目标
-            if (GetDragDropEventSource(ref targetItemsControl, out Control targetControl, args.GetPosition) == false) {
+            if (GetParent(targetControl) is ItemsControl targetItemsControl == false) {
                 return;
             }
             if (targetItemsControl.ItemsSource is IList targetCollection == false) {
                 return;
             }
+            // 获取 拖拽源
+            object? sourceData = args.Data.GetData(DraggableDataFormat) as object;
+            IList? sourceCollection = args.Data.GetData(DraggableCollectionFormat) as IList;
+            if (sourceData == null || sourceCollection == null) {
+                return;
+            }
             // 判断 集合元素类型
             object? targetData = targetControl.DataContext;
             if (CheckCollectionElementType(sourceCollection, targetCollection) == false) {
@@ -210,6 +218,51 @@ namespace Waaagh.Behaviors {
             return false;
         }
 
+        static private Control? GetElement(ItemsControl source, Point point) {
+            if (GetItemContainerType(source) is Type type == false) {
+                return null;
+            }
+            DependencyObject? dp = source.InputHitTest(point) as DependencyObject;
+            while (dp != null) {
+                if (dp.GetType().Equals(type)) {
+                    break;
+                }
+                dp = VisualTreeHelper.GetParent(dp);
+            }
+            return dp as Control;
+        }
+
+        static private ItemsControl? GetParent(Control control) {
+            for (DependencyObject dp = VisualTreeHelper.GetParent(control); dp != null; dp = VisualTreeHelper.GetParent(dp)) {
+                if (dp is ItemsControl parent && parent.ItemContainerGenerator.ContainerFromItem(control.DataContext) != null) {
+                    return parent;
+                }
+            }
+            return null;
+        }
+
+        static private Type? GetItemContainerType(ItemsControl source) {
+            if (source == null) {
+                return null;
+            }
+            if (source is ListView) {
+                return typeof(ListViewItem);
+            }
+            else if (source is ListBox) {
+                return typeof(ListBoxItem);
+            }
+            else if (source is TreeView || source is TreeViewItem) {
+                return typeof(TreeViewItem);
+            }
+            // else if (source is GridView) {
+            //     return typeof(GridViewColumn);
+            // }
+            if (source.Items.Count > 0) {
+                return source.ItemContainerGenerator.ContainerFromIndex(0)?.GetType();
+            }
+            return null;
+        }
+
         static private bool CheckCollectionElementType(IList collection1, IList collection2) {
             return collection1.GetType().GetGenericArguments()[0] == collection2.GetType().GetGenericArguments()[0];
         }