CollectionView with Gesture Recognizers in Xamarin Forms


Isn't it fun,

to instantly listen to a blog on the go? PLAY !

 
 

Gesture-Recognizers-in-Xamarin-Forms

In this blog, we will see the CollectionView with gesture recognizers and other CollectionView properties. The Collection View was introduced in version 4.0 of Xamarin forms. We can simply use the Collection View for displaying a list of data using the different layout specifications.

The Collection View aims at providing the performant alternative to ListView, and offers more flexibility. Collection View can only support the single and the multiple selections. A flexible layout model in the collection view allows data to be present horizontally or vertically.

Note that the collection view is only available on Android and iOS.

Now, let’s start with the simple demo with drag and drop using the collection view.


Step: 1

First Open Visual Studio 2017 or later and create a new Xamarin project.

Image: Create a Xamarin project

Secondly, select Blank App for Android and iOS platforms.

Image: Select the template and platform


Step: 2

After creating project, just add a new class file to bind the properties like name, category, title, etc. For adding the class file in our project right-click the project name in Solution Explorer -> Add -> Class. Then just add the below code to your class file.



ItemViewModel.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.CommunityToolkit.ObjectModel;

namespace GrouppedListReorder.ViewModels
{
    public class ItemsGroupViewModel : ObservableCollection
    {
        public string NameofCategory { get; set; }

        public ItemsGroupViewModel(string name, IEnumerable items)
            : base(items)
        {
            NameofCategory = name;
        }
    }

    public class ItemViewModel : ObservableObject
    {
        public string DiffCategory { get; set; }
        public string TitleofCategory { get; set; }

        private bool _isDraggedItems;
        public bool DraggedItems
        {
            get { return _isDraggedItems; }
            set { SetProperty(ref _isDraggedItems, value); }
        }

        private bool _isDroppedItems;
        public bool DroppedItems
        {
            get { return _isDroppedItems; }
            set { SetProperty(ref _isDroppedItems, value); }
        }
    }
}


Step: 3

Now, let’s create a design, you can create your design or paste this code in your Xaml file.

MainPage.Xaml





    
        
            


Step: 4

Now, open the MainPage.cs file and add the below code. Here, we can bind View to ViewModel.

MainPage.Xaml.cs


using System;
using System.Diagnostics;
using GrouppedListReorder.ViewModels;
using Xamarin.Forms;

namespace GrouppedListReorder
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new MainPageViewModel();
        }

        private void DragGestureRecognizer_DragStarting(Object sender, DragStartingEventArgs e)
        {
            var label = (Label)((Element)sender).Parent;
            Debug.WriteLine($"DragGestureRecognizer_DragStarting [{label.Text}]");

            e.Data.Properties["Label"] = label;
        }

        private void DropGestureRecognizer_Drop(Object sender, DropEventArgs e)
        {
            var label = (Label)((Element)sender).Parent;
            var dropLabel = (Label)e.Data.Properties["Label"];
            if (label == dropLabel)
                return;

            Debug.WriteLine($"DropGestureRecognizer_Drop [{dropLabel.Text}] => [{label.Text}]");

            var sourceContainer = (Grid)dropLabel.Parent;
            var targetContainer = (Grid)label.Parent;
            sourceContainer.Children.Remove(dropLabel);
            targetContainer.Children.Remove(label);
            sourceContainer.Children.Add(label);
            targetContainer.Children.Add(dropLabel);

            e.Handled = true;
        }

        private void DragGestureRecognizer_DragStarting_Collection(System.Object sender, Xamarin.Forms.DragStartingEventArgs e)
        {
        }

        private void DropGestureRecognizer_Drop_Collection(System.Object sender, Xamarin.Forms.DropEventArgs e)
        {
            e.Handled = true;
        }
    }
}

Planning to Hire Xamarin App Development Company ?

Your Search ends here.



Step: 5

MainPageViewModel.cs


using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GrouppedListReorder.Helpers;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
using Xamarin.Forms.Internals;

