DragDropManager can be used with any UI control to enable drag-drop capability in the application. Consider a scenario where you want to implement drag and drop operation between two ListBox controls. This walkthrough explains how you can use the DragDropManager to drag and drop items between two ListBox controls in an application.
The GIF below depicts the result:
To create this application, complete the following steps:
XAML |
Copy Code
|
---|---|
<Border Style="{StaticResource CE_SampleBkg}" Grid.Row="2" Background="#FFF1F1F1" BorderBrush="#FFCBD2DB" BorderThickness="1,0,1,1" /> <ListBox x:Name="_list1" Grid.Row="2" /> <Border Style="{StaticResource CE_SampleTitleBkg}" Background="#FFECEDED" Grid.Row="1" BorderThickness="1"> <TextBlock Text="Physics Class" Style="{StaticResource CE_SampleTitleText}" /> </Border> <Border Style="{StaticResource CE_SampleBkg}" Grid.Row="2" Background="#FFF1F1F1" Grid.Column="2" BorderBrush="#FFCBD2DB" BorderThickness="1,0,1,1" /> <ListBox x:Name="_list2" Grid.Row="2" Grid.Column="2" /> <Border Style="{StaticResource CE_SampleTitleBkg}" Background="#FFECEDED" Grid.Column="2" Grid.Row="1" BorderThickness="1"> <TextBlock Text="Mathematics Class" Style="{StaticResource CE_SampleTitleText}" /> </Border> |
XAML |
Copy Code
|
---|---|
<Window.Resources> <Style x:Key="ItemStyle" TargetType="Border"> <Setter Property="Height" Value="50" /> <Setter Property="Width" Value="50" /> <Setter Property="Margin" Value="5 5 10 5" /> <Setter Property="CornerRadius" Value="3" /> <Setter Property="BorderThickness" Value="2" /> <Setter Property="BorderBrush" Value="#FF8FB4CC" /> </Style> <SolidColorBrush x:Key="CE_SampleForeground" Color="#FFF0F8FE" /> <Style x:Key="CE_SampleText" TargetType="TextBlock"> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="TextWrapping" Value="Wrap" /> <Setter Property="Foreground" Value="#FFF0F8FE" /> <Setter Property="FontFamily" Value="Portable User Interface" /> <Setter Property="FontSize" Value="11" /> </Style> <Style x:Key="CE_SampleTextBkg" TargetType="Border"> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="1,0.5" StartPoint="0,0.5"> <GradientStop Color="#99071D2E" Offset="0.003" /> <GradientStop Color="#00071D2E" Offset="1" /> </LinearGradientBrush> </Setter.Value> </Setter> <Setter Property="CornerRadius" Value="2" /> <Setter Property="Height" Value="26" /> <Setter Property="Padding" Value="10 0 0 0" /> </Style> <Style x:Key="CE_SampleTitleBkg" TargetType="Border"> <Setter Property="BorderBrush" Value="#FFCBD2DB" /> <Setter Property="BorderThickness" Value="0,0,0,3" /> <Setter Property="Background"> <Setter.Value> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFE9ECF0" Offset="0" /> <GradientStop Color="#FFDDE1E7" Offset="0.2" /> <GradientStop Color="#FFCCD3DC" Offset="0.2" /> <GradientStop Color="#FFFAFAFB" Offset="0.647" /> </LinearGradientBrush> </Setter.Value> </Setter> </Style> <Style x:Key="CE_SampleTitleText" TargetType="TextBlock"> <Setter Property="HorizontalAlignment" Value="Left" /> <Setter Property="VerticalAlignment" Value="Center" /> <Setter Property="FontFamily" Value="Trebuchet MS" /> <Setter Property="FontSize" Value="16" /> <Setter Property="Foreground" Value="#FF507494" /> <Setter Property="TextWrapping" Value="NoWrap" /> <Setter Property="Margin" Value="10 5" /> </Style> <Style x:Key="CE_SampleBkg" TargetType="Border"> <Setter Property="Background" Value="#99071D2E" /> <Setter Property="BorderBrush" Value="#FF071D2E" /> <Setter Property="BorderThickness" Value="1" /> </Style> <DataTemplate x:Key="StudentTemplate"> <Grid Background="Transparent"> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="*" /> </Grid.ColumnDefinitions> <Border HorizontalAlignment="Left" VerticalAlignment="Center" Style="{StaticResource ItemStyle}"> <Grid> <Rectangle Stroke="#FF7E7E7E" RadiusY="1" Fill="White" RadiusX="1" /> <Rectangle Stroke="#FFABB1B3" RadiusY="1" Margin="3,3,3,9"> <Rectangle.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FFD7D7D7" /> <GradientStop Color="#FFFFFFFF" Offset="0.652" /> </LinearGradientBrush> </Rectangle.Fill> </Rectangle> <Path Stretch="Fill" Stroke="{x:Null}" Margin="4,6,4,10" Data="M17.60116,6.1738421E-05 C24.849646,0.023804173 26.683809,6.5920992 26.299255,12.14412 C25.308187,19.035593 23.641359,20.055075 22.426523,20.763863 C22.011572,22.301838 22.281172,23.129519 22.872089,23.413864 C25.789896,24.566036 28.26816,25.747917 31.26363,26.867565 C33.701267,28.11087 34.777184,28.794552 35.861771,29.767353 L38.065468,34.026146 C38.065468,34.026146 -2.0894244,33.953915 -2.0894244,33.953915 L0,29.600348 L0.0063374043,29.592121 C0.76684761,28.636683 2.0420403,27.542118 4.10077,26.985603 C8.0647907,25.539055 10.515559,24.379763 11.685194,23.874727 C12.629223,23.317556 13.257205,21.523518 12.521232,20.930931 C10.421399,19.15081 8.8502626,17.703053 8.3638849,11.022204 C7.883646,6.7073164 10.405101,-0.023508755 17.60116,6.1738421E-05 z"> <Path.Fill> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF516D7C" Offset="0.012" /> <GradientStop Color="#33516D7C" Offset="1" /> </LinearGradientBrush> </Path.Fill> </Path> <Path Fill="#3FFFFFFF" Stretch="Fill" Data="M0,0 L21.185122,0 C21.588734,0.12784213 21.858183,0.39503863 22,0.79480571 L22,24 C18.573542,13.458178 11.15755,5.5119557 0,0 z" HorizontalAlignment="Left" VerticalAlignment="Top" /> </Grid> </Border> <StackPanel Orientation="Horizontal" Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center"> <TextBlock Text="{Binding Name}" TextWrapping="Wrap" FontFamily="Arial" FontSize="12" VerticalAlignment="Top" Foreground="#FF222222" /> <TextBlock Text="{Binding Surname}" TextWrapping="Wrap" FontFamily="Arial" FontSize="12" VerticalAlignment="Top" Foreground="#FF222222" /> </StackPanel> </Grid> </DataTemplate> <Style TargetType="ListBox"> <Setter Property="Background" Value="Transparent" /> <Setter Property="BorderBrush" Value="{x:Null}" /> <Setter Property="Margin" Value="0,1,1,1" /> <Setter Property="ItemContainerStyle"> <Setter.Value> <Style TargetType="ListBoxItem"> <Setter Property="HorizontalContentAlignment" Value="Stretch" /> </Style> </Setter.Value> </Setter> </Style> </Window.Resources> |
Here we are using class, as a datasource, with the ListBox. Hence create a class by the name Person to populate ListBox with data.
C# |
Copy Code
|
---|---|
class Person { public string Name { get; set; } private static Random Randomizer = new Random(); public static List<Person> Generate(int qty) { var items = new List<Person>(); for (int i = 0; i < qty; i++) { items.Add(new Person() { Name = Names[Randomizer.Next(Names.Length)] + " " + Surnames[Randomizer.Next(Surnames.Length)], }); } return items; } private static string[] Names = new string[] { "Michael", "John", "Bernardo", "Alvaro", "Max", "Leonard", "Noela", "Gabriel", "Bruno", "Rodrigo", "Sheela", "Chris", "Martin", "Ben", "Alex", "Irina", "Dave", "Patric", }; private static string[] Surnames = new string[] { "Johnson", "Alvarez", "Maxtor", "Johansen", "Vera", "García", "Days", "Castle", "Varela", "Smith", "Gates", "Meredith", "Drexler", "Beckham", "Jobs", }; } |
C# |
Copy Code
|
---|---|
// create and initialize DragDropManager class C1DragDropManager _dd; _dd = new C1DragDropManager(); |
C# |
Copy Code
|
---|---|
// register drop targets foreach (ListBox lb in new ListBox[] { _list1, _list2 }) { _dd.RegisterDropTarget(lb, true); foreach (Person p in Person.Generate(5)) { var personElement = new ContentPresenter(); personElement.Content = p; personElement.ContentTemplate = (DataTemplate)Resources["StudentTemplate"]; lb.Items.Add(personElement); _dd.RegisterDragSource(personElement, DragDropEffect.Move, ModifierKeys.None); // Set a distance for the mouse to move before a drag operation starts _dd.DragThreshold = 5; personElement.MouseDown += (s, e) => { // _dd is the first to get the event. // Then we mark it handled to inhibit ListBox selection stealing _dd's mouse capture. e.Handled = true; }; } } |
C# |
Copy Code
|
---|---|
// handle the drops
_dd.DragDrop += _dd_DragDrop;
|
C# |
Copy Code
|
---|---|
void _dd_DragDrop(object source, DragDropEventArgs e) { // get object being dragged UIElement sourceElement = e.DragSource; // get source parent, target listboxes ListBox sourceParent = _list1.Items.Contains(sourceElement) ? _list1 : _list2; ListBox target = e.DropTarget as ListBox; // get index into target int index = GetDropIndex(e, target); // adjust index if (sourceParent == target) { int sourceIndex = sourceParent.Items.IndexOf(sourceElement); if (index > sourceParent.Items.IndexOf(sourceElement)) { index--; } if (index == sourceIndex) return; } // remove from original position, insert into new position sourceParent.Items.Remove(sourceElement); target.Items.Insert(index, sourceElement); } #region ** utility // get drop location within a ListBox public static int GetDropIndex(DragDropEventArgs e, ListBox target) { int index = 0; foreach (UIElement child in target.Items) { Point p = e.GetPosition(child); if (p.Y - child.DesiredSize.Height / 2 < 0) break; index++; } return index; } } |
Drag an item from one ListBox and drop to the other ListBox, and vice-versa hence it concludes the walkthrough for implementing drag-drop feature with ListBoxes in applications.