Introduction:
Hi everybody,
As we know that drag and drop of UI controls/elements is very commonly used in puzzle like drag and match games. While working on an application Kids IQ, an application by Ilmasoft. I faced problem to make by images draggable. Link of the application is given you can check out the working of draggable images developed by me.
So after finding the appropriate solution and completing the project successfully I thought to write a blog post which covers the dragging and dropping of UI controls/elements.
Note: It can be any control/elements like Button, Grid, Image etc.
In this blog we will learn
1- How to make a draggable control?
2- How to detect the position of control after dropping it?
3- How to set bounds of draggable control??
4- How to apply animation while control is moving back to its original position?
Before starting let me tell you that there is no rocket science to move or drag controls, all is the game of manipulation events and transformation of control.
Lets start by creating new project
1- Open Visual Studio.
2- Create New Project.
3- Add any image into your project.
4- Open MainPage.xaml from solution explorer.
5- Add an UI control/element "Image", give name and source of added image to it as I have used "egg.png" in my sample project.
6- It is important to set its Vertical Alignment to Top and Horizontal Alignment to Left
7- Add Event handlers of Manipulation for Egg image.
Let me explain you manipulation events and their workings which is our first module of this topic or blog post.
There are five different events which handle manipulation data of any control.
1- Manipulation Starting
2- Manipulation Started
3- Manipulation Delta
4- Manipulation Completed
5- Manipulation Inertia Starting.
1- Making draggable Control
To make a control draggable we only need to use Manipulation Detla, Manipulation Delta event fires when the dragging is applied on it.
So we will create event handler of Manipulation Delta for our Egg image to make it draggable in constructor of MainPage and set the Manipulation mode to "All".
After creating event handler of Manipulation delta you will see an event is automatically created below the constructor like in the image below.
1- Paste the code given below in constructor
Egg.ManipulationDelta +=Egg_ManipulationDelta;
Egg.ManipulationMode = ManipulationModes.All;
2- Paste the following code in event handler.
double NewPosX, NewPosY;
private void Egg_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
var imagetrans = Egg.TransformToVisual(this);
NewPosX = Egg.Margin.Left + e.Delta.Translation.X;
NewPosY = Egg.Margin.Top + e.Delta.Translation.Y;
Egg.Margin = new Thickness(NewPosX, NewPosY, 0, 0);
}
Build the project, run it by pressing Ctrl + F5 you will see the screen like this.
Your application will look like this now try to drag egg image anywhere you will feel good.
2- Dropping of control to specific point/region
Our next module is to detect dropping of control to specific point or region. If control will not be dropped to that particular point or specified region it will move back to its previous position automatically otherwise it will stay there.So to detect the position of control after being dragged there is another event handler named "Manipulation Completed" which will be fired automatically when the dragging of controls is completed by the user.
So again add a new event handler of manipulation completed.
1- Paste the following code in constructor as we did for manipulation delta
Egg.ManipulationCompleted += Egg_ManipulationCompleted;
2- Paste the code below after Egg_ManipulationDetla Event
private void Egg_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
}
3- put the break point at opening brace of Manipulation Completed Event and build and run solution again.
4- Drag the egg image and drop it you will see application will break when you drop the image after dragging it.
So in this case you can get the actual position of dragged control and compare it with your sepecific region or point in Manipulation Completed Event.
Now as we disscussed above that if the image or control is dragged and not dropped to desired location it should go back to its previous position. So to do this we need to get position or location(Points) of draggable image before dragging it.
To get position of image before dragging and after dropping paste the code below in MainPage.xaml.cs
1- Write this code before constructor
Point PositionBeforeDragging, PositionAfterDropping;
PositionBeforeDragging = new Point(Egg.Margin.Left, Egg.Margin.Top);
4- Now paste the few lines of code given below in Manipulation Completed Event to perform desirable action.
PositionAfterDropping = new Point(NewPosX, NewPosY);
if(PositionAfterDropping.X > 500 && PositionAfterDropping.X > 500)
{
var dia = new MessageDialog("Correct");
await dia.ShowAsync();
}
else
{
Egg.Margin = new Thickness(PositionBeforeDragging.X, PositionBeforeDragging.Y,0,0);
}
This condition shows that if image is dragged and its X and Y becomes greater than 500 it will stay there and say correct otherwise it will move back to its previous position.
You can change this condition according to your logic, that if you want to drop control on another control just get points of other control as same we have done above and match the position or points by applying conditions in Manipulation Completed Event.
3- Set Bounds for draggable control.
After making control draggable you need to set bounds that control should not move outside the screen, it is very easy to implement its logic just apply a condition in Manipulation Delta Event1- Name the main grid as "main".
2- Replace this line in ManipulationDelta Event Egg.Margin = new Thickness(NewPosX, NewPosY, 0, 0);
With
if (NewPosX > 0 && NewPosX + Egg.ActualWidth < main.ActualWidth)
{
if (NewPosY > 0 && NewPosY + Egg.ActualHeight < main.ActualHeight)
{
Egg.Margin = new Thickness(NewPosX, NewPosY, 0, 0);
}
}
in Manipulation Delta
4- Animate control while moving back to its original Position.
Egg.Tranistions = null;
And paste the code below at starting of Manipulation Completed Event
Transition trans = new EdgeUIThemeTransition { Edge = EdgeTransitionLocation.Top };
Egg.Transitions = new TransitionCollection();
Egg.Transitions.Add(trans);
Now you are done with dragging and dropping of control.
Now your whole code will look like this.
MainPage.xaml.cs
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Popups;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Media.Animation;
using Windows.UI.Xaml.Media.Imaging;
using Windows.UI.Xaml.Navigation;
// The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=234238
namespace DragandDrop
{
public sealed partial class MainPage : Page
{
Point PositionBeforeDragging, PositionAfterDropping;
public MainPage()
{
this.InitializeComponent();
PositionBeforeDragging = new Point(Egg.Margin.Left, Egg.Margin.Top);
Egg.ManipulationDelta +=Egg_ManipulationDelta;
Egg.ManipulationCompleted += Egg_ManipulationCompleted;
Egg.ManipulationMode = ManipulationModes.All;
}
double NewPosX, NewPosY;
private void Egg_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
{
Egg.Transitions = null;
var imagetrans = Egg.TransformToVisual(this);
NewPosX = Egg.Margin.Left + e.Delta.Translation.X;
NewPosY = Egg.Margin.Top + e.Delta.Translation.Y;
if (NewPosX > 0 && NewPosX + Egg.ActualWidth < main.ActualWidth)
{
if (NewPosY > 0 && NewPosY + Egg.ActualHeight < main.ActualHeight)
{
Egg.Margin = new Thickness(NewPosX, NewPosY, 0, 0);
}
}
}
private async void Egg_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
Transition trans = new EdgeUIThemeTransition { Edge = EdgeTransitionLocation.Top };
Egg.Transitions = new TransitionCollection();
Egg.Transitions.Add(trans);
PositionAfterDropping = new Point(NewPosX, NewPosY);
if(PositionAfterDropping.X > 500 && PositionAfterDropping.X > 500)
{
var dia = new MessageDialog("Correct");
await dia.ShowAsync();
}
else
{
Egg.Margin = new Thickness(PositionBeforeDragging.X, PositionBeforeDragging.Y,0,0);
}
}
}
}
<Page
x:Class="DragandDrop.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:DragandDrop"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid Background="White" Name="main">
<Image x:Name="Egg" HorizontalAlignment="Left" Height="111" Margin="56,60,0,0" VerticalAlignment="Top" Width="80" Source="egg.png"/>
</Grid>
</Page>
Now you have successfully implemented drag and drop on UI Control in Windows Store Application