locked
Drag/Drop of custom controls in a GridView.

    Question

  • Hi,

    This is a follow up to a previous post: http://social.msdn.microsoft.com/Forums/en-AU/winappswithnativecode/thread/9c689033-4199-409b-b97d-e3fb985cdb0e

    To briefly recap, in the above post I was implementing a drag and drop operation on a GridView containing four rectangles (red, green, blue, yellow) laid out 2x2. The operation is the ability to start a drag operation over any rectangle within the GridView and drop over a destination rectangle in the same GridView, the result of which would be to swap the locations of those two rectangles in the grid view. The rectangles are stored in a collection, data bound to the GridView ItemsSource.

    I got that working fine. However, what I really want to do is use four instances of a custom control (my own WinRT C++/XAML component) for the GridView items, and it's not working in the same way as for the rectangles.

    The problem comes when I handle the Drop event and look at the OriginalSource property of DragEventArgs. When I was dropping Rectangles, OriginalSource (an Object^) could be cast to the  destination Rectangle, allowing me to look that rectangle up in the underlying collection and perform the swap.

    However, when I use a collection of custom controls, the OriginalSource property of DragEventArgs turns out to be a Border^. I tried looking at it's parent and child properties but they're both null, so I don't seem to have any way to get from the border to the custom control. I tried putting each custom control inside a Canvas before adding it to the GridView, but that didn't help.

    I don't know if it's directly related, but this WPF post seems to be discussing something similar:http://social.msdn.microsoft.com/forums/en-US/wpf/thread/f0e6f71d-5d98-4656-8a8d-a3d71fa81977/.

    I could avoid the need to look inside DragEventArgs if the GridView had some sort of IndexFromPoint()  function which allowed the index of the Gridview item under the mouse to be identified (I believe there is one in WPF).

    Could anyone advise on a way forward on either of these two fronts, i.e. identifying the control via DragEventArgs, or finding the GridView index from the mouse position? 



    • Edited by RobertHF Thursday, December 13, 2012 1:20 PM typo
    Thursday, December 13, 2012 1:14 PM

Answers

  • Hi,

    I think I've found my answer. According to this post: http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/5ff64d02-a9af-452b-a4e2-49cdeb4228fc/ , the approach in Silverlight is to cast OriginalSource to a FrameworkElement, and then use the DataContext property of the FrameworkElement:

    void Page::Dropping(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
    {
    	MyControl^ dropTarget;
    	FrameworkElement^ fe;
    
    	fe = dynamic_cast<FrameworkElement^>(e -> OriginalSource);
    	dropTarget = dynamic_cast<MyControl^>(fe -> DataContext);
    }

    I tried this and it works.

    Apologies for posting long questions and answering them myself. At least I have the excuse that it's not exactly obvious, and I had to go to Silverlight to get the answer.

    I'd still be interested to know if WinRT has any IndexFromPoint() functionality of the sort I mentioned above?

    • Marked as answer by Jesse Jiang Tuesday, December 18, 2012 5:52 AM
    Thursday, December 13, 2012 4:15 PM
  • "any IndexFromPoint()": The closest is ItemContainerGenerator.IndexFromContainer method (Windows) However it still requires to access the Container element.
    • Marked as answer by Jesse Jiang Tuesday, December 18, 2012 5:52 AM
    Thursday, December 13, 2012 5:01 PM

All replies

  • Hi,

    I think I've found my answer. According to this post: http://social.msdn.microsoft.com/Forums/en-US/silverlightcontrols/thread/5ff64d02-a9af-452b-a4e2-49cdeb4228fc/ , the approach in Silverlight is to cast OriginalSource to a FrameworkElement, and then use the DataContext property of the FrameworkElement:

    void Page::Dropping(Platform::Object^ sender, Windows::UI::Xaml::DragEventArgs^ e)
    {
    	MyControl^ dropTarget;
    	FrameworkElement^ fe;
    
    	fe = dynamic_cast<FrameworkElement^>(e -> OriginalSource);
    	dropTarget = dynamic_cast<MyControl^>(fe -> DataContext);
    }

    I tried this and it works.

    Apologies for posting long questions and answering them myself. At least I have the excuse that it's not exactly obvious, and I had to go to Silverlight to get the answer.

    I'd still be interested to know if WinRT has any IndexFromPoint() functionality of the sort I mentioned above?

    • Marked as answer by Jesse Jiang Tuesday, December 18, 2012 5:52 AM
    Thursday, December 13, 2012 4:15 PM
  • "any IndexFromPoint()": The closest is ItemContainerGenerator.IndexFromContainer method (Windows) However it still requires to access the Container element.
    • Marked as answer by Jesse Jiang Tuesday, December 18, 2012 5:52 AM
    Thursday, December 13, 2012 5:01 PM