namespace GrouppedListReorder.ViewModels
{
    public class MainPageViewModel : ObservableObject
    {
        private ObservableCollection _items = new ObservableCollection();
        public ObservableCollection Items
        {
            get { return _items; }
            set { SetProperty(ref _items, value); }
        }

        private ObservableCollection _groupedItems = new ObservableCollection();
        public ObservableCollection GroupedItems
        {
            get { return _groupedItems; }
            set { SetProperty(ref _groupedItems, value); }
        }

        public ICommand StateRefresh { get; }

        public ICommand StateReset { get; }

        public ICommand StateTest { get; }

        public ICommand ItemDragged { get; }

        public ICommand ItemDraggedOver { get; }

        public ICommand ItemDragLeave { get; }

        public ICommand ItemDropped { get; }

        public MainPageViewModel()
        {
            StateRefresh = new Command(OnStateRefresh);
            StateReset = new Command(OnStateReset);
            StateTest = new Command(OnStateTest);
            ItemDragged = new Command(OnItemDragged);
            ItemDraggedOver = new Command(OnItemDraggedOver);
            ItemDragLeave = new Command(OnItemDragLeave);
            ItemDropped = new Command(i => OnItemDropped(i));
            ResetItemsState();
        }

        private void OnStateRefresh()
        {
            Debug.WriteLine($"OnStateRefresh");
            OnPropertyChanged(nameof(Items));
            PrintItemsState();
        }

        private void OnStateReset()
        {
            Debug.WriteLine($"OnStateReset");
            ResetItemsState();
            PrintItemsState();
        }

        private void OnStateTest()
        {
            Items.RemoveAt(4);
            Items.Insert(0, new ItemViewModel { TitleofCategory = "Item new 1" });
            PrintItemsState();
        }

        private void OnItemDragged(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDragged: {item?.TitleofCategory}");
            Items.ForEach(i => i.DraggedItems = item == i);
        }

        private void OnItemDraggedOver(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDraggedOver: {item?.TitleofCategory}");
            var itemBeingDragged = _items.FirstOrDefault(i => i.DraggedItems);
            Items.ForEach(i => i.DroppedItems = item == i && item != itemBeingDragged);
        }

        private void OnItemDragLeave(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDragLeave: {item?.TitleofCategory}");
            Items.ForEach(i => i.DroppedItems = false);
        }

        private async Task OnItemDropped(ItemViewModel item)
        {
            var itemToMove = _items.First(i => i.DraggedItems);
            var itemToInsertBefore = item;

            var categoryToMoveFrom = GroupedItems.First(g => g.Contains(itemToMove));
            categoryToMoveFrom.Remove(itemToMove);

            var categoryToMoveTo = GroupedItems.First(g => g.Contains(itemToInsertBefore));
            var insertAtIndex = categoryToMoveTo.IndexOf(itemToInsertBefore);
            itemToMove.DiffCategory = categoryToMoveFrom.NameofCategory;
            categoryToMoveTo.Insert(insertAtIndex, itemToMove);
            itemToMove.DraggedItems = false;
            itemToInsertBefore.DroppedItems = false;
            Debug.WriteLine($"OnItemDropped: [{itemToMove?.TitleofCategory}] => [{itemToInsertBefore?.TitleofCategory}], target index = [{insertAtIndex}]");

            PrintItemsState();
        }

