Telerik blogs

Introduction

Sometimes you want to move items from one list to another.  A traditional way to do so is to lay the two list boxes out side by side with buttons in between. The buttons are used to move the selected item from one list to the other.

DragDropNot

 

It works, but it isn’t as user friendly as drag and drop. 

 

DragDrop

On the other hand, Microsoft’s out of the box ListBox doesn’t have Drag and Drop support. 

Adding Drag and Drop

Telerik provides the DragDropManager class to simplify Drag and Drop operations in WPF. They included ListBoxDragDrop Behavior so that you can drag and drop items between standard Microsoft ListBox controls.

This blog post will demonstrate how to add Drag and Drop behavior to ListBox controls with Telerik’s help.

It Starts, As Always, With Data

We’ll need some simple data to move between the Red Team and the Blue Team.  To make this work, we’ll start by creating a Person class,

public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public int Age { get; set; }
}

We’ll next create a ViewModel, as good programming practice,  to associate with the MainPage view (not yet created).  The job of the ViewModel is to provide the properties to which the View will bind.  As a secondary job, the View Model will stand in for the database or web service which would normally provide our data.  In this case, we’ll just hand code the creation of a couple collections of Person objects.

To get started, we create two private members, each a collection of Person,  which will be populated by helper methods,

public class MainViewModel
{
private ObservableCollection<Person> flintstones =
GenerateFlintstones();
private ObservableCollection<Person> jetsons =
GenerateJetsons();

 

public ObservableCollection<Person> Flintstones
{
get { return flintstones; }
set { flintstones = value; }
}

public ObservableCollection<Person> Jetsons
{
get { return jetsons; }
set { jetsons = value; }
}

The helper methods just create a few Person objects for each collection,

private static ObservableCollection<Person> GenerateFlintstones()
{
var people = new ObservableCollection<Person>();
people.Add( new Person() { FirstName = "Fred",
LastName = "Flintstone", Age = 30 } );
people.Add( new Person() { FirstName = "Wilma",
LastName = "Flintstone", Age = 25 } );
people.Add( new Person() { FirstName = "Pebbles",
LastName = "Flintstone", Age = 2 } );
people.Add( new Person() { FirstName = "Barney",
LastName = "Rubble", Age = 29 } );
people.Add( new Person() { FirstName = "Betty",
LastName = "Rubble", Age = 24 } );
people.Add( new Person() { FirstName = "BammBamm",
LastName = "Rubble", Age = 2 } );
return people;
}

private static ObservableCollection<Person> GenerateJetsons()
{
var people = new ObservableCollection<Person>();
people.Add( new Person() { FirstName = "George",
LastName = "Jetson", Age = 40 } );
people.Add( new Person() { FirstName = "Jane",
LastName = "Jetson", Age = 33 } );
people.Add( new Person() { FirstName = "Judy",
LastName = "Jetson", Age = 15 } );
people.Add( new Person() { FirstName = "Elroy",
LastName = "Jetson", Age = 6 } );
return people;
}

Creating the View

With that data ready, we can create MainWindow.xaml.  The first thing we need to do is to add a local namespace to refer to the program itself,

xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation"
xmlns:local="clr-namespace:DragDropListBoxes"

We’ll use that namespace to create an instance of our ViewModel class as a local resource in XAML,

<Window.Resources>
<local:MainViewModel x:Key="ViewModel" />
</Window.Resources>

This in turn will be used as the ItemsSource for the ListBoxes, as shown below.

We’ll start with a grid with two columns and two rows,

<Grid x:Name="LayoutRoot"
Width="700"
Height="450">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>

 

In the first row we’ll place a couple labels (TextBlocks), one for each ListBox,

<TextBlock Text="Red Team"
FontSize="24"
Foreground="Red" />
<TextBlock Grid.Column="1"
Text="Blue Team"
FontSize="24"
Foreground="Blue" />

Now comes the fun part, creating the ListBoxes.

The first ListBox is for the RedTeam.  It will bind to the Flintstones collection.  Notice the property AllowDrop is set to True,

<ListBox x:Name="RedTeam"
Grid.Row="1"
Margin="0,0,3,0"
ItemsSource="{Binding Flintstones,
Source={StaticResource ViewModel}}"
AllowDrop="True"
Background="Transparent"
telerik:TouchManager.IsTouchHitTestVisible="True">

