Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Patch: DragInfofactory #36

Closed
punker76 opened this issue Feb 18, 2013 · 2 comments · Fixed by #403
Closed

Patch: DragInfofactory #36

punker76 opened this issue Feb 18, 2013 · 2 comments · Fixed by #403
Assignees
Milestone

Comments

@punker76
Copy link
Owner

Original author: a...@chambills.com (May 25, 2011 10:14:22)

Linked to issue 26, but with a complete patch.

Not sure what your final plans are.
But we are needing to drag items from controls which are not item controls.
such as DevExpress Grids, Images etc

At the moment the DragInfo was tightly couple to the Drag Source being ItemsControl.

This patch abstracts the creation of DragInfo behind a factory allowing for other IDragInfo to be created.

Factory can be set like the handler via dependency property

Original issue: http://code.google.com/p/gong-wpf-dragdrop/issues/detail?id=36

@punker76
Copy link
Owner Author

Index: GongSolutions.Wpf.DragDrop/DefaultDragInfoFactory.cs
===================================================================
--- GongSolutions.Wpf.DragDrop/DefaultDragInfoFactory.cs    (revision 0)
+++ GongSolutions.Wpf.DragDrop/DefaultDragInfoFactory.cs    (revision 0)
@@ -0,0 +1,12 @@
+using System.Windows.Input;
+
+namespace GongSolutions.Wpf.DragDrop
+{
+    public class DefaultDragInfoFactory : IDragInfoFactory
+    {
+        public DragInfo Create(object sender, MouseButtonEventArgs mouseButtonEventArgs)
+        {
+            return new ItemsControlDragInfo(sender, mouseButtonEventArgs);
+        }
+    }
+}
\ No newline at end of file
Index: GongSolutions.Wpf.DragDrop/DragDrop.cs
===================================================================
--- GongSolutions.Wpf.DragDrop/DragDrop.cs  (revision 37)
+++ GongSolutions.Wpf.DragDrop/DragDrop.cs  (working copy)
@@ -12,6 +12,18 @@
 {
     public static class DragDrop
     {
+
+        public static IDragInfoFactory GetDragInfoFactory(UIElement target)
+        {
+            return (IDragInfoFactory)target.GetValue(DragInfoFactoryProperty);
+        }
+
+        public static void SetDragInfoFactory(UIElement target, IDragInfoFactory value)
+        {
+            target.SetValue(DragInfoFactoryProperty, value);
+        }
+
+
         public static DataTemplate GetDragAdornerTemplate(UIElement target)
         {
             return (DataTemplate)target.GetValue(DragAdornerTemplateProperty);
@@ -104,11 +116,14 @@

         public static readonly DependencyProperty DropHandlerProperty =
             DependencyProperty.RegisterAttached("DropHandler", typeof(IDropTarget), typeof(DragDrop));
-
+        
         public static readonly DependencyProperty IsDragSourceProperty =
             DependencyProperty.RegisterAttached("IsDragSource", typeof(bool), typeof(DragDrop),
                 new UIPropertyMetadata(false, IsDragSourceChanged));

+        public static readonly DependencyProperty DragInfoFactoryProperty =
+            DependencyProperty.RegisterAttached("DragInfoFactory", typeof(IDragInfoFactory), typeof(DragDrop));
+
         public static readonly DependencyProperty IsDropTargetProperty =
             DependencyProperty.RegisterAttached("IsDropTarget", typeof(bool), typeof(DragDrop),
                 new UIPropertyMetadata(false, IsDropTargetChanged));
@@ -250,7 +265,7 @@
                 return;
             }

-            m_DragInfo = new DragInfo(sender, e);
+            m_DragInfo = CreateDragInfo(sender, e);

             // If the sender is a list box that allows multiple selections, ensure that clicking on an 
             // already selected item does not change the selection, otherwise dragging multiple items 
@@ -269,6 +284,12 @@
             }
         }

