Перетаскивание элемента в список ListBox в WPF

Автор: Диптимая Патра (Diptimaya Patra)

В этой статье будет показано, как обеспечить поведение перетаскивания для значения ListBox.

Создание проекта WPF

Запустите Visual Studio 2008 и создайте новый проект WPF. Назовите его DragDropListBoxSample.

Основная идея нашего приложения-примера — использование двух списков ListBox и перетаскивание элемента из первого списка ListBox во второй список ListBox.

Поэтому создадим два списка ListBox и назовем эти списки ListBox как lbOne и lbTwo.

Ниже приведен принципиальный макет внешнего вида приложения.

Здесь мы заполним первый список ListBox. Список часовых поясов из класса TimeZoneInfo.

ObservableCollection<string> zoneList = new ObservableCollection<string>(); 
public Window1() 
{ 
InitializeComponent(); 
foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones()) 
{ 
zoneList.Add(tzi.ToString()); 
} 
lbOne.ItemsSource = zoneList; 
}

Как видно, первый список Listbox заполнен всеми часовыми поясами.

Теперь, чтобы реализовать перетаскивание, нужно установить AllowDrop="True" для конечного списка ListBox, нам также понадобится события для списков ListBox: событие PreviewMouseLeftButtonDown для списка-источника и событие Drop для списка-получателя.

Соответствующие события и свойства приведены в следующем XAML-коде.

<Window x:Class="DragDropListBoxSample.Window1"
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Title="Drag And Drop ListBox Item" Height="300" Width="529">
  <Grid>
  <ListBox x:Name="lbOne" PreviewMouseLeftButtonDown="ListBox_PreviewMouseLeftButtonDown"
   HorizontalAlignment="Left" Margin="12,29,0,12" Width="215"
   ScrollViewer.VerticalScrollBarVisibility="Visible" />
  <ListBox x:Name="lbTwo" Drop="ListBox_Drop" AllowDrop="True"
    HorizontalAlignment="Right" Margin="0,29,12,12" Width="215"
   ScrollViewer.VerticalScrollBarVisibility="Visible"/>
  <TextBlock Height="21" Text="ListBox One" HorizontalAlignment="Left"
   Margin="12,2,0,0" VerticalAlignment="Top" Width="120" />
  <TextBlock Height="21" Text="ListBox Two" HorizontalAlignment="Right"
   Margin="0,2,107,0" VerticalAlignment="Top" Width="120" />
  </Grid>
</Window>

Теперь введем код обработчика событий ListBox_PreviewMouseLeftButtonDown.
ListBox dragSource = null;

ListBox dragSource = null;
private void ListBox_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
  {
  ListBox parent = (ListBox)sender;
  dragSource = parent;
   object data = GetDataFromListBox(dragSource, e.GetPosition(parent));
  if (data != null)
  {
  DragDrop.DoDragDrop(parent, data, DragDropEffects.Move);
  }
  }
#region GetDataFromListBox(ListBox,Point)
  private static object GetDataFromListBox(ListBox source, Point point)
  {
  UIElement element = source.InputHitTest(point) as UIElement;
  if (element != null)
  {
  object data = DependencyProperty.UnsetValue;
  while (data == DependencyProperty.UnsetValue)
  {
  data = source.ItemContainerGenerator.ItemFromContainer(element);
  if (data == DependencyProperty.UnsetValue)
   {
  element = VisualTreeHelper.GetParent(element) as UIElement;
  }
    
  if (element == source)
  {
    
  return null;
  }
    
   }
  if (data != DependencyProperty.UnsetValue)
  {
  return data;
  }
  }
  return null;
  }
    
#endregion

Теперь введем код обработчика событий ListBox_Drop.

private void ListBox_Drop(object sender, DragEventArgs e)
{
  ListBox parent = (ListBox)sender;
  object data = e.Data.GetData(typeof(string));
  ((IList)dragSource.ItemsSource).Remove(data);
  parent.Items.Add(data);
        
}

Теперь запустим приложение и перетащим приложение из первого списка ListBox во второй список ListBox. Функциональная возможность перетаскивания реализована.

Надеюсь, что эта статья окажется полезной.