Notice the last property; we effectively extend the ListBox with the TouchManager class’s IsTouchHitTestVisible property which we set to true. 

We next set the ListBox’s DataTemplate. We want to format the contents of the two ListBoxes differently (see illustration above).  The first list box will have a DataTemplate that specifies two rows. The first name will be bolded in the first row, and the last name will be in the second row.

 <ListBox.ItemTemplate>
<DataTemplate>
<Grid Width="150">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0"
Text="{Binding FirstName}"
FontWeight="Bold"
HorizontalAlignment="Center"
Foreground="#FF767676" />
<TextBlock Text="{Binding LastName}"
Grid.Row="1"
HorizontalAlignment="Center"
Foreground="#FF767676" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>

 

Next we set the ItemContainerStyle for the ListBox.  This gives us the opportunity to add three properties of the Telerik DragDropManager class:

  • AllowDrag
  • AllowCapturedDrag
  • TouchDragTrigger

The first two are set to true, the third to TapAndHold,

<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalAlignment"
Value="Stretch" />
<Setter Property="HorizontalContentAlignment"
Value="Stretch" />
<Setter Property="Foreground"
Value="#000000" />
<Setter Property="telerik:DragDropManager.AllowDrag"
Value="True" />
<Setter Property="telerik:DragDropManager.
AllowCapturedDrag"
Value="True" />
<Setter Property="telerik:DragDropManager.
TouchDragTrigger"
Value="TapAndHold" />
</Style>
</ListBox.ItemContainerStyle>

 

Finally, and perhaps most important, we add the ListBoxDragDrop behavior to implement Drag and drop,

<telerik:ListBoxDragDrop.Behavior>
<telerik:ListBoxDragDropBehavior />
</telerik:ListBoxDragDrop.Behavior>

 

The markup for the Blue Team is nearly identical, except that the DataTemplate lays out the ListBox entries somewhat differently.  For example,  the Blue Team ListBox has an ItemsPanel property which uses a RadUniformGrid to lay each ListBox item out in four columns,

<ListBox.ItemsPanel>
<ItemsPanelTemplate>
<telerik:RadUniformGrid Columns="4"
HorizontalAlignment="Left"
VerticalAlignment="Top" />
</ItemsPanelTemplate>
</ListBox.ItemsPanel>

 

You can see the effect of this most clearly by dragging and dropping most of the people from the Red Team onto the Blue Team,

DragDropColumns

What, No Code?

That’s all it takes. There is no supporting C# code for Drag and Drop; all the magic is done for you by Telerik.

As shown here when you drag from one window to the other you get a generic drag indicator.  You can customize the indicator to show what is being dragged, and I’ll show that in an upcoming blog post.

 

This post is inspired by Carey Payette’s Extending RadGridView to Enable Row Drag and Drop Functionality. Thanks to Phil Japikse for the idea of using the Flintstones.

 

About the author

Jesse Liberty

Jesse Liberty

Jesse Liberty is a Technical Evangelist for Telerik and has three decades of experience writing and delivering software projects. He is the author of 2 dozen books as well as courses on Pluralsight on Windows 8 and WPF. Jesse has been a Distinguished Software Engineer for AT&T and a VP for Information Services for Citibank and a Software Architect for PBS. You can read more on his personal blog and his Telerik blog or follow him on twitter


jesseLiberty
About the Author

Jesse Liberty

 has three decades of experience writing and delivering software projects. He is the author of 2 dozen books and has been a Distinguished Software Engineer for AT&T and a VP for Information Services for Citibank and a Software Architect for PBS. You can read more on his personal blog or follow him on twitter

Comments

Comments are disabled in preview mode.