+        private static DragInfo CreateDragInfo(object sender, MouseButtonEventArgs mouseButtonEventArgs)
+        {
+            var factory = GetDragInfoFactory((UIElement)sender) ?? new DefaultDragInfoFactory();
+            return factory.Create(sender, mouseButtonEventArgs);
+        }
+
         static void DragSource_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
         {
             // If we prevented the control's default selection handling in DragSource_PreviewMouseLeftButtonDown
@@ -419,13 +440,9 @@
         static void DropTarget_PreviewDrop(object sender, DragEventArgs e)
         {
             DropInfo dropInfo = new DropInfo(sender, e, m_DragInfo);
-            IDropTarget dropHandler = GetDropHandler((UIElement)sender) ?? DefaultDropHandler;
-            IDragSource dragHandler = GetDragHandler((UIElement)sender) ?? DefaultDragHandler;

             DragAdorner = null;
             DropTargetAdorner = null;
-            dropHandler.Drop(dropInfo);
-            dragHandler.Dropped(dropInfo);
             e.Handled = true;
         }

Index: GongSolutions.Wpf.DragDrop/DragInfo.cs
===================================================================
--- GongSolutions.Wpf.DragDrop/DragInfo.cs  (revision 37)
+++ GongSolutions.Wpf.DragDrop/DragInfo.cs  (working copy)
@@ -111,36 +111,6 @@
             MouseButton = e.ChangedButton;
             VisualSource = sender as UIElement;

-            if (sender is ItemsControl)
-            {
-                ItemsControl itemsControl = (ItemsControl)sender;
-                UIElement item = itemsControl.GetItemContainer((UIElement)e.OriginalSource);
-
-                if (item != null)
-                {
-                    ItemsControl itemParent = ItemsControl.ItemsControlFromItemContainer(item);
-
-                    SourceCollection = itemParent.ItemsSource ?? itemParent.Items;
-                    SourceItem = itemParent.ItemContainerGenerator.ItemFromContainer(item);
-                    SourceItems = itemsControl.GetSelectedItems();
-
-                    // Some controls (I'm looking at you TreeView!) haven't updated their
-                    // SelectedItem by this point. Check to see if there 1 or less item in 
-                    // the SourceItems collection, and if so, override the control's 
-                    // SelectedItems with the clicked item.
-                    if (SourceItems.Cast<object>().Count() <= 1)
-                    {
-                        SourceItems = Enumerable.Repeat(SourceItem, 1);
-                    }
-
-                    VisualSourceItem = item;
-                }
-                else
-                {
-                    SourceCollection = itemsControl.ItemsSource ?? itemsControl.Items;
-                }
-            }
-
             if (SourceItems == null)
             {
                 SourceItems = Enumerable.Empty<object>();
@@ -183,7 +153,7 @@
         /// <remarks>
         /// If the control that initated the drag is unbound or not an ItemsControl, this will be null.
         /// </remarks>
-        public IEnumerable SourceCollection { get; private set; }
+        public IEnumerable SourceCollection { get; protected set; }

         /// <summary>
         /// Gets the object that a dragged item is bound to.
@@ -192,7 +162,7 @@
         /// <remarks>
         /// If the control that initated the drag is unbound or not an ItemsControl, this will be null.
         /// </remarks>
-        public object SourceItem { get; private set; }
+        public object SourceItem { get; protected set; }

         /// <summary>
         /// Gets a collection of objects that the selected items in an ItemsControl are bound to.
@@ -201,7 +171,7 @@
         /// <remarks>
         /// If the control that initated the drag is unbound or not an ItemsControl, this will be empty.
         /// </remarks>
-        public IEnumerable SourceItems { get; private set; }
+        public IEnumerable SourceItems { get; protected set; }

         /// <summary>
         /// Gets the control that initiated the drag.
@@ -217,6 +187,6 @@
         /// container of the clicked item. For example, if <see cref="VisualSource"/> is a ListBox this
         /// will hold a ListBoxItem.
         /// </remarks>
-        public UIElement VisualSourceItem { get; private set; }
+        public UIElement VisualSourceItem { get; protected set; }
     }
 }
