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

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

Closed
punker76 opened this issue Feb 18, 2013 · 3 comments
Closed

Comments

@punker76
Copy link
Owner

Original author: [email protected] (June 28, 2011 17:10:07)

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 [email protected]
    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 [email protected]

    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 [email protected]
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: http://code.google.com/p/gong-wpf-dragdrop/issues/detail?id=38

@punker76
Copy link
Owner Author

From [email protected] on June 28, 2011 17:44:10
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);

@punker76
Copy link
Owner Author

From [email protected] on July 14, 2011 01:19:00
This looks pretty cool. Any chance of getting it into the next build?

@punker76
Copy link
Owner Author

improved in version 0.1.3.6

punker76 added a commit that referenced this issue Jul 19, 2013
thx to @Troglodactyl (https://github.com/Troglodactyl)
+ add DragMouseAnchorPoint dependency property adorner positioning
+ capture screen for default drag adorner
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant