출처 : http://social.msdn.microsoft.com/Forums/en/wpf/thread/d32bb0af-b14f-4e88-ad36-098d11cd375c
WPF의 StackPanel 컨트롤에 들어있는 아이템들에 Drag and Drop 기능을 입혀 보겠습니다.
1. StackPanel을 만들고 AllowDrop 속성 및 마우스 이벤트를 등록 합니다.
테스트를 위해 TextBlock 아이템을 넣어 놓았습니다.
<StackPanel x:Name="Container" Orientation="Vertical"
HorizontalAlignment="Stretch"
AllowDrop="True"
PreviewMouseLeftButtonDown="Container_PreviewMouseLeftButtonDown"
PreviewMouseLeftButtonUp="Container_PreviewMouseLeftButtonUp"
PreviewMouseMove="Container_PreviewMouseMove"
Drop="Container_Drop">
<TextBlock Text="1번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Red"/>
<TextBlock Text="2번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Blue"/>
<TextBlock Text="3번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Yellow"/>
<TextBlock Text="4번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Beige"/>
</StackPanel>
HorizontalAlignment="Stretch"
AllowDrop="True"
PreviewMouseLeftButtonDown="Container_PreviewMouseLeftButtonDown"
PreviewMouseLeftButtonUp="Container_PreviewMouseLeftButtonUp"
PreviewMouseMove="Container_PreviewMouseMove"
Drop="Container_Drop">
<TextBlock Text="1번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Red"/>
<TextBlock Text="2번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Blue"/>
<TextBlock Text="3번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Yellow"/>
<TextBlock Text="4번" FontSize="20" HorizontalAlignment="Stretch" TextAlignment="Center" Background="Beige"/>
</StackPanel>
2. Behind Code에 추가된 이벤트 함수에 Drag and Drop에 필요한 변수를 등록 합니다.
private bool _isDown; // 마우스 클릭 체크
private bool _isDragging; // 컨트롤을 드레깅 하는지 체크
private Point _startPoint; // Drag 하는 아이템의 시작 위치
private UIElement _realDragSource;
private UIElement _dummyDragSource = new UIElement();
private bool _isDragging; // 컨트롤을 드레깅 하는지 체크
private Point _startPoint; // Drag 하는 아이템의 시작 위치
private UIElement _realDragSource;
private UIElement _dummyDragSource = new UIElement();
3. 마우스를 클릭 했을때 StackPanel 안에 있는 자식 컨트롤을 선택 하는지 체크 하는 코드를 입력 합니다.
private void Container_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Source == this.Container)
{
}
else
{
_isDown = true;
_startPoint = e.GetPosition(this.Container);
}
}
{
if (e.Source == this.Container)
{
}
else
{
_isDown = true;
_startPoint = e.GetPosition(this.Container);
}
}
4. 마우스를 땠을때 변수를 초기화 시켜 주는 코드를 입력 합니다.
private void Container_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
_isDown = false;
_isDragging = false;
if (_realDragSource != null)
{
_realDragSource.ReleaseMouseCapture();
}
}
{
_isDown = false;
_isDragging = false;
if (_realDragSource != null)
{
_realDragSource.ReleaseMouseCapture();
}
}
5. 컨트롤을 드레깅 하는동안 위치를 확인 하는 코드를 입력 합니다.
private void Container_PreviewMouseMove(object sender, MouseEventArgs e)
{
if (_isDown)
{
if ((_isDragging == false) && ((Math.Abs(e.GetPosition(this.Container).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(this.Container).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
{
_isDragging = true;
_realDragSource = e.Source as UIElement;
_realDragSource.CaptureMouse();
DragDrop.DoDragDrop(_dummyDragSource, new DataObject("UIElement", e.Source, true), DragDropEffects.Move);
}
}
}
{
if (_isDown)
{
if ((_isDragging == false) && ((Math.Abs(e.GetPosition(this.Container).X - _startPoint.X) > SystemParameters.MinimumHorizontalDragDistance) ||
(Math.Abs(e.GetPosition(this.Container).Y - _startPoint.Y) > SystemParameters.MinimumVerticalDragDistance)))
{
_isDragging = true;
_realDragSource = e.Source as UIElement;
_realDragSource.CaptureMouse();
DragDrop.DoDragDrop(_dummyDragSource, new DataObject("UIElement", e.Source, true), DragDropEffects.Move);
}
}
}
6. 컨트롤을 Drop 시켰을때 컨트롤들의 순서를 바꿔주는 코드를 입력합니다.
private void Container_Drop(object sender, DragEventArgs e)
{
if (e.Data.GetDataPresent("UIElement"))
{
UIElement droptarget = e.Source as UIElement;
int droptargetIndex = -1, i = 0;
{
if (element.Equals(droptarget))
{
droptargetIndex = i;
break;
}
i++;
}
{
if (e.Data.GetDataPresent("UIElement"))
{
UIElement droptarget = e.Source as UIElement;
int droptargetIndex = -1, i = 0;
foreach (UIElement element in this.Container.Children)
{
if (element.Equals(droptarget))
{
droptargetIndex = i;
break;
}
i++;
}
if (droptargetIndex != -1)
{
this.Container.Children.Remove(_realDragSource);
this.Container.Children.Insert(droptargetIndex, _realDragSource);
}
_isDragging = false;
_realDragSource.ReleaseMouseCapture();
}
}
{
this.Container.Children.Remove(_realDragSource);
this.Container.Children.Insert(droptargetIndex, _realDragSource);
}
_isDown = false;
_isDragging = false;
_realDragSource.ReleaseMouseCapture();
}
}
샘플 다운로드 :StackPanelDragAndDrop.zip
'Programming > WPF' 카테고리의 다른 글
[WPF] ControlTemplate Examples (0) | 2013.01.31 |
---|---|
[WPF, Silverlight] Behind Code에서 Binding 구현하기 (0) | 2012.10.19 |
[WPF, Silverlight] UserControl의 Binding에 필요한 DependencyProperty 생성하기 (0) | 2012.10.19 |
[WPF, Silverlgiht, Windows 8] MVVM Light Toolkit (0) | 2012.07.17 |
[WPF] DataGrid에 마우스 더블 클릭 이벤트 주기 (0) | 2012.06.19 |
[WPF] DataGrid Row에 마우스 더블 클릭 이벤트 주기 (0) | 2012.06.19 |