Index: GongSolutions.Wpf.DragDrop/GongSolutions.Wpf.DragDrop.csproj
===================================================================
--- GongSolutions.Wpf.DragDrop/GongSolutions.Wpf.DragDrop.csproj    (revision 37)
+++ GongSolutions.Wpf.DragDrop/GongSolutions.Wpf.DragDrop.csproj    (working copy)
@@ -57,6 +57,7 @@
   </ItemGroup>
   <ItemGroup>
     <Compile Include="DefaultDragHandler.cs" />
+    <Compile Include="DefaultDragInfoFactory.cs" />
     <Compile Include="DefaultDropHandler.cs" />
     <Compile Include="DragAdorner.cs" />
     <Compile Include="DragDrop.cs" />
@@ -66,8 +67,10 @@
     <Compile Include="DropTargetAdorners.cs" />
     <Compile Include="DropTargetHighlightAdorner.cs" />
     <Compile Include="DropTargetInsertionAdorner.cs" />
+    <Compile Include="IDragInfoFactory.cs" />
     <Compile Include="IDragSource.cs" />
     <Compile Include="IDropTarget.cs" />
+    <Compile Include="ItemsControlDragInfo.cs" />
     <Compile Include="Properties\AssemblyInfo.cs" />
     <Compile Include="Utilities\ItemsControlExtensions.cs" />
     <Compile Include="Utilities\TypeUtilities.cs" />
Index: GongSolutions.Wpf.DragDrop/IDragInfoFactory.cs
===================================================================
--- GongSolutions.Wpf.DragDrop/IDragInfoFactory.cs  (revision 0)
+++ GongSolutions.Wpf.DragDrop/IDragInfoFactory.cs  (revision 0)
@@ -0,0 +1,15 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows.Input;
+
+namespace GongSolutions.Wpf.DragDrop
+{
+    public interface IDragInfoFactory
+    {
+        // Methods
+        DragInfo Create(object sender, MouseButtonEventArgs mouseButtonEventArgs);
+    }
+
+}
Index: GongSolutions.Wpf.DragDrop/ItemsControlDragInfo.cs
===================================================================
--- GongSolutions.Wpf.DragDrop/ItemsControlDragInfo.cs  (revision 0)
+++ GongSolutions.Wpf.DragDrop/ItemsControlDragInfo.cs  (revision 0)
@@ -0,0 +1,47 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Input;
+using GongSolutions.Wpf.DragDrop.Utilities;
+
+namespace GongSolutions.Wpf.DragDrop
+{
+   public class ItemsControlDragInfo : DragInfo
+  {
+      public ItemsControlDragInfo(object sender, MouseButtonEventArgs e) : base(sender, e)
+      {
+          if (sender is ItemsControl)
+          {
+              ItemsControl itemsControl = (ItemsControl)sender;
+              UIElement item = itemsControl.GetItemContainer((UIElement)e.OriginalSource);
+
+              if (item != null)
+              {
+                  ItemsControl itemParent = ItemsControl.ItemsControlFromItemContainer(item);
+
+                  SourceCollection = itemParent.ItemsSource ?? itemParent.Items;
+                  SourceItem = itemParent.ItemContainerGenerator.ItemFromContainer(item);
+                  SourceItems = itemsControl.GetSelectedItems();
+
+                  // Some controls (I'm looking at you TreeView!) haven't updated their
+                  // SelectedItem by this point. Check to see if there 1 or less item in 
+                  // the SourceItems collection, and if so, override the control's 
+                  // SelectedItems with the clicked item.
+                  if (SourceItems.Cast<object>().Count() <= 1)
+                  {
+                      SourceItems = Enumerable.Repeat(SourceItem, 1);
+                  }
+
+                  VisualSourceItem = item;
+              }
+              else
+              {
+                  SourceCollection = itemsControl.ItemsSource ?? itemsControl.Items;
+              }
+          }
+      }
+  }
+}

@ghost ghost assigned punker76 Feb 18, 2013
@jrgcubano
Copy link

jrgcubano commented Mar 13, 2018

@punker76

I'm facing this same problem with a custom grid to allow drag and drop between rows. Implementing a factory sounds like the best choice right now, so does not introduce any breaking change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants