zzz6519003 / gong-wpf-dragdrop

Automatically exported from code.google.com/p/gong-wpf-dragdrop
1 stars 0 forks source link

Code submit: display visual of dragged item instead of using template #38

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I made a quick modification to the DragDrop.CreateDragAdorner() method so that 
by default (when an adorner template is not specified), an image is extracted 
from the dragged item(s) and that is used as the adorner instead.

I'm not sure why this was never added as a feature before, it's so easy to 
implement...

Here is my modification to that method, plus a new helper method to do the 
image generation:

static void CreateDragAdorner()
        {
            var template = GetDragAdornerTemplate(m_DragInfo.VisualSource);

            // This block was added to create a Data Template on the fly with an image generated
            // from m_DragInfo.VisualSourceItem. -- Chris Bordeman cbordeman@gmail.com
            if (template == null)
            {
                template = new DataTemplate();

                var factory = new FrameworkElementFactory(typeof(Image));

                var bs = CaptureScreen(m_DragInfo.VisualSourceItem);
                factory.SetValue(Image.SourceProperty,  bs);
                if (m_DragInfo.VisualSourceItem is FrameworkElement)
                {
                    factory.SetValue(FrameworkElement.WidthProperty,((FrameworkElement) m_DragInfo.VisualSourceItem).ActualWidth);
                    factory.SetValue(FrameworkElement.HeightProperty, ((FrameworkElement)m_DragInfo.VisualSourceItem).ActualHeight);
                }
                template.VisualTree = factory;
            }

            // The rest of the code was originally inside an "if (template != null)" 
            // block. -- Chris Bordeman cbordeman@gmail.com

            UIElement rootElement = null;
            Window parentWindow = m_DragInfo.VisualSource.GetVisualAncestor<Window>();
            UIElement adornment = null;

            if (parentWindow != null)
            {
                rootElement = parentWindow.Content as UIElement;
            }
            if (rootElement == null)
            {
                rootElement = (UIElement)Application.Current.MainWindow.Content;
            }

            if (m_DragInfo.Data is IEnumerable && !(m_DragInfo.Data is string))
            {
                if (((IEnumerable)m_DragInfo.Data).Cast<object>().Count() <= 10)
                {
                    ItemsControl itemsControl = new ItemsControl();
                    itemsControl.ItemsSource = (IEnumerable)m_DragInfo.Data;
                    itemsControl.ItemTemplate = template;

                    // The ItemsControl doesn't display unless we create a border to contain it.
                    // Not quite sure why this is...
                    Border border = new Border();
                    border.Child = itemsControl;
                    adornment = border;
                }
            }
            else
            {
                ContentPresenter contentPresenter = new ContentPresenter();
                contentPresenter.Content = m_DragInfo.Data;
                contentPresenter.ContentTemplate = template;
                adornment = contentPresenter;
            }

            if (adornment != null)
            {
                adornment.Opacity = 0.5;
                DragAdorner = new DragAdorner(rootElement, adornment);
            }
        }

        // Helper to generate the image - I grabbed this off Google 
        // somewhere. -- Chris Bordeman cbordeman@gmail.com
        private static BitmapSource CaptureScreen(Visual target, double dpiX = 96.0, double dpiY = 96.0)
        {
            if (target == null)
                return null;

            var bounds = VisualTreeHelper.GetDescendantBounds(target);

            var rtb = new RenderTargetBitmap((int)(bounds.Width * dpiX / 96.0),
                                             (int)(bounds.Height * dpiY / 96.0),
                                             dpiX,
                                             dpiY,
                                             PixelFormats.Pbgra32);

            var dv = new DrawingVisual();
            using (var ctx = dv.RenderOpen())
            {
                var vb = new VisualBrush(target);
                ctx.DrawRectangle(vb, null, new Rect(new Point(), bounds.Size));
            }

            rtb.Render(dv);

            return rtb;
        }

Original issue reported on code.google.com by cborde...@gmail.com on 28 Jun 2011 at 5:10

GoogleCodeExporter commented 9 years ago
One mistake: should also set the alignments of the generated image control in 
addition to setting the ActualWidth/Height:

factory.SetValue(FrameworkElement.HorizontalAlignmentProperty, 
HorizontalAlignment.Left);
factory.SetValue(FrameworkElement.VerticalAlignmentProperty, 
VerticalAlignment.Top);

Original comment by cborde...@gmail.com on 28 Jun 2011 at 5:44

GoogleCodeExporter commented 9 years ago
This looks pretty cool.  Any chance of getting it into the next build?  

Original comment by aedward...@gmail.com on 14 Jul 2011 at 1:19