        private void ResetItemsState()
        {
            Items.Clear();
            Items.Add(new ItemViewModel { DiffCategory = "Category 1", TitleofCategory = "Item 1" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 1", TitleofCategory = "Item 2" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 3" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 4" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 5" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 6" });

            GroupedItems = (ObservableCollection)Items
                .GroupBy(i => i.DiffCategory)
                .Select(g => new ItemsGroupViewModel(g.Key, g));
        }
    }
}

Conclusion

In this blog, we have learned how to work with drag and drop items with the gesture recognizer in Collection View. We can also customize the effect and look for an item while the item being dragged and drop.

CollectionView with Gesture Recognizers in Xamarin Forms

Gesture-Recognizers-in-Xamarin-Forms

In this blog, we will see the CollectionView with gesture recognizers and other CollectionView properties. The Collection View was introduced in version 4.0 of Xamarin forms. We can simply use the Collection View for displaying a list of data using the different layout specifications.

The Collection View aims at providing the performant alternative to ListView, and offers more flexibility. Collection View can only support the single and the multiple selections. A flexible layout model in the collection view allows data to be present horizontally or vertically.

Note that the collection view is only available on Android and iOS.

Now, let’s start with the simple demo with drag and drop using the collection view.


Step: 1

First Open Visual Studio 2017 or later and create a new Xamarin project.

Image: Create a Xamarin project

Secondly, select Blank App for Android and iOS platforms.

Image: Select the template and platform


Step: 2

After creating project, just add a new class file to bind the properties like name, category, title, etc. For adding the class file in our project right-click the project name in Solution Explorer -> Add -> Class. Then just add the below code to your class file.



ItemViewModel.cs

using System.Collections.Generic;
using System.Collections.ObjectModel;
using Xamarin.CommunityToolkit.ObjectModel;

namespace GrouppedListReorder.ViewModels
{
    public class ItemsGroupViewModel : ObservableCollection
    {
        public string NameofCategory { get; set; }

        public ItemsGroupViewModel(string name, IEnumerable items)
            : base(items)
        {
            NameofCategory = name;
        }
    }

    public class ItemViewModel : ObservableObject
    {
        public string DiffCategory { get; set; }
        public string TitleofCategory { get; set; }

        private bool _isDraggedItems;
        public bool DraggedItems
        {
            get { return _isDraggedItems; }
            set { SetProperty(ref _isDraggedItems, value); }
        }

        private bool _isDroppedItems;
        public bool DroppedItems
        {
            get { return _isDroppedItems; }
            set { SetProperty(ref _isDroppedItems, value); }
        }
    }
}


Step: 3

Now, let’s create a design, you can create your design or paste this code in your Xaml file.

MainPage.Xaml





    
        
            


Step: 4

Now, open the MainPage.cs file and add the below code. Here, we can bind View to ViewModel.

MainPage.Xaml.cs


using System;
using System.Diagnostics;
using GrouppedListReorder.ViewModels;
using Xamarin.Forms;

namespace GrouppedListReorder
{
    public partial class MainPage : ContentPage
    {
        public MainPage()
        {
            InitializeComponent();
            BindingContext = new MainPageViewModel();
        }

        private void DragGestureRecognizer_DragStarting(Object sender, DragStartingEventArgs e)
        {
            var label = (Label)((Element)sender).Parent;
            Debug.WriteLine($"DragGestureRecognizer_DragStarting [{label.Text}]");

            e.Data.Properties["Label"] = label;
        }

        private void DropGestureRecognizer_Drop(Object sender, DropEventArgs e)
        {
            var label = (Label)((Element)sender).Parent;
            var dropLabel = (Label)e.Data.Properties["Label"];
            if (label == dropLabel)
                return;

            Debug.WriteLine($"DropGestureRecognizer_Drop [{dropLabel.Text}] => [{label.Text}]");

            var sourceContainer = (Grid)dropLabel.Parent;
            var targetContainer = (Grid)label.Parent;
            sourceContainer.Children.Remove(dropLabel);
            targetContainer.Children.Remove(label);
            sourceContainer.Children.Add(label);
            targetContainer.Children.Add(dropLabel);

            e.Handled = true;
        }

        private void DragGestureRecognizer_DragStarting_Collection(System.Object sender, Xamarin.Forms.DragStartingEventArgs e)
        {
        }

        private void DropGestureRecognizer_Drop_Collection(System.Object sender, Xamarin.Forms.DropEventArgs e)
        {
            e.Handled = true;
        }
    }
}

Planning to Hire Xamarin App Development Company ?

Your Search ends here.



Step: 5

MainPageViewModel.cs


using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GrouppedListReorder.Helpers;
using Xamarin.CommunityToolkit.ObjectModel;
using Xamarin.Forms;
using Xamarin.Forms.Internals;

namespace GrouppedListReorder.ViewModels
{
    public class MainPageViewModel : ObservableObject
    {
        private ObservableCollection _items = new ObservableCollection();
        public ObservableCollection Items
        {
            get { return _items; }
            set { SetProperty(ref _items, value); }
        }

