Search code examples
windows-phone-7drag-and-dropexpression-blendwindows-phone

Multi-Touch UI : Drag And Drop multiple objects at the same time


Is there any way to move multiple objects at the same time in Windows Phone ? (if I move my left & right indexes, I want to move both items)

I find two solutions for implementing drag&drop on Windows Phone. However, I am restricted to move only one item at the same time.

With Expression Blend

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
       <Image Margin="129,112,167,122" Source="mypicture.png" Stretch="Fill">
                <Custom:Interaction.Behaviors>
                    <il:MouseDragElementBehavior/>
                </Custom:Interaction.Behaviors>
       </Image>
</Grid>

With Windows Phone Toolkit

<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
             <Rectangle x:Name="myRectangle" Width="200" Height="200" Fill="Blue">
                 <toolkit:GestureService.GestureListener>
                     <toolkit:GestureListener DragDelta="GestureListener_DragDelta"/> 
                 </toolkit:GestureService.GestureListener>
             </Rectangle>
 </Grid>

Solution

  • In fact, the solution is to use Touch.FrameReported

    // MainPage.xaml
    <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
        <Rectangle x:Name="RedRect" Width="100" Height="100" Fill="Red">
            <Rectangle.RenderTransform>
                <TranslateTransform x:Name="RedTransform" Y="-100" />
            </Rectangle.RenderTransform>
        </Rectangle>
        <Rectangle x:Name="BlueRect" Width="100" Height="100" Fill="Blue">
            <Rectangle.RenderTransform>
                <TranslateTransform x:Name="BlueTransform" Y="100" />
            </Rectangle.RenderTransform>
        </Rectangle>
    </Grid>
    
    // MainPage.xaml.cs
    public partial class MainPage : PhoneApplicationPage
    {
        private Dictionary<int, RectInfo> _rects = new Dictionary<int, RectInfo>();
    
        // Constructor
        public MainPage()
        {
            InitializeComponent();
    
            // Register handler for Touch.FrameReported events
            Touch.FrameReported += new TouchFrameEventHandler(OnFrameReported);
        }
    
        private void OnFrameReported(object sender, TouchFrameEventArgs e)
        {
            TouchPointCollection points = e.GetTouchPoints(null);
    
            foreach (TouchPoint point in points)
            {
                if (point.Action == TouchAction.Down)
                {
                    // Find out if a rectangle was touched
                    Rectangle rect = null;
    
                    if (point.TouchDevice.DirectlyOver == RedRect)
                        rect = RedRect;
                    else if (point.TouchDevice.DirectlyOver == BlueRect)
                        rect = BlueRect;
    
                    // If the answer is yes, associate the "device" (finger) ID with
                    // the rectangle and store information regarding that rectangle.
                    // Then change the rectangle's fill color to yellow.
                    if (rect != null)
                    {
                        TranslateTransform transform =
                            rect.RenderTransform as TranslateTransform;
                        RectInfo ri = new RectInfo() { Rect = rect, Translation =
                            new Point(transform.X, transform.Y), StartPos = point.Position,
                            Fill = rect.Fill };
                        _rects.Add(point.TouchDevice.Id, ri);
                        rect.Fill = new SolidColorBrush(Colors.Yellow);
                    }
                }
                else if (point.Action == TouchAction.Move)
                {
                    // Find the rectangle (if any) associated with the finger being moved
                    int id = point.TouchDevice.Id;
    
                    RectInfo ri = null;
                    _rects.TryGetValue(id, out ri);
    
                    if (ri != null)
                    {
                        Rectangle rect = ri.Rect;
                        TranslateTransform transform =
                            rect.RenderTransform as TranslateTransform;
    
                        // Get the current position of the cursor
                        Point pos = point.Position;
    
                        // Compute the offset from the starting position
                        double dx = pos.X - ri.StartPos.X;
                        double dy = pos.Y - ri.StartPos.Y;
    
                        // Apply the deltas to the transform
                        transform.X = ri.Translation.X + dx;
                        transform.Y = ri.Translation.Y + dy;
                    }
                }
                else if (point.Action == TouchAction.Up)
                {
                    // Find the rectangle (if any) associated with the finger being moved
                    int id = point.TouchDevice.Id;
    
                    RectInfo ri = null;
                    _rects.TryGetValue(id, out ri);
    
                    if (ri != null)
                    {
                        // Restore the original fill color of the rectangle associated
                        // with the finger that was just lifted
                        Rectangle rect = ri.Rect;
                        rect.Fill = ri.Fill;
    
                        // Remove the finger ID from the dictionary
                        _rects.Remove(id);
                    }
                }
            }
        }
    }
    
    public class RectInfo
    {
        public Rectangle Rect;
        public Point Translation;
        public Point StartPos;
        public Brush Fill;
    }