Recognise drag and drop gestures in .Net MAUI/Xamarin forms

Swetha vennapusa
Nerd For Tech
Published in
3 min readApr 4, 2023

.NET MAUI drag and drop gesture recognizer enables items to be dragged from one screen location to another location using a gesture. It provides gesture recognizers for drag and drop.

DragGestureRecognizer

DropGestureRecognizer

Gesture recognizers will recognize the drag or drop gestures and will trigger events where we need to handle what happens on those events.

How to enable DragGestureRecognizer

If you want to drag an element you need to add DragGestureRecognizer

 <Label Text="Drag">
<Label.GestureRecognizers>
<DragGestureRecognizer/>
</Label.GestureRecognizers>
</Label>

we can disable drag gestures by setting the CanDrag property to false default value will be True.

DragStartingCommand is executed when the drag is first recognized and can pass parameters through DragStartingCommandParameters

DropCompletedCommand is executed when the drag source is dropped and can pass parameters through DropCompletedCommandParameter

it even fires events DragStarting and DropCompleted. It is better to use Command as we follow Mvvm and try to reduce code in code behind class

How to enable DropGestureRecognizer

Add DropGestureRecognizer to the element where you want to drop

<Frame>
<Frame.GestureRecognizers>
<DropGestureRecognizer/>
</Frame.GestureRecognizers>

we can disable drop gestures by setting the AllowDrop to false default value will be True.

It executes DropCommand, DragLeaveCommand, and DragOverCommand we can pass parameters to commands through DropCommandParameter, DragLeaveCommandParameter, and DragOverCommandParameter.

Let's have some fun Implementing it

As shown above we need to add drag and drop gestures where we need to drag the happy face emoji and drop it in the frame. If we try to drop others it should not allow us to drop.

Step 1:

Let's create a model and ViewModel that contains the list of images and text

public class ImageModel
{
public string ImageSource { get; set; }

public string ImageText { get; set; }
}
public class DragandDropViewModel: BaseViewModel
{
public DragandDropViewModel()
{
PrepareData();
}
private List<ImageModel> _imageList;
public List<ImageModel> ImageList
{
get
{
return _imageList;
}
set
{
_imageList = value;
OnPropertyChanged(nameof(ImageList));
}
}

private void PrepareData()
{
ImageList = new List<ImageModel>()
{
new ImageModel(){ImageSource="angry.png",ImageText="Angry"},
new ImageModel(){ImageSource="smile.png",ImageText="Happy"},
new ImageModel(){ImageSource="sad.png",ImageText="Sad"}
};
}

Now let us add Xaml Code that contains the collection view with DragGestureRecognizer and frame with DropGestureRecognizer

<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="GesturesSample.Views.DragandDropGesturesPage"
Title="DragandDrop Gestures">
<ContentPage.Content>

<Grid RowDefinitions="*,*" RowSpacing="10" Padding="20">
<CollectionView Grid.Row="0" x:Name="imageCollection"
ItemsSource="{Binding ImageList}">
<CollectionView.ItemsLayout>
<GridItemsLayout Orientation="Horizontal" HorizontalItemSpacing="10"/>
</CollectionView.ItemsLayout>
<CollectionView.ItemTemplate>
<DataTemplate>
<Frame HasShadow="False" Padding="10" HeightRequest="200">
<VerticalStackLayout VerticalOptions="CenterAndExpand">
<Image Source="{Binding ImageSource}" HeightRequest="80" WidthRequest="80">
<Image.GestureRecognizers>
<DragGestureRecognizer CanDrag="True"
DragStartingCommand="{Binding BindingContext.DragStartingCommand, Source={x:Reference imageCollection}}"
DragStartingCommandParameter="{Binding .}" />
</Image.GestureRecognizers>
</Image>
<Label Text="{Binding ImageText}" HorizontalOptions="CenterAndExpand"/>
</VerticalStackLayout>
</Frame>
</DataTemplate>

</CollectionView.ItemTemplate>

</CollectionView>

<Frame BorderColor="{Binding FrameColor}" Grid.Row="1">
<Grid>
<Label HorizontalOptions="CenterAndExpand" FontAttributes="Bold" TextColor="Blue" VerticalOptions="CenterAndExpand" Text="Drag Happy Face Here"/>
<Image Source="{Binding DraggedImage, Mode=TwoWay}"/>
</Grid>

<Frame.GestureRecognizers>
<DropGestureRecognizer AllowDrop="{Binding AllowDrop}" DropCommand="{Binding DropCommand}" />
</Frame.GestureRecognizers>
</Frame>


</Grid>
</ContentPage.Content>

</ContentPage>

Here we are using DragStartingCommand and sending the image item dragged as DragStartingCommandParameter and on DropGestureRecognizer we are using DropCommand

Now let us add commands in the ViewModel and implement them

public class DragandDropViewModel: BaseViewModel
{
public DragandDropViewModel()
{
PrepareData();
}
public ICommand DragStartingCommand=> new Command<ImageModel>(OnDragStarted);
public ICommand DropCommand=> new Command(onDrop);


private ImageModel dragedImageModel {get; set;}

private Color _frameColor=Colors.Black;
public Color FrameColor
{
get
{
return _frameColor;
}
set
{
_frameColor = value;
OnPropertyChanged(nameof(FrameColor));
}
}
private string _draggedImage;
public string DraggedImage
{
get
{
return _draggedImage;
}
set
{
_draggedImage = value;
OnPropertyChanged(nameof(DraggedImage));
}
}

private bool _allowDrop=true;
public bool AllowDrop
{
get
{
return _allowDrop;
}
set
{
_allowDrop = value;
OnPropertyChanged(nameof(AllowDrop));
}
}
private List<ImageModel> _imageList;
public List<ImageModel> ImageList
{
get
{
return _imageList;
}
set
{
_imageList = value;
OnPropertyChanged(nameof(ImageList));
}
}

private void PrepareData()
{
ImageList = new List<ImageModel>()
{
new ImageModel(){ImageSource="angry.png",ImageText="Angry"},
new ImageModel(){ImageSource="smile.png",ImageText="Happy"},
new ImageModel(){ImageSource="sad.png",ImageText="Sad"}
};
}

private void OnDragStarted(ImageModel imageModel)
{
AllowDrop = true;
DraggedImage = string.Empty;
dragedImageModel = new ImageModel();
dragedImageModel = imageModel;
}

private void onDrop()
{
if (dragedImageModel?.ImageText=="Happy")
{
DraggedImage = dragedImageModel.ImageSource;
FrameColor = Colors.Black;
}
else
{
AllowDrop = false;
FrameColor = Colors.Red;
}
}
}

On DragStartingCommand we are calling the OnDragStarted method where we are storing images that started dragging and onDrop we are checking whether it is a happy emoji. If yes we are showing the image dragged in the frame else we are making AllowDrop false throwing error.

--

--