        private ObservableCollection _groupedItems = new ObservableCollection();
        public ObservableCollection GroupedItems
        {
            get { return _groupedItems; }
            set { SetProperty(ref _groupedItems, value); }
        }

        public ICommand StateRefresh { get; }

        public ICommand StateReset { get; }

        public ICommand StateTest { get; }

        public ICommand ItemDragged { get; }

        public ICommand ItemDraggedOver { get; }

        public ICommand ItemDragLeave { get; }

        public ICommand ItemDropped { get; }

        public MainPageViewModel()
        {
            StateRefresh = new Command(OnStateRefresh);
            StateReset = new Command(OnStateReset);
            StateTest = new Command(OnStateTest);
            ItemDragged = new Command(OnItemDragged);
            ItemDraggedOver = new Command(OnItemDraggedOver);
            ItemDragLeave = new Command(OnItemDragLeave);
            ItemDropped = new Command(i => OnItemDropped(i));
            ResetItemsState();
        }

        private void OnStateRefresh()
        {
            Debug.WriteLine($"OnStateRefresh");
            OnPropertyChanged(nameof(Items));
            PrintItemsState();
        }

        private void OnStateReset()
        {
            Debug.WriteLine($"OnStateReset");
            ResetItemsState();
            PrintItemsState();
        }

        private void OnStateTest()
        {
            Items.RemoveAt(4);
            Items.Insert(0, new ItemViewModel { TitleofCategory = "Item new 1" });
            PrintItemsState();
        }

        private void OnItemDragged(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDragged: {item?.TitleofCategory}");
            Items.ForEach(i => i.DraggedItems = item == i);
        }

        private void OnItemDraggedOver(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDraggedOver: {item?.TitleofCategory}");
            var itemBeingDragged = _items.FirstOrDefault(i => i.DraggedItems);
            Items.ForEach(i => i.DroppedItems = item == i && item != itemBeingDragged);
        }

        private void OnItemDragLeave(ItemViewModel item)
        {
            Debug.WriteLine($"OnItemDragLeave: {item?.TitleofCategory}");
            Items.ForEach(i => i.DroppedItems = false);
        }

        private async Task OnItemDropped(ItemViewModel item)
        {
            var itemToMove = _items.First(i => i.DraggedItems);
            var itemToInsertBefore = item;

            var categoryToMoveFrom = GroupedItems.First(g => g.Contains(itemToMove));
            categoryToMoveFrom.Remove(itemToMove);

            var categoryToMoveTo = GroupedItems.First(g => g.Contains(itemToInsertBefore));
            var insertAtIndex = categoryToMoveTo.IndexOf(itemToInsertBefore);
            itemToMove.DiffCategory = categoryToMoveFrom.NameofCategory;
            categoryToMoveTo.Insert(insertAtIndex, itemToMove);
            itemToMove.DraggedItems = false;
            itemToInsertBefore.DroppedItems = false;
            Debug.WriteLine($"OnItemDropped: [{itemToMove?.TitleofCategory}] => [{itemToInsertBefore?.TitleofCategory}], target index = [{insertAtIndex}]");

            PrintItemsState();
        }

        private void ResetItemsState()
        {
            Items.Clear();
            Items.Add(new ItemViewModel { DiffCategory = "Category 1", TitleofCategory = "Item 1" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 1", TitleofCategory = "Item 2" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 3" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 4" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 5" });
            Items.Add(new ItemViewModel { DiffCategory = "Category 2", TitleofCategory = "Item 6" });

            GroupedItems = (ObservableCollection)Items
                .GroupBy(i => i.DiffCategory)
                .Select(g => new ItemsGroupViewModel(g.Key, g));
        }
    }
}

Conclusion

In this blog, we have learned how to work with drag and drop items with the gesture recognizer in Collection View. We can also customize the effect and look for an item while the item being dragged and drop.