{"id":698,"date":"2023-01-14T09:28:07","date_gmt":"2023-01-14T09:28:07","guid":{"rendered":"https:\/\/learnmobiledevelopment.com\/?p=698"},"modified":"2023-01-18T15:57:13","modified_gmt":"2023-01-18T15:57:13","slug":"drag-and-drop-gesture-to-collectionview","status":"publish","type":"post","link":"https:\/\/learnmobiledevelopment.com\/index.php\/2023\/01\/14\/drag-and-drop-gesture-to-collectionview\/","title":{"rendered":"How to use drag and drop gesture to CollectionView in MAUI"},"content":{"rendered":"\n<p>MAUI provides us drag and drop gestures which enables drag an element from one place and drop to another place. We can apply drag and drop gestures to any UI elements using <strong>DragGestureRecognizer<\/strong> and <strong>DropGestureRecognizer<\/strong> class. So In this article, I\u2019m going to show you how to use drag and drop gesture to CollectionView in MAUI.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>&nbsp;Note : <\/strong>To implement drag and drop in iOS platform minimum iOS version 11 required. <\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p style=\"font-size:25px\"><strong>Let\u2019s Start<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>1 &#8211; Setting up the UI<\/strong><\/p>\n\n\n\n<p class=\"has-medium-font-size\"><strong>1.1 &#8211; Create a MainPage.xaml<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"xml\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">&lt;?xml version=\"1.0\" encoding=\"utf-8\" ?>\n&lt;ContentPage\n    x:Class=\"MAUIDragDropCollectionViewItemsDemo.MainPage\"\n    xmlns=\"http:\/\/schemas.microsoft.com\/dotnet\/2021\/maui\"\n    xmlns:x=\"http:\/\/schemas.microsoft.com\/winfx\/2009\/xaml\"\n    xmlns:converter=\"clr-namespace:MAUIDragDropCollectionViewItemsDemo\"\n    x:Name=\"MainPageContainer\">\n\n    &lt;ContentPage.Resources>\n        &lt;ResourceDictionary>\n            &lt;converter:BoolToColorConverter x:Key=\"BoolToColor\" \/>\n        &lt;\/ResourceDictionary>\n    &lt;\/ContentPage.Resources>\n\n    &lt;Grid\n        Padding=\"30,5\"\n        HorizontalOptions=\"Fill\"\n        RowDefinitions=\"*,Auto\"\n        RowSpacing=\"10\"\n        VerticalOptions=\"Fill\">\n\n        &lt;CollectionView\n            Grid.Row=\"0\"\n            Margin=\"0,30,0,0\"\n            ItemsSource=\"{Binding UserList}\"\n            SelectionMode=\"None\">\n            &lt;CollectionView.ItemTemplate>\n                &lt;DataTemplate>\n                    &lt;Frame\n                        Padding=\"3\"\n                        BorderColor=\"{StaticResource Primary}\"\n                        CornerRadius=\"0\"\n                        IsClippedToBounds=\"True\">\n                        &lt;VerticalStackLayout>\n                            &lt;StackLayout\n                                Padding=\"10\"\n                                BackgroundColor=\"{Binding IsBeingDragged, Converter={StaticResource BoolToColor}}\"\n                                HeightRequest=\"60\"\n                                HorizontalOptions=\"FillAndExpand\"\n                                Orientation=\"Horizontal\"\n                                VerticalOptions=\"FillAndExpand\">\n\n                                &lt;!--  User Image  -->\n                                &lt;Image\n                                    HeightRequest=\"50\"\n                                    Source=\"user.png\"\n                                    WidthRequest=\"50\">\n                                    &lt;Image.Clip>\n                                        &lt;EllipseGeometry\n                                            Center=\"50,50\"\n                                            RadiusX=\"100\"\n                                            RadiusY=\"100\" \/>\n                                    &lt;\/Image.Clip>\n                                &lt;\/Image>\n\n                                &lt;!--  User Name  -->\n                                &lt;Label\n                                    x:Name=\"UserName\"\n                                    Margin=\"10,0,0,0\"\n                                    HorizontalOptions=\"FillAndExpand\"\n                                    Text=\"{Binding UserName}\"\n                                    TextColor=\"Black\"\n                                    VerticalTextAlignment=\"Center\" \/>\n\n                                &lt;!--  Delete Icon  -->\n                                &lt;Frame\n                                    Padding=\"7\"\n                                    CornerRadius=\"15\"\n                                    HeightRequest=\"30\"\n                                    HorizontalOptions=\"EndAndExpand\"\n                                    WidthRequest=\"30\">\n                                    &lt;Image Source=\"delete_user.png\" \/>\n                                    &lt;Frame.GestureRecognizers>\n                                        &lt;TapGestureRecognizer Command=\"{Binding BindingContext.DeleteUserCommand, Source={x:Reference MainPageContainer}}\" CommandParameter=\"{Binding .}\" \/>\n                                    &lt;\/Frame.GestureRecognizers>\n                                &lt;\/Frame>\n\n                                &lt;StackLayout.GestureRecognizers>\n                                    &lt;DragGestureRecognizer\n                                        CanDrag=\"True\"\n                                        DragStartingCommand=\"{Binding BindingContext.ItemDraggedCommand, Source={x:Reference MainPageContainer}}\"\n                                        DragStartingCommandParameter=\"{Binding}\" \/>\n                                    &lt;DropGestureRecognizer\n                                        AllowDrop=\"True\"\n                                        DragLeaveCommand=\"{Binding BindingContext.ItemDragLeaveCommand, Source={x:Reference MainPageContainer}}\"\n                                        DragLeaveCommandParameter=\"{Binding}\"\n                                        DragOverCommand=\"{Binding BindingContext.ItemDraggedOverCommand, Source={x:Reference MainPageContainer}}\"\n                                        DragOverCommandParameter=\"{Binding}\"\n                                        DropCommand=\"{Binding BindingContext.ItemDroppedCommand, Source={x:Reference MainPageContainer}}\"\n                                        DropCommandParameter=\"{Binding}\" \/>\n                                &lt;\/StackLayout.GestureRecognizers>\n                            &lt;\/StackLayout>\n\n                            &lt;StackLayout\n                                BackgroundColor=\"LightGray\"\n                                HeightRequest=\"30\"\n                                HorizontalOptions=\"FillAndExpand\"\n                                IsVisible=\"{Binding IsBeingDraggedOver}\"\n                                VerticalOptions=\"FillAndExpand\" \/>\n                        &lt;\/VerticalStackLayout>\n                    &lt;\/Frame>\n                &lt;\/DataTemplate>\n            &lt;\/CollectionView.ItemTemplate>\n        &lt;\/CollectionView>\n\n        &lt;VerticalStackLayout Grid.Row=\"1\">\n\n            &lt;Entry Placeholder=\"Type name\" Text=\"{Binding User}\" \/>\n\n            &lt;Button\n                Margin=\"0,10,0,0\"\n                Command=\"{Binding AddUserCommand}\"\n                HorizontalOptions=\"CenterAndExpand\"\n                Text=\"Add User\" \/>\n\n        &lt;\/VerticalStackLayout>\n\n    &lt;\/Grid>\n\n&lt;\/ContentPage><\/pre>\n\n\n\n<div style=\"height:16px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As in the above&nbsp;<strong>MainPage.xaml<\/strong>, I have taken&nbsp;<strong>CollectionView<\/strong>&nbsp;to show list of user and&nbsp;<strong>Entry\/Button<\/strong>&nbsp;to add new user.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>BoolToColorConverter<\/strong> is used for changing the color based on bool value passed at runtime.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li>And I have also used <strong>DragGestureRecognizer<\/strong> and <strong>DropGestureRecognizer<\/strong> gestures to collectionview item.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragStartingCommand<\/strong> &#8211; It&#8217;s a command which gets executed while dragging start.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragStartingCommandParameter<\/strong> &#8211; It&#8217;s an object type which passed to <strong>DragStartingCommand<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragLeaveCommand<\/strong> &#8211; It&#8217;s also a command which gets executed while an element is dragged out of the control\u2019s bounds.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragLeaveCommandParameter<\/strong> &#8211; It&#8217;s an object type which passed to <strong>DragLeaveCommand<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragOverCommand<\/strong> &#8211; It&#8217;s also a command which gets executed while an element is dragged over the control\u2019s bounds.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DragOverCommandParameter<\/strong> &#8211;  It&#8217;s an object type which passed to <strong>DragOverCommand<\/strong>.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DropCommand<\/strong> &#8211; It&#8217;s also a command which gets executed while an element is dropped over the target control.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>DropCommandParameter<\/strong> &#8211; It&#8217;s an object type which passed to <strong><strong>DropCommand<\/strong><\/strong>.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:33px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>1.2 &#8211; Create a BoolToColorConverter.cs<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using System.Globalization;\n\nnamespace MAUIDragDropCollectionViewItemsDemo\n{\n    public class BoolToColorConverter : IValueConverter\n    {\n        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)\n        {\n            var isBeingDragged = (bool?)value;\n            var result = (isBeingDragged ?? false) ? Color.FromArgb(\"#bcacdc\") : Color.FromArgb(\"#FFFFFF\");\n            return result;\n        }\n\n        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)\n        {\n            return value;\n        }\n    }\n}<\/pre>\n\n\n\n<div style=\"height:33px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>2 &#8211; Setting up the ViewModel<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"csharp\" data-enlighter-theme=\"dracula\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">using CommunityToolkit.Mvvm.ComponentModel;\nusing CommunityToolkit.Mvvm.Input;\nusing System.Collections.ObjectModel;\nusing System.Diagnostics;\n\nnamespace MAUIDragDropCollectionViewItemsDemo\n{\n    public partial class MainPageViewModel : ObservableObject\n    {\n        [ObservableProperty]\n        private ObservableCollection&lt;User> userList;\n\n        [ObservableProperty]\n        private string user;\n\n        private User _itemBeingDragged;\n\n        public MainPageViewModel()\n        {\n            GetUserList();\n        }\n\n        [RelayCommand]\n        public void AddUser()\n        {\n            Application.Current.Dispatcher.Dispatch(() =>\n            {\n                if (!string.IsNullOrEmpty(User))\n                {\n                    UserList.Add(new User() { UserName = User });\n                    User = string.Empty;\n                }\n            });\n        }\n\n        [RelayCommand]\n        public void DeleteUser(User user)\n        {\n            Application.Current.Dispatcher.Dispatch(() =>\n            {\n                if (UserList.Contains(user))\n                {\n                    UserList.Remove(user);\n                }\n            });\n        }\n\n        [RelayCommand]\n        public void ItemDragged(User user)\n        {\n            Debug.WriteLine($\"ItemDragged : {user?.UserName}\");\n\n            user.IsBeingDragged = true;\n            _itemBeingDragged = user;\n        }\n\n        [RelayCommand]\n        public void ItemDragLeave(User user)\n        {\n            Debug.WriteLine($\"ItemDragLeave : {user?.UserName}\");\n\n            user.IsBeingDraggedOver = false;\n        }\n\n        [RelayCommand]\n        public void ItemDraggedOver(User user)\n        {\n            Debug.WriteLine($\"ItemDraggedOver : {user?.UserName}\");\n\n            if (user == _itemBeingDragged)\n            {\n                user.IsBeingDragged = false;\n            }\n            user.IsBeingDraggedOver = user != _itemBeingDragged;\n        }\n\n        [RelayCommand]\n        public void ItemDropped(User user)\n        {\n            try\n            {\n                var itemToMove = _itemBeingDragged;\n                var itemToInsertBefore = user;\n\n                if (itemToMove == null || itemToInsertBefore == null || itemToMove == itemToInsertBefore)\n                    return;\n\n                int insertAtIndex = UserList.IndexOf(itemToInsertBefore);\n\n                if (insertAtIndex >= 0 &amp;&amp; insertAtIndex &lt; UserList.Count)\n                {\n                    UserList.Remove(itemToMove);\n                    UserList.Insert(insertAtIndex, itemToMove);\n\n                    itemToMove.IsBeingDragged = false;\n                    itemToInsertBefore.IsBeingDraggedOver = false;\n                }\n\n                Debug.WriteLine($\"ItemDropped: [{itemToMove?.UserName}] => [{itemToInsertBefore?.UserName}], target index = [{insertAtIndex}]\");\n            }\n            catch (Exception ex)\n            {\n                Debug.WriteLine(ex.Message);\n            }\n        }\n\n        private void GetUserList()\n        {\n            UserList = new ObservableCollection&lt;User>()\n            {\n                new User(){UserName = \"User 1\"},\n                new User(){UserName = \"User 2\"},\n                new User(){UserName = \"User 3\"},\n                new User(){UserName = \"User 4\"},\n                new User(){UserName = \"User 5\"},\n                new User(){UserName = \"User 6\"},\n            };\n        }\n    }\n\n    public partial class User : ObservableObject\n    {\n        [ObservableProperty]\n        private string userName;\n\n        [ObservableProperty]\n        private bool isBeingDragged;\n\n        [ObservableProperty]\n        private bool isBeingDraggedOver;\n    }\n}<\/pre>\n\n\n\n<div style=\"height:33px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<ul class=\"wp-block-list\">\n<li>As you will see I have used the <strong>ObservableObject<\/strong> class for data binding and I already explained about this in my last article. You can visit this <strong><a href=\"https:\/\/learnmobiledevelopment.com\/index.php\/2023\/01\/10\/observableobject-in-maui-for-data-binding\/\" target=\"_blank\" rel=\"noopener\" title=\"\">link<\/a><\/strong> for more details.<\/li>\n<\/ul>\n\n\n\n<div style=\"height:30px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>Result<\/strong> <\/p>\n\n\n\n<figure class=\"wp-block-video\"><video height=\"2796\" style=\"aspect-ratio: 1290 \/ 2796;\" width=\"1290\" controls src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/CollectionViewItemReorderning.mp4\"><\/video><\/figure>\n\n\n\n<div style=\"height:16px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p>That\u2019s all for now!<\/p>\n\n\n\n<p>You can check the full source code&nbsp;<strong><a href=\"https:\/\/github.com\/Alam-Ashraf\/MAUIDragDropCollectionViewItemsDemo\" target=\"_blank\" rel=\"noopener\" title=\"\">here<\/a>.<\/strong><\/p>\n\n\n\n<p>Happy Coding! <strong>\ud83d\ude00&nbsp;<\/strong><\/p>\n\n\n\n<div style=\"height:35px\" aria-hidden=\"true\" class=\"wp-block-spacer\"><\/div>\n\n\n\n<p class=\"has-medium-font-size\"><strong>You may also like<\/strong><\/p>\n\n\n\n<div class=\"wp-block-group is-content-justification-space-between is-nowrap is-layout-flex wp-container-core-group-is-layout-0dfbf163 wp-block-group-is-layout-flex\">\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\"><div class=\"wp-block-image\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/learnmobiledevelopment.com\/index.php\/2023\/01\/18\/item-reordering-to-collectionview\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView-1024x682.png\" alt=\"Item reordering to CollectionView\" class=\"wp-image-733\" width=\"512\" height=\"341\" srcset=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView-1024x682.png 1024w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView-300x200.png 300w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView-768x512.png 768w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView-850x566.png 850w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/Item-reordering-to-CollectionView.png 1384w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\">How to apply item reordering to CollectionView GridItemsLayout in MAUI<\/p>\n<\/div>\n\n\n\n<p><\/p>\n\n\n\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\">\n<div class=\"wp-block-group is-vertical is-content-justification-center is-layout-flex wp-container-core-group-is-layout-4b2eccd6 wp-block-group-is-layout-flex\"><div class=\"wp-block-image is-style-default\">\n<figure class=\"aligncenter size-large is-resized\"><a href=\"https:\/\/learnmobiledevelopment.com\/index.php\/2023\/01\/10\/observableobject-in-maui-for-data-binding\/\" target=\"_blank\" rel=\"noreferrer noopener\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI-1024x733.png\" alt=\"ObservableObject in MAUI\" class=\"wp-image-686\" width=\"512\" height=\"367\" srcset=\"https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI-1024x733.png 1024w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI-300x215.png 300w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI-768x550.png 768w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI-850x609.png 850w, https:\/\/learnmobiledevelopment.com\/wp-content\/uploads\/2023\/01\/ObservableObject-in-MAUI.png 1486w\" sizes=\"auto, (max-width: 512px) 100vw, 512px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p class=\"has-text-align-center\">How to use ObservableObject in MAUI for Data Binding<\/p>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>MAUI provides us drag and drop gestures which enables drag an element from one place and drop to another place. We can apply drag and drop gestures to any UI elements using DragGestureRecognizer and DropGestureRecognizer class. So In this article, I\u2019m going to show you how to use drag and drop gesture to CollectionView in&#8230;<\/p>\n","protected":false},"author":1,"featured_media":708,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"om_disable_all_campaigns":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[4,53],"tags":[58,59,57],"class_list":["post-698","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnetmaui","category-mvvm","tag-collectionview-item-reordering","tag-drag-and-drop-gestures-in-maui","tag-item-reordering-in-maui"],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/698","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/comments?post=698"}],"version-history":[{"count":16,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/698\/revisions"}],"predecessor-version":[{"id":735,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/posts\/698\/revisions\/735"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/media\/708"}],"wp:attachment":[{"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/media?parent=698"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/categories?post=698"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/learnmobiledevelopment.com\/index.php\/wp-json\/wp\/v2\/tags?post=698"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}