ListBox Item Drag and Drop
The Telerik Blazor ListBox allows users to drag and drop items within the same component instance or across different instances. This is a more flexible alternative to reordering or moving ListBox items with toolbar buttons. As a result, dragging and dropping can be a lot faster and convenient to users when the number of related ListBoxes is three or more.
Configuration
To enable drag and drop between ListBox components:
- Set
Draggable="true"
to all of them. - Set
DropSources
to theId
values of the permitted source ListBoxes. - Subscribe to the
OnDrop
event of each ListBox that users can drag items from. TheOnDrop
event always fires from the source (origin) ListBox instance. -
Rebind()
each ListBox after making programmatic changes to itsData
.
Example
@* Drag and drop items between ListBoxes *@
<TelerikListBox @ref="@ListBoxRef1"
Data="@ListBoxData1"
TextField="@nameof(ListBoxModel.Name)"
Id="@ListBoxId1"
SelectionMode="@ListBoxSelectionMode.Multiple"
@bind-SelectedItems="@ListBoxSelectedItems1"
Draggable="true"
DropSources="@ListBoxDropSources"
OnDrop="( (ListBoxDropEventArgs<ListBoxModel> args) =>
OnListBoxDrop(args, ListBoxId1, ListBoxData1) )">
<ListBoxToolBarSettings>
<ListBoxToolBar Visible="false" />
</ListBoxToolBarSettings>
</TelerikListBox>
<TelerikListBox @ref="@ListBoxRef2"
Data="@ListBoxData2"
TextField="@nameof(ListBoxModel.Name)"
Id="@ListBoxId2"
SelectionMode="@ListBoxSelectionMode.Multiple"
@bind-SelectedItems="@ListBoxSelectedItems2"
Draggable="true"
DropSources="@ListBoxDropSources"
OnDrop="( (ListBoxDropEventArgs<ListBoxModel> args) =>
OnListBoxDrop(args, ListBoxId2, ListBoxData2) )">
<ListBoxToolBarSettings>
<ListBoxToolBar Visible="false" />
</ListBoxToolBarSettings>
</TelerikListBox>
<TelerikListBox @ref="@ListBoxRef3"
Data="@ListBoxData3"
TextField="@nameof(ListBoxModel.Name)"
Id="@ListBoxId3"
SelectionMode="@ListBoxSelectionMode.Multiple"
@bind-SelectedItems="@ListBoxSelectedItems3"
Draggable="true"
DropSources="@ListBoxDropSources"
OnDrop="( (ListBoxDropEventArgs<ListBoxModel> args) =>
OnListBoxDrop(args, ListBoxId3, ListBoxData3) )">
<ListBoxToolBarSettings>
<ListBoxToolBar Visible="false" />
</ListBoxToolBarSettings>
</TelerikListBox>
@code {
private TelerikListBox<ListBoxModel> ListBoxRef1 { get; set; } = null!;
private TelerikListBox<ListBoxModel> ListBoxRef2 { get; set; } = null!;
private TelerikListBox<ListBoxModel> ListBoxRef3 { get; set; } = null!;
private const string ListBoxId1 = "listbox1";
private const string ListBoxId2 = "listbox2";
private const string ListBoxId3 = "listbox3";
private List<string> ListBoxDropSources => new List<string>() { ListBoxId1, ListBoxId2, ListBoxId3 };
private List<ListBoxModel> ListBoxData1 { get; set; } = new List<ListBoxModel>();
private List<ListBoxModel> ListBoxData2 { get; set; } = new List<ListBoxModel>();
private List<ListBoxModel> ListBoxData3 { get; set; } = new List<ListBoxModel>();
private IEnumerable<ListBoxModel> ListBoxSelectedItems1 { get; set; } = new List<ListBoxModel>();
private IEnumerable<ListBoxModel> ListBoxSelectedItems2 { get; set; } = new List<ListBoxModel>();
private IEnumerable<ListBoxModel> ListBoxSelectedItems3 { get; set; } = new List<ListBoxModel>();
private void OnListBoxDrop(
ListBoxDropEventArgs<ListBoxModel> args,
string sourceListBoxId,
List<ListBoxModel> sourceData)
{
var destinationIndex = args.DestinationIndex ?? 0;
var destinationData = GetListBoxDataFromId(args.DestinationListBoxId);
if (args.DestinationListBoxId == sourceListBoxId)
{
ReorderItems(args.Items, sourceData, destinationIndex);
}
else
{
MoveItems(args.Items, sourceData, destinationData, destinationIndex);
}
ListBoxRef1.Rebind();
ListBoxRef2.Rebind();
ListBoxRef3.Rebind();
}
private void ReorderItems(
List<ListBoxModel> items,
List<ListBoxModel> collection,
int destinationIndex)
{
collection.RemoveAll(x => items.Contains(x));
if (destinationIndex >= 0)
{
collection.InsertRange(destinationIndex, items);
}
else
{
collection.AddRange(items);
}
}
private void MoveItems(
List<ListBoxModel> items,
List<ListBoxModel> sourceData,
List<ListBoxModel> destinationData,
int destinationIndex)
{
foreach (var item in items)
{
sourceData.RemoveAll(x => items.Any(y => y.Id == x.Id));
if (destinationIndex >= 0)
{
destinationData.Insert(destinationIndex, item);
}
else
{
destinationData.Add(item);
}
}
}
private List<ListBoxModel> GetListBoxDataFromId(string listBoxId)
{
var collection = new List<ListBoxModel>();
switch (listBoxId)
{
case ListBoxId1:
collection = ListBoxData1;
break;
case ListBoxId2:
collection = ListBoxData2;
break;
case ListBoxId3:
collection = ListBoxData3;
break;
default:
break;
}
return collection;
}
protected override void OnInitialized()
{
for (int i = 1; i <= 5; i++)
{
ListBoxData1.Add(new ListBoxModel()
{
Id = i,
Name = $"Foo {i}"
});
}
for (int i = 101; i <= 103; i++)
{
ListBoxData2.Add(new ListBoxModel()
{
Id = i,
Name = $"Bar {i}"
});
}
}
public class ListBoxModel
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
}
}