New to Telerik UI for .NET MAUI? Start a free 30-day trial
.NET MAUI CollectionView Reorder Grouped Items
The .NET MAUI CollectionView provides the option to customize its drag-and-drop behavior and implement custom logic when items are dropped. This can be useful when you need to allow the users to move items between different groups in a grouped scenario.
To customize the behavior, you can create a new class that derives from CollectionViewDragDropBehavior
and override its virtual methods, such as:
CanStartDrag
(CollectionViewDragDropState
state)—Returns a boolean value specifying whether the drag operation can be started.CanDrop
(CollectionViewDragDropState
state)—Returns a value specifying whether the current drop operation can be completed.Drop
(CollectionViewDragDropState
state)—Completes the drop operation. This method is called only in the context of the drop target control.
The following example demonstrates how you can implement a custom logic on the drop event to allow moving items between groups:
1. Add a sample CollectionViewDragDropBehavior
class and override its Drop
method:
c#
public class CustomDragDropBehavior : CollectionViewDragDropBehavior
{
public override void Drop(CollectionViewDragDropContext state)
{
var collectionView = this.CollectionView;
if (collectionView == null)
{
return;
}
var hasGrouping = collectionView.GroupDescriptors.Count > 0;
if (hasGrouping)
{
var dataView = collectionView.GetDataView();
var dropTargetItem = state.DropTargetItem;
var draggedItem = state.DraggedItem;
if (dropTargetItem == draggedItem)
{
return;
}
var destinationGroup = dataView.GetParentGroup(dropTargetItem);
if (destinationGroup != null)
{
var childItems = destinationGroup.ChildItems;
int dropIndex = GetIndex(childItems, state.DropTargetItem);
dropIndex = state.Placement == ItemDropPlacement.After ? dropIndex + 1 : dropIndex;
var destinationItemsSource = state.DestinationItemsSource;
var sourceItemsSource = state.SourceItemsSource;
if (sourceItemsSource != null && destinationItemsSource == sourceItemsSource && dataView.GetParentGroup(draggedItem) == destinationGroup)
{
var removeIndex = GetIndex(childItems, draggedItem);
if (dropIndex > removeIndex)
{
dropIndex = Math.Clamp(dropIndex - 1, 0, childItems.Count - 1);
}
}
destinationItemsSource.Remove(draggedItem);
((DataModel)draggedItem).Country = (string)destinationGroup.Key;
((DataModel)draggedItem).Continent = (string)destinationGroup.ParentGroup.Key;
destinationItemsSource.Insert(dropIndex, draggedItem);
}
}
else
{
base.Drop(state);
}
}
public int GetIndex(IEnumerable list, object item)
{
int num = -1;
foreach (object item2 in list)
{
num++;
if (item2.Equals(item))
{
return num;
}
}
return ~num;
}
}
2. Add a CollectionView control to the page:
xaml
<telerik:RadCollectionView x:Name="collectionView"
ItemsSource="{Binding Locations}"
IsDragDropEnabled="True"
DisplayMemberPath="City">
<telerik:RadCollectionView.GroupDescriptors>
<telerik:PropertyGroupDescriptor PropertyName="Continent" />
<telerik:PropertyGroupDescriptor PropertyName="Country" />
</telerik:RadCollectionView.GroupDescriptors>
<telerik:RadCollectionView.DragDropBehavior>
<local:CustomDragDropBehavior />
</telerik:RadCollectionView.DragDropBehavior>
</telerik:RadCollectionView>
3. Define the following business object:
c#
public class DataModel : NotifyPropertyChangedBase
{
private string continent;
private string country;
private string city;
private int id;
public string Continent
{
get => this.continent;
set => this.UpdateValue(ref this.continent, value);
}
public string Country
{
get => this.country;
set => this.UpdateValue(ref this.country, value);
}
public string City
{
get => this.city;
set => this.UpdateValue(ref this.city, value);
}
public int Id
{
get => this.id;
set => this.UpdateValue(ref this.id, value);
}
}
4. Create a ViewModel
class as shown below:
c#
public class ViewModel : NotifyPropertyChangedBase
{
public ViewModel()
{
this.Locations = new ObservableCollection<DataModel>
{
new DataModel { Continent = "Europe", Country = "Austria", City = "Graz", Id = 1 },
new DataModel { Continent = "Europe", Country = "Austria", City = "Innsbruck", Id = 2 },
new DataModel { Continent = "Europe", Country = "Austria", City = "Ratz", Id = 3 },
new DataModel { Continent = "Europe", Country = "Austria", City = "Vienna", Id = 4 },
new DataModel { Continent = "Europe", Country = "Belgium", City = "Antwerp", Id = 5 },
new DataModel { Continent = "Europe", Country = "Belgium", City = "Charleroi", Id = 6 },
new DataModel { Continent = "Europe", Country = "Belgium", City = "Schaffen", Id = 7 },
new DataModel { Continent = "Europe", Country = "Denmark", City = "Copenhagen", Id = 8 },
new DataModel { Continent = "Europe", Country = "Denmark", City = "Odense", Id = 9 },
new DataModel { Continent = "Europe", Country = "France", City = "Nice", Id = 10 },
new DataModel { Continent = "Europe", Country = "France", City = "Paris", Id = 11 },
new DataModel { Continent = "Europe", Country = "Germany", City = "Baden-Baden", Id = 12 },
new DataModel { Continent = "Europe", Country = "Germany", City = "Berlin", Id = 13 },
new DataModel { Continent = "Europe", Country = "Germany", City = "Hamburg", Id = 14 },
new DataModel { Continent = "Europe", Country = "Germany", City = "Munich", Id = 15 },
new DataModel { Continent = "Europe", Country = "Germany", City = "Nuremberg", Id = 16 },
new DataModel { Continent = "Europe", Country = "Italy", City = "Bari", Id = 17 },
new DataModel { Continent = "Europe", Country = "Italy", City = "Rome", Id = 18 },
new DataModel { Continent = "Europe", Country = "Netherlands", City = "Amsterdam", Id = 19 },
new DataModel { Continent = "Europe", Country = "Netherlands", City = "Eindhoven", Id = 20 },
new DataModel { Continent = "Europe", Country = "Netherlands", City = "Rotterdam", Id = 21 },
new DataModel { Continent = "Europe", Country = "Portugal", City = "Lisbon", Id = 22 },
new DataModel { Continent = "Europe", Country = "Portugal", City = "Porto", Id = 23 },
new DataModel { Continent = "Europe", Country = "Spain", City = "Barcelona", Id = 24 },
new DataModel { Continent = "Europe", Country = "Spain", City = "Madrid", Id = 25 },
new DataModel { Continent = "Europe", Country = "United Kingdom", City = "London", Id = 26 },
new DataModel { Continent = "Europe", Country = "United Kingdom", City = "Manchester", Id = 27 },
new DataModel { Continent = "North America", Country = "United States", City = "New York", Id = 28 },
new DataModel { Continent = "North America", Country = "United States", City = "Los Angeles", Id = 29 },
new DataModel { Continent = "North America", Country = "United States", City = "Chicago", Id = 30 },
new DataModel { Continent = "North America", Country = "United States", City = "Boston", Id = 31 },
new DataModel { Continent = "North America", Country = "United States", City = "San Francisco", Id = 32 },
new DataModel { Continent = "North America", Country = "Canada", City = "Toronto", Id = 33 },
new DataModel { Continent = "North America", Country = "Canada", City = "Vancouver", Id = 34 },
new DataModel { Continent = "North America", Country = "Canada", City = "Ottawa", Id = 35 },
new DataModel { Continent = "South America", Country = "Brazil", City = "Rio de Janeiro", Id = 36 },
new DataModel { Continent = "South America", Country = "Brazil", City = "Sao Paulo", Id = 37 },
new DataModel { Continent = "South America", Country = "Brazil", City = "Salvador", Id = 38 },
new DataModel { Continent = "South America", Country = "Argentina", City = "Buenos Aires", Id = 39 },
new DataModel { Continent = "South America", Country = "Peru", City = "Lima", Id = 40 },
new DataModel { Continent = "South America", Country = "Peru", City = "Cusco", Id = 41 },
new DataModel { Continent = "South America", Country = "Colombia", City = "Bogota", Id = 42 },
new DataModel { Continent = "South America", Country = "Bolivia", City = "La Paz", Id = 43 },
new DataModel { Continent = "South America", Country = "Venezuela", City = "Caracas", Id = 44 },
new DataModel { Continent = "South America", Country = "Chile", City = "Santiago", Id = 45 },
new DataModel { Continent = "Asia", Country = "China", City = "Hong Kong", Id = 46 },
new DataModel { Continent = "Asia", Country = "China", City = "Shanghai", Id = 47 },
new DataModel { Continent = "Asia", Country = "China", City = "Macau", Id = 48 },
new DataModel { Continent = "Asia", Country = "India", City = "Delhi", Id = 49 },
new DataModel { Continent = "Asia", Country = "India", City = "Hyderabad", Id = 50 },
new DataModel { Continent = "Asia", Country = "Japan", City = "Tokyo", Id = 51 },
new DataModel { Continent = "Asia", Country = "Japan", City = "Osaka", Id = 52 },
new DataModel { Continent = "Asia", Country = "Japan", City = "Kyoto", Id = 53 },
new DataModel { Continent = "Asia", Country = "Vietnam", City = "Ho Chi Minh", Id = 54 },
new DataModel { Continent = "Asia", Country = "Vietnam", City = "Hanoi", Id = 55 },
new DataModel { Continent = "Asia", Country = "Thailand", City = "Bangkok", Id = 56 },
new DataModel { Continent = "Asia", Country = "Thailand", City = "Phuket", Id = 57 },
new DataModel { Continent = "Africa", Country = "Nigeria", City = "Lagos", Id = 58 },
new DataModel { Continent = "Africa", Country = "Egypt", City = "Cairo", Id = 59 },
new DataModel { Continent = "Africa", Country = "Algeria", City = "Algiers", Id = 60 },
new DataModel { Continent = "Oceania", Country = "Australia", City = "Sydney", Id = 61 },
new DataModel { Continent = "Oceania", Country = "Australia", City = "Melbourne", Id = 62 },
new DataModel { Continent = "Oceania", Country = "Australia", City = "Canberra", Id = 63 },
new DataModel { Continent = "Oceania", Country = "New Zealand", City = "Auckland", Id = 64 },
new DataModel { Continent = "Oceania", Country = "New Zealand", City = "Wellington", Id = 65 },
};
}
public ObservableCollection<DataModel> Locations { get; set; }
}