Drag And Drop Item in ListBox in WPF
아래와 같이 두개의 ListBox 를 배치한다.
<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>
DragDrop 을 구현하기 위해 데이터를 Drag 할 ListBox 에서는 PreviewMouseLeftButtonDown 이벤트 핸들러를 정의해 주어야 한다. Drop 할 목적지 ListBox 에서는 AllowDrop 프로퍼티를 True 로 설정하고, Drop 이벤트 핸들러를 정의해주어야 한다.
PreviewMouseLeftButtonDown
마우스 포인터가 ListBox 위에 있을 때 마우스 왼쪽 버튼을 클릭하면 발생하는 이벤트
AllowDrop
이 요소를 끌어서 놓기 작업의 대상으로 사용할 수 있는지 여부를 나타내는 값을 가져오거나 설정.
기본값은 false 이다.
Drop
해당 요소에(ListBox) 아이템을 끌어다 놓았을 때 발생하는 이벤트
첫 번째 ListBox 에 테스트할 데이터를 넣는다. TimeZoneInfo 클래스로 부터 TimeZones 리스트를 넣어 준다.
public Window1()
{
InitializeComponent();
foreach (TimeZoneInfo tzi in TimeZoneInfo.GetSystemTimeZones())
{
zoneList.Add(tzi.ToString());
}
lbxOne.ItemsSource = zoneList;
}
PreviewMouseLeftButtonDown 이벤트 핸들러 구현 코드는 다음과 같다. GetDataFromListBox 메소드를 눈여겨 보자
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);
}
예제 소스